大连地区建设网站,wordpress程序图片打开慢,搜索引擎 网站推广 举例,专做美食的网站基础知识#xff08;三#xff09;Struts2中的OGNL表达式浅析值栈ValueStack对象相当于一个栈#xff0c;它贯穿整个Action的生命周期#xff0c;每个Action类的对象实例都会拥有一个ValueStack对象 当Struts2接收到一个*.action请求后#xff0c;并不是直接调用Action方法… 基础知识三 Struts2中的OGNL表达式 浅析值栈 ValueStack对象相当于一个栈它贯穿整个Action的生命周期每个Action类的对象实例都会拥有一个ValueStack对象 当Struts2接收到一个*.action请求后并不是直接调用Action方法而是先将Action类的相应属性放到ValueStack对象的顶层节点 值栈也位于内存中它也是和parameters、request、session、application、attr对象放在一起的 值栈属于ONGL Context里面的根对象。也就是说它位于整个内存中最最重要的地方所以叫根对象 根对象和另外五个对象是有区别的根对象可以省写#号比如s:property valueuser.username/ 值栈的生命周期与request请求相关每次请求产生一个值栈。默认所有的Action会被自动放到值栈里 服务器跳转时共用值栈 假设从一个Action11通过服务器跳转到Action22的话就意味着这两个Action是共享一个值栈的因为一次请求只使用一个值栈 这时内存中情况是这样的首先接收到Action11请求后会产生一个值栈在栈顶存放Action11对象以及它所有的属性 然后经过服务器跳转到Action22这时就会把Action22对象压入值栈的栈顶位置此时Action11对象以及它的所有属性就位于栈底了 取值过程 栈的特征是后进先出。于是首先到栈顶的对象里查找是否存在这个属性如果栈顶的Action22对象中不存在这个属性的话 它就会继续向下寻找直至栈底对象一直查找是否存在这个属性 如果最后找到该属性的话那么就会在JSP页面中通过s:property valueusername/输出属性值 如果在Action22和Action11都有一个同名的同类型的username属性的话那么将输出Action22中的属性值 因为它是先从栈顶开始寻找属性的值栈的特征就是后进先出但有个前提请求过程是通过服务器跳转的 三个语法 假设此时想要获取Action11中的username属性的话就可以使用值栈的Top语法或者N语法 使用Top语法获取值栈中的第二个对象的属性s:property value[1].top.username/ 使用 N 语法获取值栈中的第二个对象的属性s:property value[1].username/ 另外值栈还有一个语法例如使用语法调用Action中的静态方法s:property valuevsgetVOMethod()/ vsget()等价于vs1getVOMethod()指的是栈顶对象的静态getVOMethod()方法 同理vs2getVOMethod()就是取值栈中第二个对象的静态getVOMethod()方法 客户端跳转时使用各自的值栈 假如中间某一个步骤中出现了客户端跳转的话那么两个Action所使用的就是两个不同的值栈了 所以在Action22中就不能再使用Action11中的属性了在最后跳转到的JSP页面中也就无法获取Action11的属性了 也即从Action22跳转到JSP页面时使用的是redirect的话那么最后值栈中是没有任何的Action对象的 这个时候我们可以通过链接传参比如result typeredirecttest.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 用于按requestsessionapplication顺序访问其属性 #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 valueuser.getVOMethod()/的时候 它会自动到值栈里面查找Action对象里面有没有user对象然后它就发现有user 然后它就再找user里面有没有getVOMethod()方法然后它发现有于是调用getVOMethod() 实际上调用User中的getVOMethod()方法的过程与获取表单中的姓名密码的方式都是相同的 都是到值栈里面查找找是否存在user对象如果存在接着查找user中是否存在某某属性或方法 调用Action中的静态方法 同样我们也可以在JSP页面中写一个OGNL表达式调用Action中的静态方法 调用Action中的静态方法时与调用user对象的getVOMethod()方法的过程是截然不同的 此时value的写法是固定的以开头后面跟上具体的包名然后加上静态方法 比如s:property valuecom.jadyer.action.LoginActiongetStatic()/ 另外user对象是LoginAction中的一个属性这个属性会自动的放到值栈里面 而值栈调用的时候不用加上或者包名等等所以直接user.getVOMethod()就可以了 调用JDK类中的静态方法 可以使用s:property valuefloor(46.58)/输出floor()的执行结果 这就意味着如果不在中指定类的话默认的就表示java.lang.Math类 当前大多数情况下我们都不会省略这个类都会写全了的然后在后面加上静态方法 集合的伪属性 OGNL能够引用集合的一些特殊的属性这些属性并不是JavaBean模式例如size()、length() 当表达式引用这些属性时OGNL会调用相应的方法这就是伪属性 比如获取List的大小s:property valuetestList.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 :[#this0 ? 0 : #this1 ? 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.grade60}.{username}输出的是[张三] 注意此时输出文本中包含中括号这表示它是一个列表 而stus.{?#this.grade60}.{username}[0]输出的是张三是字符串二者是不同的 美元符号$是结束的意思所以stus.{$#this.grade60}.{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 typechain跳转到另一个Action 4..constant namestruts.ognl.allowStaticMethodAccess valuetrue/ 在Struts2.1.6中必须设置struts.ognl.allowStaticMethodAccess为true之后 才允许使用OGNL访问静态方法。而在Struts2.0.11则无需设置即可直接访问 下面是OGNL测试的工程代码这是一个Struts2.0.11应用 首先是web.xml文件 [xhtml] view plaincopy ?xmlversion1.0encodingUTF-8? web-app version2.5 xmlnshttp://java.sun.com/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://java.sun.com/xml/ns/javaee ; http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd filter filter-namestruts2/filter-name filter-classorg.apache.struts2.dispatcher.FilterDispatcher/filter-class /filter filter-mapping filter-namestruts2/filter-name url-pattern/*/url-pattern /filter-mapping welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list /web-app [xhtml] view plaincopy ?xml version1.0 encodingUTF-8? web-app version2.5 xmlnshttp://java.sun.com/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://java.sun.com/xml/ns/javaee ; http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd filter filter-namestruts2/filter-name filter-classorg.apache.struts2.dispatcher.FilterDispatcher/filter-class /filter filter-mapping filter-namestruts2/filter-name url-pattern/*/url-pattern /filter-mapping welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list /web-app 然后是用于输入用户名和密码等信息的测试页面login.jsp [xhtml] view plaincopy % page languagejavapageEncodingUTF-8% h1这是测试OGNL使用的登录页面/h1 h3fontcolorred提示/font程序设定的用户名和密码各为fontcolorbluestrongadmin/strong/font和fontcolorbluestrongjadyer/strong/font/h3 h3fontcolorred注意/font用户名和密码不正确时将停留在页面不动/h3 formaction%request.getContextPath()%/login.actionmethodPOST %--这里user.username匹配的是LoginAction中的引用类型user里面的username属性--% %--查看标签库说明的话就知道name中指定的是对象。这里它不是字符串而是OGNL表达式--% 姓名inputtypetextnameuser.usernamebr 密码inputtypetextnameuser.passwordbr 地址inputtypetextnameuser.address.addrbr inputtypesubmitvalue测试OGNL的输出 /form [xhtml] view plaincopy % page languagejava pageEncodingUTF-8% h1这是测试OGNL使用的登录页面/h1 h3font colorred提示/font程序设定的用户名和密码各为font colorbluestrongadmin/strong/font和font colorbluestrongjadyer/strong/font/h3 h3font colorred注意/font用户名和密码不正确时将停留在页面不动/h3 form action%request.getContextPath()%/login.action methodPOST %--这里user.username匹配的是LoginAction中的引用类型user里面的username属性--% %--查看标签库说明的话就知道name中指定的是对象。这里它不是字符串而是OGNL表达式--% 姓名input typetext nameuser.usernamebr 密码input typetext nameuser.passwordbr 地址input typetext nameuser.address.addrbr input typesubmit value测试OGNL的输出 /form 然后是用于显示OGNL处理结果的loginSuc.jsp页面 [xhtml] view plaincopy % page languagejavapageEncodingUTF-8% % taglib prefixsuri/struts-tags% h1这是使用OGNL输出的结果页面/h1 table border9 tr tdalignright获取姓名属性/td tdalignlefts:propertyvalueuser.username//td %-- 另外还有两种写法也是可以正常输出值栈中对象的普通属性的 --% %-- s:propertyvalueuser[username]/ --% %-- s:propertyvalueuser[/username/]/ --% %-- 但是如果写成下面这种形式的话就什么都不会输出了 --% %-- s:propertyvalueuser[username]/ --% /tr tr tdalignright获取地址属性/td tdalignlefts:propertyvalueuser.address.addr//td /tr tr tdalignright调用值栈中的对象的普通方法/td tdalignlefts:propertyvalueuser.getVOMethod()//td /tr tr tdalignright调用值栈中Action的普通方法/td tdalignlefts:propertyvaluegetCommon()//td /tr /table hr/ table border9 tr tdalignright获取普通类的静态属性/td tdalignlefts:propertyvaluecom.jadyer.vo.AddressTIPS//td /tr tr tdalignright访问普通类的构造方法/td tdalignlefts:propertyvaluenew com.jadyer.vo.Student(张小三,22).username//td /tr tr tdalignright调用Action中的静态方法/td tdalignlefts:propertyvaluecom.jadyer.action.LoginActiongetStatic()//td /tr tr tdalignright调用JDK中的类的静态方法/td tdalignlefts:propertyvaluejava.util.CalendargetInstance().time//td /tr tr tdalignright调用JDK中的类的静态方法/td tdalignlefts:propertyvaluejava.lang.Mathfloor(46.58)//td /tr tr tdalignright调用JDK中的类的静态方法/td tdalignlefts:propertyvaluefloor(46.58)//td /tr /table hr/ tableborder9 tr tdalignright获取List中的所有元素/td tdalignlefts:propertyvaluetestList//td /tr tr tdalignright获取Set中的所有元素/td tdalignlefts:propertyvaluetestSet//td /tr tr tdalignright获取Map中的所有元素/td tdalignlefts:propertyvaluetestMap//td /tr tr tdalignright获取Map中的某个元素/td tdalignlefts:propertyvaluetestMap[m22]//td %-- 另外还有两种写法也是可以正常获取Map中的某个具体元素的 --% %-- s:propertyvaluetestMap.m22/ --% %-- s:propertyvaluetestMap[/m22/]/ --% /tr tr tdalignright获取Set中的某个元素/td %-- 由于Set中的元素是无顺序的所以不能使用下标获取数据所以这里什么也得不到 --% tdalignlefts:propertyvaluetestSet[2]//td /tr tr tdalignright获取List中的某个元素/td tdalignlefts:propertyvaluetestList[2]//td /tr /table hr/ table border9 tr tdalignright获取List的大小/td tdalignlefts:propertyvaluetestList.size//td /tr tr tdalignright获取Set的大小/td tdalignlefts:propertyvaluetestSet.size//td /tr tr tdalignright获取Map的大小/td tdalignlefts:propertyvaluetestMap.size//td /tr tr tdalignright获取Map中所有的键/td tdalignlefts:propertyvaluetestMap.keys//td /tr tr tdalignright获取Map中所有的值/td tdalignlefts:propertyvaluetestMap.values//td /tr tr tdalignrightLambda计算4的阶乘/td tdalignlefts:propertyvalue#f :[#this1?1 : #this*#f(#this-1)],#f(4)//td /tr /table hr/ tableborder9 tr tdalignright获取List中的所有对象/td tdalignlefts:propertyvaluestus//td /tr tr tdalignright利用投影获取List中对象的名字/td tdalignlefts:propertyvaluestus.{username}//td /tr tr tdalignright利用投影获取List中第二个对象的名字/td %-- 使用s:propertyvaluestus[1].{username}/获取到的值为[李四] --% %-- 二者的区别在于后者比前者多了一个中括号 --% tdalignleft s:propertyvaluestus.{username}[1]/ s:propertyvaluestus[1].{username}/ /td /tr tr tdalignright利用选择获取List中成绩及格的所有对象/td tdalignlefts:propertyvaluestus.{?#this.grade60}//td /tr tr tdalignright利用选择获取List中成绩及格的第一个对象/td tdalignlefts:propertyvaluestus.{^#this.grade60}//td /tr tr tdalignright利用选择获取List中成绩及格的最后一个对象/td tdalignlefts:propertyvaluestus.{$#this.grade60}//td /tr /table hr/ tableborder9 tr tdalignright利用选择获取List中成绩及格的所有对象的名字/td tdalignlefts:propertyvaluestus.{?#this.grade60}.{username}//td /tr tr tdalignright利用选择获取List中成绩及格的第二个对象的名字/td tdalignlefts:propertyvaluestus.{?#this.grade60}.{username}[1]//td /tr tr tdalignright利用选择获取List中成绩及格的第一个对象的名字/td tdalignlefts:propertyvaluestus.{^#this.grade60}.{username}//td /tr tr tdalignright利用选择获取List中成绩及格的最后一个对象的名字/td tdalignlefts:propertyvaluestus.{$#this.grade60}.{username}//td /tr tr tdalignright利用选择获取List中成绩及格的第一个对象然后求大小/td tdalignlefts:propertyvaluestus.{^#this.grade60}.{username}.size//td /tr /table hr/ table border9 tr tdalignright利用OGNL中的#号获取attr中的属性/td tdalignlefts:propertyvalue#attr.BB//td /tr tr tdalignright利用OGNL中的#号获取request范围中的属性/td tdalignlefts:propertyvalue#request.req//td /tr tr tdalignright利用OGNL中的#号获取session范围中的属性/td tdalignlefts:propertyvalue#session.ses//td /tr tr tdalignright利用OGNL中的#号获取Paraments对象的属性/td tdalignlefts:propertyvalue#parameters.netname//td /tr tr tdalignright使用#60;#37;request.getParameter#40;#41;#37;#62;或者#36;#123;param.name#125;获取链接参数值/td tdalignleft ${param.netname} %request.getParameter(netname)% /td /tr tr tdalignright查看值栈中的信息/td tdalignlefts:debug//td /tr /table [xhtml] view plaincopy % page languagejava pageEncodingUTF-8% % taglib prefixs uri/struts-tags% h1这是使用OGNL输出的结果页面/h1 table border9 tr td alignright获取姓名属性/td td alignlefts:property valueuser.username//td %-- 另外还有两种写法也是可以正常输出值栈中对象的普通属性的 --% %-- s:property valueuser[username]/ --% %-- s:property valueuser[/username/]/ --% %-- 但是如果写成下面这种形式的话就什么都不会输出了 --% %-- s:property valueuser[username]/ --% /tr tr td alignright获取地址属性/td td alignlefts:property valueuser.address.addr//td /tr tr td alignright调用值栈中的对象的普通方法/td td alignlefts:property valueuser.getVOMethod()//td /tr tr td alignright调用值栈中Action的普通方法/td td alignlefts:property valuegetCommon()//td /tr /table hr/ table border9 tr td alignright获取普通类的静态属性/td td alignlefts:property valuecom.jadyer.vo.AddressTIPS//td /tr tr td alignright访问普通类的构造方法/td td alignlefts:property valuenew com.jadyer.vo.Student(张小三,22).username//td /tr tr td alignright调用Action中的静态方法/td td alignlefts:property valuecom.jadyer.action.LoginActiongetStatic()//td /tr tr td alignright调用JDK中的类的静态方法/td td alignlefts:property valuejava.util.CalendargetInstance().time//td /tr tr td alignright调用JDK中的类的静态方法/td td alignlefts:property valuejava.lang.Mathfloor(46.58)//td /tr tr td alignright调用JDK中的类的静态方法/td td alignlefts:property valuefloor(46.58)//td /tr /table hr/ table border9 tr td alignright获取List中的所有元素/td td alignlefts:property valuetestList//td /tr tr td alignright获取Set中的所有元素/td td alignlefts:property valuetestSet//td /tr tr td alignright获取Map中的所有元素/td td alignlefts:property valuetestMap//td /tr tr td alignright获取Map中的某个元素/td td alignlefts:property valuetestMap[m22]//td %-- 另外还有两种写法也是可以正常获取Map中的某个具体元素的 --% %-- s:property valuetestMap.m22/ --% %-- s:property valuetestMap[/m22/]/ --% /tr tr td alignright获取Set中的某个元素/td %-- 由于Set中的元素是无顺序的所以不能使用下标获取数据所以这里什么也得不到 --% td alignlefts:property valuetestSet[2]//td /tr tr td alignright获取List中的某个元素/td td alignlefts:property valuetestList[2]//td /tr /table hr/ table border9 tr td alignright获取List的大小/td td alignlefts:property valuetestList.size//td /tr tr td alignright获取Set的大小/td td alignlefts:property valuetestSet.size//td /tr tr td alignright获取Map的大小/td td alignlefts:property valuetestMap.size//td /tr tr td alignright获取Map中所有的键/td td alignlefts:property valuetestMap.keys//td /tr tr td alignright获取Map中所有的值/td td alignlefts:property valuetestMap.values//td /tr tr td alignrightLambda计算4的阶乘/td td alignlefts:property value#f :[#this1?1 : #this*#f(#this-1)],#f(4)//td /tr /table hr/ table border9 tr td alignright获取List中的所有对象/td td alignlefts:property valuestus//td /tr tr td alignright利用投影获取List中对象的名字/td td alignlefts:property valuestus.{username}//td /tr tr td alignright利用投影获取List中第二个对象的名字/td %-- 使用s:property valuestus[1].{username}/获取到的值为[李四] --% %-- 二者的区别在于后者比前者多了一个中括号 --% td alignleft s:property valuestus.{username}[1]/ s:property valuestus[1].{username}/ /td /tr tr td alignright利用选择获取List中成绩及格的所有对象/td td alignlefts:property valuestus.{?#this.grade60}//td /tr tr td alignright利用选择获取List中成绩及格的第一个对象/td td alignlefts:property valuestus.{^#this.grade60}//td /tr tr td alignright利用选择获取List中成绩及格的最后一个对象/td td alignlefts:property valuestus.{$#this.grade60}//td /tr /table hr/ table border9 tr td alignright利用选择获取List中成绩及格的所有对象的名字/td td alignlefts:property valuestus.{?#this.grade60}.{username}//td /tr tr td alignright利用选择获取List中成绩及格的第二个对象的名字/td td alignlefts:property valuestus.{?#this.grade60}.{username}[1]//td /tr tr td alignright利用选择获取List中成绩及格的第一个对象的名字/td td alignlefts:property valuestus.{^#this.grade60}.{username}//td /tr tr td alignright利用选择获取List中成绩及格的最后一个对象的名字/td td alignlefts:property valuestus.{$#this.grade60}.{username}//td /tr tr td alignright利用选择获取List中成绩及格的第一个对象然后求大小/td td alignlefts:property valuestus.{^#this.grade60}.{username}.size//td /tr /table hr/ table border9 tr td alignright利用OGNL中的#号获取attr中的属性/td td alignlefts:property value#attr.BB//td /tr tr td alignright利用OGNL中的#号获取request范围中的属性/td td alignlefts:property value#request.req//td /tr tr td alignright利用OGNL中的#号获取session范围中的属性/td td alignlefts:property value#session.ses//td /tr tr td alignright利用OGNL中的#号获取Paraments对象的属性/td td alignlefts:property value#parameters.netname//td /tr tr td alignright使用#60;#37;request.getParameter#40;#41;#37;#62;或者#36;#123;param.name#125;获取链接参数值/td td alignleft ${param.netname} %request.getParameter(netname)% /td /tr tr td alignright查看值栈中的信息/td td alignlefts:debug//td /tr /table 然后是struts.xml文件 [xhtml] view plaincopy ?xmlversion1.0encodingUTF-8? !DOCTYPE struts PUBLIC -//Apache Software Foundation//DTD Struts Configuration 2.0//EN http://struts.apache.org/dtds/struts-2.0.dtd struts packagenameognlextendsstruts-default actionnameloginclasscom.jadyer.action.LoginAction resultnameinput/login.jsp/result resultnamesuccess/loginSuc.jsp?netnamehongyu/result !-- resultnamesuccesstyperedirect/loginSuc.jsp?netnamehongyu/result resultnamesuccesstyperedirect/loginSuc.jsp?netname${user.username}/result -- /action /package /struts [xhtml] view plaincopy ?xml version1.0 encodingUTF-8? !DOCTYPE struts PUBLIC -//Apache Software Foundation//DTD Struts Configuration 2.0//EN http://struts.apache.org/dtds/struts-2.0.dtd struts package nameognl extendsstruts-default action namelogin classcom.jadyer.action.LoginAction result nameinput/login.jsp/result result namesuccess/loginSuc.jsp?netnamehongyu/result !-- result namesuccess typeredirect/loginSuc.jsp?netnamehongyu/result result namesuccess typeredirect/loginSuc.jsp?netname${user.username}/result -- /action /package /struts 接着是用到的三个VO类 [java] view plaincopy package com.jadyer.vo; publicclass User { private String username; private String password; private Address address; /* 三个属性的setter和getter略 */ public String getVOMethod(){ return这是User类中的一个普通方法; } } package com.jadyer.vo; publicclass Address { //如果将TIPS设为private的话loginSuc.jsp中就无法获取它的属性值了 //事实上将一个静态的final属性设为private是毫无意义的 //因为既然设置成了静态那么就是供他人调用的如果再设成private的话别的地方根本就无法调用了 //即使OGNL再怎么强大它也不可能违反Java的规则所以不要将静态的属性设为私有 publicstaticfinal String TIPS 玄玉加油!!; //addr属性的setter和getter略 private String addr; } package com.jadyer.vo; publicclass Student { private String username; privateint grade; /* 两个属性的setter和getter略 */ //只要是重写一个类的构造方法就必须要为这个类保留空的构造方法 //因为框架默认的都会去调用无参的空的构造方法 public Student(){}; public Student(String username,int grade){ this.username username; this.grade grade; } Override public String toString() { //如果不重写它的toString()方法的话默认调用toString()将输出【类型内存地址的哈希值】 return{学生姓名 username 成绩 grade }; } } [java] view plaincopy package com.jadyer.vo; public class User { private String username; private String password; private Address address; /* 三个属性的setter和getter略 */ public String getVOMethod(){ return 这是User类中的一个普通方法; } } package com.jadyer.vo; public class Address { //如果将TIPS设为private的话loginSuc.jsp中就无法获取它的属性值了 //事实上将一个静态的final属性设为private是毫无意义的 //因为既然设置成了静态那么就是供他人调用的如果再设成private的话别的地方根本就无法调用了 //即使OGNL再怎么强大它也不可能违反Java的规则所以不要将静态的属性设为私有 public static final String TIPS 玄玉加油!!; //addr属性的setter和getter略 private String addr; } package com.jadyer.vo; public class Student { private String username; private int grade; /* 两个属性的setter和getter略 */ //只要是重写一个类的构造方法就必须要为这个类保留空的构造方法 //因为框架默认的都会去调用无参的空的构造方法 public Student(){}; public Student(String username,int grade){ this.username username; this.grade grade; } Override public String toString() { //如果不重写它的toString()方法的话默认调用toString()将输出【类型内存地址的哈希值】 return {学生姓名 username 成绩 grade }; } } 最后是用来提供OGNL测试的数据的LoginAction.java [java] view plaincopyprint? package com.jadyer.action; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.struts2.interceptor.RequestAware; import org.apache.struts2.interceptor.SessionAware; import com.jadyer.vo.Student; import com.jadyer.vo.User; import com.opensymphony.xwork2.ActionSupport; SuppressWarnings({serial,unchecked}) publicclass LoginActionextends ActionSupport implements RequestAware,SessionAware { private User user; private List testList new ArrayList(); private Set testSet new HashSet(); private Map testMap new HashMap(); private List stus new ArrayList(); /* 以上五个属性的setter和getter略 */ private Map request; private Map session; publicvoid setRequest(Map request) { this.request request; } publicvoid setSession(Map session) { this.session session; } publicstatic String getStatic(){ return这是LoginAction中的一个静态方法; } public String getCommon(){ return这是LoginAction中的一个普通方法; } Override public String execute() throws Exception { if(user.getUsername().trim().equalsIgnoreCase(admin) user.getPassword().equals(jadyer)){ testList.add(list11); testList.add(list22); testList.add(list33); testList.add(list44); testList.add(list55); testSet.add(set11); testSet.add(set22); testSet.add(set33); testSet.add(set22); testSet.add(set11); testMap.put(m11, map11); testMap.put(m22,map22); testMap.put(m33, map33); testMap.put(m44,map44); testMap.put(m55, map55); stus.add(new Student(张三,88)); stus.add(new Student(李四,77)); stus.add(new Student(王五,66)); stus.add(new Student(马六,55)); request.put(req,这是通过OGNL中的#号获取的request属性范围的值); session.put(ses, 这是通过OGNL中的#号获取的session属性范围的值); request.put(BB,这是通过OGNL中的#号获取的request属性范围的BB); session.put(BB, 这是通过OGNL中的#号获取的session属性范围的BB); return SUCCESS; }else{ return INPUT; } } }