Struts2中的OGNL表达式

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

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

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

三个语法
假设此时想要获取Action11中的username属性的话,就可以使用值栈的Top语法 或者N语法
使用Top语法 获取值栈中的第二个对象的属性:<s:property value="[1].top.username"/>
使用 N 语法 获取值栈中的第二个对象的属性:<s:property value="[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:property value="#parameters.netname"/> 就可以取到值了
辅助参考: http://blog.csdn.net/jadyer/archive/2010/09/16/5887509.aspx

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

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

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

OGNL中%号的使用
1.. 使用%{} 可以取出保存在值堆栈中的Action对象,直接调用它的方法
2.. 如果Action继承了ActionSupport,那么在页面标签中可以使用%{getText('key')} 获取国际化信息
辅助参考: http://blog.csdn.net/jadyer/archive/2010/09/16/5887545.aspx

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:property value="user.getVOMethod()"/> 的时候
它会自动到值栈里面查找Action对象里面有没有user对象,然后它就发现有user
然后它就再找user里面有没有getVOMethod()方法,然后它发现有,于是调用getVOMethod()
实际上调用User中的getVOMethod()方法的过程与获取表单中的姓名密码的方式都是相同的
都是到值栈里面查找 ,找是否存在user对象,如果存在,接着查找user中是否存在某某属性或方法

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

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

集合的伪属性
OGNL能够引用集合的一些特殊的属性,这些属性并不是JavaBean模式,例如size()、length()
当表达式引用这些属性时,OGNL会调用相应的方法,这就是伪属性
比如获取List的大小:<s:property value="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:property value="[1]"/> 返回的是ValueStack中从上至下的第二个Object
3.. <s:property value="[0].username"/> 返回的是成员变量username的值
    假设ValueStack中存在两个Action的话,如果第一个Action如果没有username变量
    那么它会继续找第二个Action。那么在什么情况下ValueStack中会存在两个Action呢
    答案是在struts.xml中配置的是从一个Action通过<result type="chain"> 跳转到另一个Action
4.. <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
    在Struts2.1.6 中必须设置struts.ognl.allowStaticMethodAccess为true 之后
    才允许使用OGNL访问静态方法。而在Struts2.0.11则无需设置 ,即可直接访问


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

首先是web.xml文件

  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 > < 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.         < 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. <? 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.     /* 三个属性的setter和getter略 */   
  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属性的setter和getter略   
  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.     /* 两个属性的setter和getter略 */   
  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  LoginAction  extends  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.     /* 以上五个属性的setter和getter略 */   
  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. }

猜你喜欢

转载自88548886.iteye.com/blog/1550586