Struts2中OGNL

浅析值栈
ValueStack对象
相当于一个,它贯穿整个Action的生命周期,每个Action类的对象实例都会拥有一个ValueStack对象
当Struts2接收到一个*.action请求后,并不是直接调用Action方法,而是先将Action类的相应属性放到ValueStack对象的顶层节点
值栈也位于内存中
,它也是和parametersrequestsessionapplicationattr对象放在一起的
值栈属于ONGL Context里面的根对象。也就是说它位于整个内存中最最重要的地方,所以叫根对象
根对象和另外五个对象是有区别的,根对象可以省写#号,比如<s:propertyvalue="user.username"/>
值栈的生命周期与request请求相关,每次请求产生一个值栈。默认所有的Action会被自动放到值栈里

 

服务器跳转时共用值栈
假设从一个Action11通过服务器跳转到Action22的话,就意味着这两个Action是共享一个值栈的,因为一次请求只使用一个值栈
这时内存中情况是这样的:首先接收到Action11请求后,会产生一个值栈,在栈顶存放Action11对象以及它所有的属性
然后经过服务器跳转到Action22,这时就会把Action22对象压入值栈的栈顶位置,此时Action11对象以及它的所有属性就位于栈底了

 

取值过程
栈的特征是后进先出。于是首先到栈顶的对象里查找是否存在这个属性,如果栈顶的Action22对象中不存在这个属性的话
它就会继续向下寻找直至栈底对象,一直查找是否存在这个属性
如果最后找到该属性的话,那么就会在JSP页面中通过<s:propertyvalue="username"/>输出属性值
如果在Action22和Action11都有一个同名的同类型的username属性的话,那么将输出Action22中的属性值
因为它是先从栈顶开始寻找属性的,值栈的特征就是后进先出,但有个前提:请求过程是通过服务器跳转的

 

三个语法
假设此时想要获取Action11中的username属性的话,就可以使用值栈的Top语法或者N语法
使用Top语法
获取值栈中的第二个对象的属性:<s:property value="[1].top.username"/>
使用 N 语法
获取值栈中的第二个对象的属性:<s:propertyvalue="[1].username"/>
另外值栈还有一个@语法,例如使用@语法调用Action中的静态方法:<s:property value="@vs@getVOMethod()"/>
@vs@get()等价于@vs1@getVOMethod()
,指的是栈顶对象的静态getVOMethod()方法
同理@vs2@getVOMethod()就是取值栈中第二个对象的静态getVOMethod()方法

 

客户端跳转时使用各自的值栈
假如中间某一个步骤中出现了客户端跳转的话,那么两个Action所使用的就是两个不同的值栈了
所以在Action22中就不能再使用Action11中的属性了,在最后跳转到的JSP页面中也就无法获取Action11的属性了
也即从Action22跳转到JSP页面时使用的是redirect的话,那么最后值栈中是没有任何的Action对象的
这个时候我们可以通过链接传参,比如<result type="redirect">test.jsp?netname=${username}</result>
意思就是取出Action22中的username属性作为参数,通过浏览器地址栏传递到JSP页面中
然后使用OGNL中的#获取Paraments对象的属性,即<s:propertyvalue="#parameters.netname"/>就可以取到值了

 

手工向值栈中压入对象
正常情况下值栈保存的是Action对象,而我们也可以直接往值栈中添加其它对象,这时可以在Action中添加如下代码
向值栈中添加对象:ActionContext.getContext.getValueStack().push(new Student("沈浪",22));
而且我们手工往值栈中添加的Student对象会位于栈顶。这是因为Struts2会首先初始化Action,然后才能调用它的方法
初始化Action的时候,便把Action放到值栈中了,然后在执行它的execute()方法时,就又往值栈中添加了Student对象

 

浅析OGNL
OGNL是Object-GraphNavigation Language的缩写,是一种功能强大的表达式语言
通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能
OGNL用得最多的地方就是和Struts2的标签绑定,也可以在配置文件中通过${}使用OGNL表达式

 

OGNL$号的使用
1..
在国际化资源文件中,引用OGNL表达式
2..在struts.xml文件中,引用OGNL表达式

 

OGNL%号的使用
1..
使用%{}可以取出保存在值堆栈中的Action对象,直接调用它的方法
2..如果Action继承了ActionSupport,那么在页面标签中可以使用%{getText('key')}获取国际化信息

 

OGNL#号的使用
OGNL中的#号可以取出堆栈上下文中存放的对象

名称

作用

例子

attr

用于按request>>session>>application顺序访问其属性

#attr.userName相当于按顺序从三个范围读取userName属性直到找到为止

request

包含当前HttpServletRequest的属性的Map

#request.userName相当于request.getAttribute("userName")

session

包含当前HttpSession的属性的Map

#session.userName相当于session.getAttribute("userName")

application

包含当前应用的ServletContext的属性的Map

#application.userName相当于application.getAttribute("userName")

parameters

包含当前HTTP请求参数的Map

#parameters.id[0]相当于request.getParameter("id")

 

获取Action中的属性值或者Action中的对象的某某属性值
利用<s:property/>标签可以直接获取Action中的引用类型user里面的username属性
同样可以通过user.address.addr获取user中引用类型address中的addr属性的值
像这种一层一层往下传递的访问方式,即所谓的导航,也就是一步步的往下调用

 

调用Action的对象里面的普通方法
默认的会把Action放到值栈里面,而值栈在访问的时候,并不需要值栈的名字
当我们调用<s:propertyvalue="user.getVOMethod()"/>的时候
它会自动到值栈里面查找Action对象里面有没有user对象,然后它就发现有user
然后它就再找user里面有没有getVOMethod()方法,然后它发现有,于是调用getVOMethod()
实际上调用User中的getVOMethod()方法的过程与获取表单中的姓名密码的方式都是相同的
都是到值栈里面查找,找是否存在user对象,如果存在,接着查找user中是否存在某某属性或方法

 

调用Action中的静态方法
同样我们也可以在JSP页面中写一个OGNL表达式调用Action中的静态方法
调用Action中的静态方法时,与调用user对象的getVOMethod()方法的过程,是截然不同的
此时value的写法是固定的,以@开头,后面跟上具体的包名,然后@加上静态方法
比如<s:propertyvalue="@com.jadyer.action.LoginAction@getStatic()"/>
另外user对象是LoginAction中的一个属性,这个属性会自动的放到值栈里面
而值栈调用的时候,不用加上@或者包名等等,所以直接user.getVOMethod()就可以了

 

调用JDK类中的静态方法
可以使用<s:propertyvalue="@@floor(46.58)"/>输出floor()的执行结果
这就意味着如果不在@@中指定类的话,默认的就表示java.lang.Math
当前大多数情况下,我们都不会省略这个类,都会写全了的,然后在后面加上静态方法

 

集合的伪属性
OGNL能够引用集合的一些特殊的属性,这些属性并不是JavaBean模式,例如size()、length()
当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性
比如获取List的大小:<s:propertyvalue="testList.size"/>
      List的伪属性:
size、isEmpty、iterator
       Set的伪属性:size、isEmpty、iterator
       Map的伪属性:size、isEmpty、keys、values
  Iterator的伪属性:next、hasNext
Enumeration伪属性:next、hasNext、nextElement、hasMoreElements

 

获取集合中元素的实质就是调用它的toString()方法
它还可以直接获取集合中的元素,事实上是在调用集合的toString()方法
所以我们可以根据实际情况通过重写集合的toString()方法来实现个性化输出
甚至它还可以像访问数组那样,直接testList[2]获取集合中的元素
但这种方法只适用于List,不适用于Map。因为Map的索引是key,不是数值
另外,由于HashSet中的元素是没有顺序的,所以也不能用下标获取单个元素

 

Lambda表达式
补充一下:使用Lambda表达式可以在OGNL中书写递归式子,在帮助中对它有很详细的说明
打开帮助中的//struts-2.0.14-all//struts-2.0.14//docs//index.html页面
在左侧的Documentation下面点击Guides链接,然后在这个页面中点击OGNL
最后跳转到//struts-2.0.14-all//struts-2.0.14//docs//docs//ognl.html
将这个页面右侧的下拉条拖放到最下面,就会看到它的说明了,它举的例子如下所示
<s:property value="#fib =:[#this==0? 0 : #this==1 ? 1 : #fib(#this-2)+#fib(#this-1)], #fib(11)" />
Lambda表达式的语法是:[...] ,中括号前面有一个冒号,所有东西都在中括号里面写
也就是说我们只要看到一个冒号跟着一个中括号,就表示这里使用的是Lambda表达式
#this指的是表达式的参数
所以这个例子可以这样理解:先判断这个参数是否等于零,如果等于零,那么它的值最后就是零
如果参数不等于零,就再判断它是否等于壹。如果参数等于壹,那么它的值最后就是壹
如果参数不等于壹,就继续调用#fib。注意这里已经用中括号将整体的值赋给了fib
实际上很少能够用得到Lambda表达式

 

利用投影获取属性
利用投影获取List中对象的username属性时,其中{}表示的是一个集合
stus.{username}就表示将suts中所有的username属性取出组成一个新的列表

 

利用选择获取属性
OGNL表达式是很灵活的,可以同时使用选择技术投影技术获取属性
使用选择技术时,#this代表当前元素,问号?是把所有满足条件的元素都取出来
上箭头^是开始的意思,所以stus.{^#this.grade>=60}.{username}输出的是[张三]
注意,此时输出文本中包含中括号,这表示它是一个列表
stus.{?#this.grade>=60}.{username}[0]输出的是张三,是字符串,二者是不同的
美元符号$是结束的意思,所以stus.{$#this.grade>=60}.{username}输出的是[王五]
这三个符合:问号、上箭头、美元符所返回的都是List

 

补充
1..
当OGNL取不到值的时候,它不会报错,而是什么都不显示
2..<s:property value="[0]"/>返回的是ValueStack中从上至下的所有的Object
    <s:propertyvalue="[1]"/>返回的是ValueStack中从上至下的第二个Object
3..<s:property value="[0].username"/>返回的是成员变量username的值
    假设ValueStack中存在两个Action的话,如果第一个Action如果没有username变量
    那么它会继续找第二个Action。那么在什么情况下ValueStack中会存在两个Action呢
    答案是在struts.xml中配置的是从一个Action通过<resulttype="chain">跳转到另一个Action
4..<constantname="struts.ognl.allowStaticMethodAccess"value="true"/>
    在Struts2.1.6中必须设置struts.ognl.allowStaticMethodAccesstrue之后
    才允许使用OGNL访问静态方法。而在Struts2.0.11则无需设置,即可直接访问

下面是OGNL测试的工程代码,这是一个Struts2.0.11应用

首先是web.xml文件

1.  <?xmlversion="1.0"encoding="UTF-8"?> 

2.  <web-app version="2.5"  

3.      xmlns="http://java.sun.com/xml/ns/javaee"  

4.      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

5.      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  

6.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 

7.      <filter> 

8.          <filter-name>struts2</filter-name> 

9.          <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> 

10.     </filter> 

11.     <filter-mapping> 

12.         <filter-name>struts2</filter-name> 

13.         <url-pattern>/*</url-pattern> 

14.     </filter-mapping> 

15.     <welcome-file-list> 

16.         <welcome-file>login.jsp</welcome-file> 

17.     </welcome-file-list>   

18. </web-app> 

1.  <?xml version="1.0" encoding="UTF-8"?>  

2.  <web-app version="2.5"   

3.      xmlns="http://java.sun.com/xml/ns/javaee"   

4.      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   

5.      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   

6.      http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  

7.      <filter>  

8.          <filter-name>struts2</filter-name>  

9.          <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  

10.     </filter>  

11.     <filter-mapping>  

12.         <filter-name>struts2</filter-name>  

13.         <url-pattern>/*</url-pattern>  

14.     </filter-mapping>  

15.     <welcome-file-list>  

16.         <welcome-file>login.jsp</welcome-file>  

17.     </welcome-file-list>    

18. </web-app>  

然后是用于输入用户名和密码等信息的测试页面login.jsp

1.  <%@ page language="java"pageEncoding="UTF-8"%> 

2.  <h1>这是测试OGNL使用的登录页面</h1> 

3.  <h3><fontcolor="red">提示:</font>程序设定的用户名和密码各为<fontcolor="blue"><strong>admin</strong></font><fontcolor="blue"><strong>jadyer</strong></font></h3> 

4.  <h3><fontcolor="red">注意:</font>用户名和密码不正确时将停留在页面不动</h3> 

5.  <formaction="<%=request.getContextPath()%>/login.action"method="POST"> 

6.      <%--这里user.username匹配的是LoginAction中的引用类型user里面的username属性--%> 

7.      <%--查看标签库说明的话,就知道name中指定的是对象。这里它不是字符串,而是OGNL表达式--%> 

8.      姓名:<inputtype="text"name="user.username"><br> 

9.      密码:<inputtype="text"name="user.password"><br> 

10.     地址:<inputtype="text"name="user.address.addr"><br> 

11.     <inputtype="submit"value="测试OGNL的输出"> 

12. </form> 

[xhtml] view plaincopyprint?

1.  <%@ page language="java" pageEncoding="UTF-8"%>  

2.  <h1>这是测试OGNL使用的登录页面</h1>  

3.  <h3><font color="red">提示:</font>程序设定的用户名和密码各为<font color="blue"><strong>admin</strong></font><font color="blue"><strong>jadyer</strong></font></h3>  

4.  <h3><font color="red">注意:</font>用户名和密码不正确时将停留在页面不动</h3>  

5.  <form action="<%=request.getContextPath()%>/login.action" method="POST">  

6.      <%--这里user.username匹配的是LoginAction中的引用类型user里面的username属性--%>  

7.      <%--查看标签库说明的话,就知道name中指定的是对象。这里它不是字符串,而是OGNL表达式--%>  

8.      姓名:<input type="text" name="user.username"><br>  

9.      密码:<input type="text" name="user.password"><br>  

10.     地址:<input type="text" name="user.address.addr"><br>  

11.     <input type="submit" value="测试OGNL的输出">  

12. </form>  

然后是用于显示OGNL处理结果的loginSuc.jsp页面

1.  <%@ page language="java"pageEncoding="UTF-8"%> 

2.  <%@ taglib prefix="s"uri="/struts-tags"%> 

3.  <h1>这是使用OGNL输出的结果页面</h1> 

4.  <table border="9"> 

5.      <tr> 

6.          <tdalign="right">获取姓名属性:</td> 

7.          <tdalign="left"><s:propertyvalue="user.username"/></td> 

8.          <%-- 另外还有两种写法也是可以正常输出值栈中对象的普通属性的 --%> 

9.          <%-- <s:propertyvalue="user['username']"/> --%> 

10.         <%-- <s:propertyvalue="user[/"username/"]"/> --%> 

11.         <%-- 但是如果写成下面这种形式的话,就什么都不会输出了 --%> 

12.         <%-- <s:propertyvalue="user[username]"/> --%> 

13.     </tr> 

14.     <tr> 

15.         <tdalign="right">获取地址属性:</td> 

16.         <tdalign="left"><s:propertyvalue="user.address.addr"/></td> 

17.     </tr> 

18.     <tr> 

19.         <tdalign="right">调用值栈中的对象的普通方法:</td> 

20.         <tdalign="left"><s:propertyvalue="user.getVOMethod()"/></td> 

21.     </tr> 

22.     <tr> 

23.         <tdalign="right">调用值栈中Action的普通方法:</td> 

24.         <tdalign="left"><s:propertyvalue="getCommon()"/></td> 

25.     </tr> 

26. </table> 

27. <hr/> 

28. <table border="9"> 

29.     <tr> 

30.         <tdalign="right">获取普通类的静态属性:</td> 

31.         <tdalign="left"><s:propertyvalue="@com.jadyer.vo.Address@TIPS"/></td> 

32.     </tr> 

33.     <tr> 

34.         <tdalign="right">访问普通类的构造方法:</td> 

35.         <tdalign="left"><s:propertyvalue="new com.jadyer.vo.Student('张小三',22).username"/></td> 

36.     </tr> 

37.     <tr> 

38.         <tdalign="right">调用Action中的静态方法:</td> 

39.         <tdalign="left"><s:propertyvalue="@com.jadyer.action.LoginAction@getStatic()"/></td> 

40.     </tr> 

41.     <tr> 

42.         <tdalign="right">调用JDK中的类的静态方法:</td> 

43.         <tdalign="left"><s:propertyvalue="@java.util.Calendar@getInstance().time"/></td> 

44.     </tr> 

45.     <tr> 

46.         <tdalign="right">调用JDK中的类的静态方法:</td> 

47.         <tdalign="left"><s:propertyvalue="@java.lang.Math@floor(46.58)"/></td> 

48.     </tr> 

49.     <tr> 

50.         <tdalign="right">调用JDK中的类的静态方法:</td> 

51.         <tdalign="left"><s:propertyvalue="@@floor(46.58)"/></td> 

52.     </tr> 

53. </table> 

54. <hr/> 

55. <tableborder="9"> 

56.     <tr> 

57.         <tdalign="right">获取List中的所有元素:</td> 

58.         <tdalign="left"><s:propertyvalue="testList"/></td> 

59.     </tr> 

60.     <tr> 

61.         <tdalign="right">获取Set中的所有元素:</td> 

62.         <tdalign="left"><s:propertyvalue="testSet"/></td> 

63.     </tr> 

64.     <tr> 

65.         <tdalign="right">获取Map中的所有元素:</td> 

66.         <tdalign="left"><s:propertyvalue="testMap"/></td> 

67.     </tr> 

68.     <tr> 

69.         <tdalign="right">获取Map中的某个元素:</td> 

70.         <tdalign="left"><s:propertyvalue="testMap['m22']"/></td> 

71.         <%-- 另外还有两种写法也是可以正常获取Map中的某个具体元素的 --%> 

72.         <%-- <s:propertyvalue="testMap.m22"/> --%> 

73.         <%-- <s:propertyvalue="testMap[/"m22/"]"/> --%> 

74.     </tr> 

75.     <tr> 

76.         <tdalign="right">获取Set中的某个元素:</td> 

77.         <%-- 由于Set中的元素是无顺序的,所以不能使用下标获取数据,所以这里什么也得不到 --%> 

78.         <tdalign="left"><s:propertyvalue="testSet[2]"/></td> 

79.     </tr> 

80.     <tr> 

81.         <tdalign="right">获取List中的某个元素:</td> 

82.         <tdalign="left"><s:propertyvalue="testList[2]"/></td> 

83.     </tr> 

84. </table> 

85. <hr/> 

86. <table border="9"> 

87.     <tr> 

88.         <tdalign="right">获取List的大小:</td> 

89.         <tdalign="left"><s:propertyvalue="testList.size"/></td> 

90.     </tr> 

91.     <tr> 

92.         <tdalign="right">获取Set的大小:</td> 

93.         <tdalign="left"><s:propertyvalue="testSet.size"/></td> 

94.     </tr> 

95.     <tr> 

96.         <tdalign="right">获取Map的大小:</td> 

97.         <tdalign="left"><s:propertyvalue="testMap.size"/></td> 

98.     </tr> 

99.     <tr> 

100.         <tdalign="right">获取Map中所有的键:</td> 

101.         <tdalign="left"><s:propertyvalue="testMap.keys"/></td> 

102.     </tr> 

103.     <tr> 

104.         <tdalign="right">获取Map中所有的值:</td> 

105.         <tdalign="left"><s:propertyvalue="testMap.values"/></td> 

106.     </tr> 

107.     <tr> 

108.         <tdalign="right">Lambda计算4的阶乘:</td> 

109.         <tdalign="left"><s:propertyvalue="#f= :[#this==1?1 :#this*#f(#this-1)],#f(4)"/></td> 

110.     </tr> 

111. </table> 

112. <hr/> 

113. <tableborder="9"> 

114.     <tr> 

115.         <tdalign="right">获取List中的所有对象:</td> 

116.         <tdalign="left"><s:propertyvalue="stus"/></td> 

117.     </tr> 

118.     <tr> 

119.         <tdalign="right">利用投影获取List中对象的名字:</td> 

120.         <tdalign="left"><s:propertyvalue="stus.{username}"/></td> 

121.     </tr> 

122.     <tr> 

123.         <tdalign="right">利用投影获取List中第二个对象的名字:</td> 

124.         <%-- 使用<s:propertyvalue="stus[1].{username}"/>获取到的值为:[李四] --%> 

125.         <%-- 二者的区别在于:后者比前者多了一个中括号 --%> 

126.         <tdalign="left"> 

127.             <s:propertyvalue="stus.{username}[1]"/>       

128.             <s:propertyvalue="stus[1].{username}"/> 

129.         </td> 

130.     </tr> 

131.     <tr> 

132.         <tdalign="right">利用选择获取List中成绩及格的所有对象:</td> 

133.         <tdalign="left"><s:propertyvalue="stus.{?#this.grade>=60}"/></td> 

134.     </tr> 

135.     <tr> 

136.         <tdalign="right">利用选择获取List中成绩及格的第一个对象:</td> 

137.         <tdalign="left"><s:propertyvalue="stus.{^#this.grade>=60}"/></td> 

138.     </tr> 

139.     <tr> 

140.         <tdalign="right">利用选择获取List中成绩及格的最后一个对象:</td> 

141.         <tdalign="left"><s:propertyvalue="stus.{$#this.grade>=60}"/></td> 

142.     </tr> 

143. </table> 

144. <hr/> 

145. <tableborder="9"> 

146.     <tr> 

147.         <tdalign="right">利用选择获取List中成绩及格的所有对象的名字:</td> 

148.         <tdalign="left"><s:propertyvalue="stus.{?#this.grade>=60}.{username}"/></td> 

149.     </tr> 

150.     <tr> 

151.         <tdalign="right">利用选择获取List中成绩及格的第二个对象的名字:</td> 

152.         <tdalign="left"><s:propertyvalue="stus.{?#this.grade>=60}.{username}[1]"/></td> 

153.     </tr> 

154.     <tr> 

155.         <tdalign="right">利用选择获取List中成绩及格的第一个对象的名字:</td> 

156.         <tdalign="left"><s:propertyvalue="stus.{^#this.grade>=60}.{username}"/></td> 

157.     </tr> 

158.     <tr> 

159.         <tdalign="right">利用选择获取List中成绩及格的最后一个对象的名字:</td> 

160.         <tdalign="left"><s:propertyvalue="stus.{$#this.grade>=60}.{username}"/></td> 

161.     </tr> 

162.     <tr> 

163.         <tdalign="right">利用选择获取List中成绩及格的第一个对象然后求大小:</td> 

164.         <tdalign="left"><s:propertyvalue="stus.{^#this.grade>=60}.{username}.size"/></td> 

165.     </tr> 

166. </table> 

167. <hr/> 

168. <table border="9"> 

169.     <tr> 

170.         <tdalign="right">利用OGNL中的#号获取attr中的属性:</td> 

171.         <tdalign="left"><s:propertyvalue="#attr.BB"/></td> 

172.     </tr> 

173.     <tr> 

174.         <tdalign="right">利用OGNL中的#号获取request范围中的属性:</td> 

175.         <tdalign="left"><s:propertyvalue="#request.req"/></td> 

176.     </tr> 

177.     <tr> 

178.         <tdalign="right">利用OGNL中的#号获取session范围中的属性:</td> 

179.         <tdalign="left"><s:propertyvalue="#session.ses"/></td> 

180.     </tr> 

181.     <tr> 

182.         <tdalign="right">利用OGNL中的#号获取Paraments对象的属性:</td> 

183.         <tdalign="left"><s:propertyvalue="#parameters.netname"/></td> 

184.     </tr> 

185.     <tr> 

186.         <tdalign="right">使用&#60;&#37;=request.getParameter&#40;""&#41;&#37;&#62;或者&#36;&#123;param.name&#125;获取链接参数值:</td> 

187.         <tdalign="left"> 

188.            ${param.netname}       

189.             <%=request.getParameter("netname")%> 

190.         </td> 

191.     </tr> 

192.     <tr> 

193.         <tdalign="right">查看值栈中的信息:</td> 

194.         <tdalign="left"><s:debug/></td> 

195.     </tr> 

196. </table> 

1.  <%@ page language="java" pageEncoding="UTF-8"%>  

2.  <%@ taglib prefix="s" uri="/struts-tags"%>  

3.  <h1>这是使用OGNL输出的结果页面</h1>  

4.  <table border="9">  

5.      <tr>  

6.          <td align="right">获取姓名属性:</td>  

7.          <td align="left"><s:property value="user.username"/></td>  

8.          <%-- 另外还有两种写法也是可以正常输出值栈中对象的普通属性的 --%>  

9.          <%-- <s:property value="user['username']"/> --%>  

10.         <%-- <s:property value="user[/"username/"]"/> --%>  

11.         <%-- 但是如果写成下面这种形式的话,就什么都不会输出了 --%>  

12.         <%-- <s:property value="user[username]"/> --%>  

13.     </tr>  

14.     <tr>  

15.         <td align="right">获取地址属性:</td>  

16.         <td align="left"><s:property value="user.address.addr"/></td>  

17.     </tr>  

18.     <tr>  

19.         <td align="right">调用值栈中的对象的普通方法:</td>  

20.         <td align="left"><s:property value="user.getVOMethod()"/></td>  

21.     </tr>  

22.     <tr>  

23.         <td align="right">调用值栈中Action的普通方法:</td>  

24.         <td align="left"><s:property value="getCommon()"/></td>  

25.     </tr>  

26. </table>  

27. <hr/>  

28. <table border="9">  

29.     <tr>  

30.         <td align="right">获取普通类的静态属性:</td>  

31.         <td align="left"><s:property value="@com.jadyer.vo.Address@TIPS"/></td>  

32.     </tr>  

33.     <tr>  

34.         <td align="right">访问普通类的构造方法:</td>  

35.         <td align="left"><s:property value="new com.jadyer.vo.Student('张小三',22).username"/></td>  

36.     </tr>  

37.     <tr>  

38.         <td align="right">调用Action中的静态方法:</td>  

39.         <td align="left"><s:property value="@com.jadyer.action.LoginAction@getStatic()"/></td>  

40.     </tr>  

41.     <tr>  

42.         <td align="right">调用JDK中的类的静态方法:</td>  

43.         <td align="left"><s:property value="@java.util.Calendar@getInstance().time"/></td>  

44.     </tr>  

45.     <tr>  

46.         <td align="right">调用JDK中的类的静态方法:</td>  

47.         <td align="left"><s:property value="@java.lang.Math@floor(46.58)"/></td>  

48.     </tr>  

49.     <tr>  

50.         <td align="right">调用JDK中的类的静态方法:</td>  

51.         <td align="left"><s:property value="@@floor(46.58)"/></td>  

52.     </tr>  

53. </table>  

54. <hr/>  

55. <table border="9">  

56.     <tr>  

57.         <td align="right">获取List中的所有元素:</td>  

58.         <td align="left"><s:property value="testList"/></td>  

59.     </tr>  

60.     <tr>  

61.         <td align="right">获取Set中的所有元素:</td>  

62.         <td align="left"><s:property value="testSet"/></td>  

63.     </tr>  

64.     <tr>  

65.         <td align="right">获取Map中的所有元素:</td>  

66.         <td align="left"><s:property value="testMap"/></td>  

67.     </tr>  

68.     <tr>  

69.         <td align="right">获取Map中的某个元素:</td>  

70.         <td align="left"><s:property value="testMap['m22']"/></td>  

71.         <%-- 另外还有两种写法也是可以正常获取Map中的某个具体元素的 --%>  

72.         <%-- <s:property value="testMap.m22"/> --%>  

73.         <%-- <s:property value="testMap[/"m22/"]"/> --%>  

74.     </tr>  

75.     <tr>  

76.         <td align="right">获取Set中的某个元素:</td>  

77.         <%-- 由于Set中的元素是无顺序的,所以不能使用下标获取数据,所以这里什么也得不到 --%>  

78.         <td align="left"><s:property value="testSet[2]"/></td>  

79.     </tr>  

80.     <tr>  

81.         <td align="right">获取List中的某个元素:</td>  

82.         <td align="left"><s:property value="testList[2]"/></td>  

83.     </tr>  

84. </table>  

85. <hr/>  

86. <table border="9">  

87.     <tr>  

88.         <td align="right">获取List的大小:</td>  

89.         <td align="left"><s:property value="testList.size"/></td>  

90.     </tr>  

91.     <tr>  

92.         <td align="right">获取Set的大小:</td>  

93.         <td align="left"><s:property value="testSet.size"/></td>  

94.     </tr>  

95.     <tr>  

96.         <td align="right">获取Map的大小:</td>  

97.         <td align="left"><s:property value="testMap.size"/></td>  

98.     </tr>  

99.     <tr>  

100.         <td align="right">获取Map中所有的键:</td>  

101.         <td align="left"><s:property value="testMap.keys"/></td>  

102.     </tr>  

103.     <tr>  

104.         <td align="right">获取Map中所有的值:</td>  

105.         <td align="left"><s:property value="testMap.values"/></td>  

106.     </tr>  

107.     <tr>  

108.         <td align="right">Lambda计算4的阶乘:</td>  

109.         <td align="left"><s:property value="#f= :[#this==1?1 : #this*#f(#this-1)],#f(4)"/></td>  

110.     </tr>  

111. </table>  

112. <hr/>  

113. <table border="9">  

114.     <tr>  

115.         <td align="right">获取List中的所有对象:</td>  

116.         <td align="left"><s:property value="stus"/></td>  

117.     </tr>  

118.     <tr>  

119.         <td align="right">利用投影获取List中对象的名字:</td>  

120.         <td align="left"><s:property value="stus.{username}"/></td>  

121.     </tr>  

122.     <tr>  

123.         <td align="right">利用投影获取List中第二个对象的名字:</td>  

124.         <%-- 使用<s:property value="stus[1].{username}"/>获取到的值为:[李四] --%>  

125.         <%-- 二者的区别在于:后者比前者多了一个中括号 --%>  

126.         <td align="left">  

127.             <s:property value="stus.{username}[1]"/>        

128.             <s:property value="stus[1].{username}"/>  

129.         </td>  

130.     </tr>  

131.     <tr>  

132.         <td align="right">利用选择获取List中成绩及格的所有对象:</td>  

133.         <td align="left"><s:property value="stus.{?#this.grade>=60}"/></td>  

134.     </tr>  

135.     <tr>  

136.         <td align="right">利用选择获取List中成绩及格的第一个对象:</td>  

137.         <td align="left"><s:property value="stus.{^#this.grade>=60}"/></td>  

138.     </tr>  

139.     <tr>  

140.         <td align="right">利用选择获取List中成绩及格的最后一个对象:</td>  

141.         <td align="left"><s:property value="stus.{$#this.grade>=60}"/></td>  

142.     </tr>  

143. </table>  

144. <hr/>  

145. <table border="9">  

146.     <tr>  

147.         <td align="right">利用选择获取List中成绩及格的所有对象的名字:</td>  

148.         <td align="left"><s:property value="stus.{?#this.grade>=60}.{username}"/></td>  

149.     </tr>  

150.     <tr>  

151.         <td align="right">利用选择获取List中成绩及格的第二个对象的名字:</td>  

152.         <td align="left"><s:property value="stus.{?#this.grade>=60}.{username}[1]"/></td>  

153.     </tr>  

154.     <tr>  

155.         <td align="right">利用选择获取List中成绩及格的第一个对象的名字:</td>  

156.         <td align="left"><s:property value="stus.{^#this.grade>=60}.{username}"/></td>  

157.     </tr>  

158.     <tr>  

159.         <td align="right">利用选择获取List中成绩及格的最后一个对象的名字:</td>  

160.         <td align="left"><s:property value="stus.{$#this.grade>=60}.{username}"/></td>  

161.     </tr>  

162.     <tr>  

163.         <td align="right">利用选择获取List中成绩及格的第一个对象然后求大小:</td>  

164.         <td align="left"><s:property value="stus.{^#this.grade>=60}.{username}.size"/></td>  

165.     </tr>  

166. </table>  

167. <hr/>  

168. <table border="9">  

169.     <tr>  

170.         <td align="right">利用OGNL中的#号获取attr中的属性:</td>  

171.         <td align="left"><s:property value="#attr.BB"/></td>  

172.     </tr>  

173.     <tr>  

174.         <td align="right">利用OGNL中的#号获取request范围中的属性:</td>  

175.         <td align="left"><s:property value="#request.req"/></td>  

176.     </tr>  

177.     <tr>  

178.         <td align="right">利用OGNL中的#号获取session范围中的属性:</td>  

179.         <td align="left"><s:property value="#session.ses"/></td>  

180.     </tr>  

181.     <tr>  

182.         <td align="right">利用OGNL中的#号获取Paraments对象的属性:</td>  

183.         <td align="left"><s:property value="#parameters.netname"/></td>  

184.     </tr>  

185.     <tr>  

186.         <td align="right">使用&#60;&#37;=request.getParameter&#40;""&#41;&#37;&#62;或者&#36;&#123;param.name&#125;获取链接参数值:</td>  

187.         <td align="left">  

188.             ${param.netname}        

189.             <%=request.getParameter("netname")%>  

190.         </td>  

191.     </tr>  

192.     <tr>  

193.         <td align="right">查看值栈中的信息:</td>  

194.         <td align="left"><s:debug/></td>  

195.     </tr>  

196. </table>  

然后是struts.xml文件

1.  <?xmlversion="1.0"encoding="UTF-8"?> 

2.  <!DOCTYPE struts PUBLIC 

3.      "-//Apache SoftwareFoundation//DTD Struts Configuration 2.0//EN" 

4.     "http://struts.apache.org/dtds/struts-2.0.dtd"> 

5.  <struts> 

6.      <packagename="ognl"extends="struts-default"> 

7.          <actionname="login"class="com.jadyer.action.LoginAction"> 

8.              <resultname="input">/login.jsp</result> 

9.              <resultname="success">/loginSuc.jsp?netname=hongyu</result> 

10.            <!-- 

11.             <resultname="success"type="redirect">/loginSuc.jsp?netname=hongyu</result> 

12.             <resultname="success"type="redirect">/loginSuc.jsp?netname=${user.username}</result>  

13.             --> 

14.         </action> 

15.     </package> 

16. </struts> 

1.  <?xml version="1.0" encoding="UTF-8"?>  

2.  <!DOCTYPE struts PUBLIC  

3.      "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  

4.      "http://struts.apache.org/dtds/struts-2.0.dtd">  

5.  <struts>  

6.      <package name="ognl" extends="struts-default">  

7.          <action name="login" class="com.jadyer.action.LoginAction">  

8.              <result name="input">/login.jsp</result>  

9.              <result name="success">/loginSuc.jsp?netname=hongyu</result>  

10.             <!--  

11.             <result name="success" type="redirect">/loginSuc.jsp?netname=hongyu</result>  

12.             <result name="success" type="redirect">/loginSuc.jsp?netname=${user.username}</result>   

13.              -->  

14.         </action>  

15.     </package>  

16. </struts>  

接着是用到的三个VO类

1.  package com.jadyer.vo; 

2.  public class User { 

3.      private String username; 

4.      private String password; 

5.      private Address address; 

6.      /* 三个属性的settergetter */ 

7.      public String getVOMethod(){ 

8.          return "这是User类中的一个普通方法"

9.      } 

10.

11.  

12.  

13. package com.jadyer.vo; 

14. public class Address { 

15.     //如果将TIPS设为private的话,loginSuc.jsp中就无法获取它的属性值了 

16.     //事实上将一个静态的final属性设为private是毫无意义的 

17.     //因为既然设置成了静态,那么就是供他人调用的,如果再设成private的话,别的地方根本就无法调用了 

18.     //即使OGNL再怎么强大,它也不可能违反Java的规则,所以不要将静态的属性设为私有 

19.     public staticfinal String TIPS = "玄玉加油!!"

20.     //addr属性的settergetter 

21.     private String addr; 

22.

23.  

24.  

25. package com.jadyer.vo; 

26. public class Student { 

27.     private String username; 

28.     private int grade; 

29.     /* 两个属性的settergetter */ 

30.      

31.     //只要是重写一个类的构造方法,就必须要为这个类保留空的构造方法 

32.     //因为框架默认的都会去调用无参的空的构造方法 

33.     public Student(){}; 

34.     public Student(String username,int grade){ 

35.         this.username = username; 

36.         this.grade = grade; 

37.     } 

38.     @Override 

39.     public String toString() { 

40.         //如果不重写它的toString()方法的话,默认调用toString()将输出【类型+@+内存地址的哈希值】 

41.         return "{学生姓名:" + username +",成绩:" + grade + "}"

42.     } 

43.

1.  package com.jadyer.vo;  

2.  public class User {  

3.      private String username;  

4.      private String password;  

5.      private Address address;  

6.      /* 三个属性的settergetter */  

7.      public String getVOMethod(){  

8.          return "这是User类中的一个普通方法";  

9.      }  

10. }  

11.   

12.   

13. package com.jadyer.vo;  

14. public class Address {  

15.     //如果将TIPS设为private的话,loginSuc.jsp中就无法获取它的属性值了  

16.     //事实上将一个静态的final属性设为private是毫无意义的  

17.     //因为既然设置成了静态,那么就是供他人调用的,如果再设成private的话,别的地方根本就无法调用了  

18.     //即使OGNL再怎么强大,它也不可能违反Java的规则,所以不要将静态的属性设为私有  

19.     public static final String TIPS = "玄玉加油!!";  

20.     //addr属性的settergetter  

21.     private String addr;  

22. }  

23.   

24.   

25. package com.jadyer.vo;  

26. public class Student {  

27.     private String username;  

28.     private int grade;  

29.     /* 两个属性的settergetter */  

30.       

31.     //只要是重写一个类的构造方法,就必须要为这个类保留空的构造方法  

32.     //因为框架默认的都会去调用无参的空的构造方法  

33.     public Student(){};  

34.     public Student(String username,int grade){  

35.         this.username = username;  

36.         this.grade = grade;  

37.     }  

38.     @Override  

39.     public String toString() {  

40.         //如果不重写它的toString()方法的话,默认调用toString()将输出【类型+@+内存地址的哈希值】  

41.         return "{学生姓名:" + username + ",成绩:" + grade + "}";  

42.     }  

43. }  

最后是用来提供OGNL测试的数据的LoginAction.java

1.  package com.jadyer.action; 

2.   

3.  import java.util.ArrayList; 

4.  import java.util.HashMap; 

5.  import java.util.HashSet; 

6.  import java.util.List; 

7.  import java.util.Map; 

8.  import java.util.Set; 

9.   

10. import org.apache.struts2.interceptor.RequestAware; 

11. import org.apache.struts2.interceptor.SessionAware; 

12.  

13. import com.jadyer.vo.Student; 

14. import com.jadyer.vo.User; 

15. import com.opensymphony.xwork2.ActionSupport; 

16.  

17. @SuppressWarnings({"serial","unchecked"}) 

18. public class LoginActionextends ActionSupport implements RequestAware,SessionAware { 

19.     private User user; 

20.     private List testList = new ArrayList(); 

21.     private Set testSet =new HashSet(); 

22.     private Map testMap = new HashMap(); 

23.     private List stus = new ArrayList(); 

24.      

25.     /* 以上五个属性的settergetter */ 

26.      

27.     private Map request; 

28.     private Map session; 

29.     public void setRequest(Map request) { 

30.         this.request = request; 

31.     } 

32.     public void setSession(Map session) { 

33.         this.session = session; 

34.     } 

35.      

36.     public static String getStatic(){ 

37.         return "这是LoginAction中的一个静态方法"

38.     } 

39.     public String getCommon(){ 

40.         return "这是LoginAction中的一个普通方法"

41.     } 

42.      

43.     @Override 

44.     public String execute() throws Exception { 

45.         if(user.getUsername().trim().equalsIgnoreCase("admin") && user.getPassword().equals("jadyer")){ 

46.            testList.add("list11"); 

47.            testList.add("list22"); 

48.            testList.add("list33"); 

49.            testList.add("list44"); 

50.            testList.add("list55"); 

51.              

52.            testSet.add("set11"); 

53.            testSet.add("set22"); 

54.            testSet.add("set33"); 

55.            testSet.add("set22"); 

56.            testSet.add("set11"); 

57.              

58.            testMap.put("m11", "map11"); 

59.            testMap.put("m22","map22"); 

60.            testMap.put("m33", "map33"); 

61.            testMap.put("m44","map44"); 

62.            testMap.put("m55", "map55"); 

63.              

64.            stus.add(new Student("张三",88)); 

65.            stus.add(new Student("李四",77)); 

66.            stus.add(new Student("王五",66)); 

67.            stus.add(new Student("马六",55)); 

68.              

69.            request.put("req","这是通过OGNL中的#号获取的request属性范围的值"); 

70.            session.put("ses", "这是通过OGNL中的#号获取的session属性范围的值"); 

71.            request.put("BB","这是通过OGNL中的#号获取的request属性范围的BB"); 

72.            session.put("BB", "这是通过OGNL中的#号获取的session属性范围的BB"); 

73.             return SUCCESS; 

74.         }else

75.             return INPUT; 

76.        } 

77.     } 

78. }

你可能感兴趣的:(struts,list,user,action,getter,setter)