Struts2.2 OGNL

OGNL ,作为Struts2 一大亮点,感觉也是Struts2 中相对最难理解的一部分了。所以这里认真的总结学习一下。

值栈分析:

MVC 请求处理流程中,牵涉的数据种类比较多,框架使用ValueStack 数据结构对这些数据结构进行有机的整合,便于统一管理。充分认识ValueStack 数据结构可以便于框架使用者轻松自如获取所需的数据。

ValueStack 由ValueStack Contents 和Stack Context 两部分构成

    每个请求都会生成一个对应的Action 实例,每一个动作在执行相应方法( 默认execute 方法) 之前,都会创建一个ValueStack 的对象。ValueStack 用来保存这个动作对象和其他对象( 请求处理所涉及的数据);

    ValueStack 对象相当于一个栈,它贯穿整个Action 的生命周期,每个Action 类的对象实例都会拥有一个ValueStack 对象。

    当Struts2 接受到一个*.action 请求后,并不是直接调用Action 方法,而是先将Action 类的相应属性放到ValueStack 对象的顶层节点

    值栈也是位于内存中,它也是和parameters 、request 、session 、application 、attr 对象放在一起的。值栈属于ONGLContext 里面的根对象。也就是说它位于整个内存中最最重要的地方,所以叫根对象

根对象和另外五个对象是有区别的,根对象可以省写# 号,比如<s:property value="user.username"/> 。值栈的生命周期与request 请求相关,每次请求产生一个值栈。默认所有的Action 会被自动放到值栈里

生命周期内置对象被封装在一个Map 结构中。

在跳转的页面上加一个struts 标签-<s:debug/> 可以看到ValueStack 结构。

 

服务器跳转时共用值栈:

 

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

 

取值过程(原则:后进先出):

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

 

三个语法:

假设此时想要获取Action11 中的username 属性的话,就可以使用值栈的Top 语法 或者N 语法 。 
1 、使用Top 语法 获取值栈中的第二个对象的属性:

<s:property value="[1].top.username"/> 
2 、使用N 语法 获取值栈中的第二个对象的属性:<s:property value="[1].username"/> 
3 、@ 语法 ,例如使用@ 语法调用Action 中的静态方法:<s:property value="@vs @getVOMethod()"/> 
@vs @get() 等价于@vs1@getVOMethod() ,指的是栈顶对象的静态getVOMethod() 方法
同理@vs2@getVOMethod() 就是取值栈中第二个对象的静态getVOMethod() 方法

 

客户端跳转时使用各自的值栈:

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

 

手工向值栈中压入对象:

正 常情况下值栈保存的是Action 对象,而我们也可以直接往值栈中添加其它对象,这时可以在Action 中添加如下代码向值栈中添加对象:

ActionContext.getContext.getValueStack().push(new Student("xdwang",23)); 
而且我们手工往值栈中添加的Student 对象会位于栈顶 。这是因为Struts2 会首先初始化Action ,然后才能调用它的方法。初始化Action 的时候,便把Action 放到值栈中了,然后在执行它的execute() 方法时,就又往值栈中添加了Student 对象。

 

OGNL 历史:

    OGNL 最初是为了能够使用对象的属性名来建立 UI 组件 (component) 和 控制器 (controllers) 之间的联系,简单来说就是:视图与控制器之间数据的联系 。后来为了应付更加复杂的数据关系。

 

什么是OGNL :

OGNL 是 Object-Graph Navigation Language 的缩写, 对象图形导航语言 , ,从语言角度来说:它是一种操作复杂数据结构的常用语言 ,它旨在提供一个更高抽象度语法来对 java 对象图进行导航。

可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性;

    对象通过OgnlContext上下文对象来管理。

    OGNL可以让我们用非常简单的表达式访问对象层。

 

OGNL 应用:

1 、作为 GUI 元素(textfield,combobox, 等)到模型对象的绑定语言;

2 、数据库表到 Swing 的 TableModel 的数据源语言;

3 、web 组件和后台 Model 对象的绑定语言 (WebOGNL,Tapestry,WebWork,WebObjects) ;

4 、作为 Jakarata Commons BeanUtils 或者 JSTL 的表达式语言的一个更具表达力的替代语言;

 

为什么需要表达式语言 (EL)

表达式语言(EL)本质上被设计为:帮助你使用简单的表达式来完成一些“常用”的工作。通常情况下,ELs 可以在一些框架中找到,它被是用来简化我们的工作。例如:大家熟知的 Hibernate,使用 HQL(Hibernate Query Language) 来完成数据库的操作,HQL 成了开发人员与复查的 SQL 表达式之间的一个桥梁。 在 web 框架下,表达式语言起到了相似的目的。它的存在消除了重复代码的书写。例如:当没有 EL 的时候,为了从 session 中得到购物车并且将 ID 在网页上呈现出来,当直接在 jsp 中使用 java 代码来完成的时候,一般是:

Jsp代码    收藏代码
  1. <%   
  2.     ShoppingCart cart = (ShoppingCart) session.get("cart");   
  3.     int id = cart.getId();   
  4.     %>   
  5.     <%= id%>  

 

你也可以将这些 code 压缩成一句,如下,但是现在代码就很不直观,且不可读。另外,虽然变成了一句,但是与上面的原始的例子一样,也包含了同样的表达式。例如:类型转换:转换 成 ShoppingCart 。这里只不过是将原来的三个表达式变成了一句,其复杂度是没有得到简化的。

Jsp代码    收藏代码
  1. <%= ((ShoppingCart) session.get("cart")).getId() %>  

 

当在 web 框架中使用表达式语言的时候,则可以有效的处理这种代码的复杂性。而不需要你,调用 servelet API,类型转换,然后再调用 getter 方法,多数的 Els 都可将这个过程简化为类似于:#session.cart.id 这中更可读的表达式。 表达式:#session.cart.id 与 java 代码不一样的是:没有 java 代码的 get 方法调用和类型转换。因为这些操作是非常“常用”的,这时候使用 EL 就顺理成章了,使用 EL 可以“消除”这些代码。

 

OGNL标识符:

    “$”有两个主要的用途:

1、 用于在国际化资源文件中,引用OGNL表达式:

validation.require=${getText(fileName)} is required

2、 在Struts 2配置文件中,引用OGNL表达式:

Xml代码    收藏代码
  1. <action name="AddPhoto" class="addPhoto">  
  2.      <result type="redirect">  
  3.         ListPhotos.action?albumId=${albumId}  
  4.      </result>  
  5. </action>  

 

“# ”, 一般用于取出堆栈上下文中存放的对象和过滤、投影集合。这里我们可以将 # 理解为ActionContext.getContext()

1 、取出堆栈上下文:

名称

作用

Demo

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")

2、 用于过滤和投影(projecting)集合

如person.{?#this.age>20}

? -- 获取集合中所有满足选择逻辑的对象( 拿sql 来做比例就是"select * from xxx where age>20")

^ -- 获取集合中第一个满足选择逻辑的对象( 拿sql 来做比例就是"select top(1) from xxx where age>20")

$ -- 获取集合中最后一个满足选择逻辑的对象

 

    %:用途是在标识的属性为字符串类型时,计算OGNL表达式的值,即将原本的文本属性解析为ognl,对于本来就是ognl的属性不起作用

Jsp代码    收藏代码
  1. <s:url value="test.jsp?age=#userlist['admin']">→test.jsp?#userlist['admin']---可见当字符串与OGNL表达式串起来时,只会被当作字符串对待,并不执行  
  2. <s:url value="test.jsp?age=%{#userlist['admin']}">→test.jsp?age=44---使用了该符号,就可以使得OGNL表达式被执行  
 
Jsp代码    收藏代码
  1. <s:set name="hello" value="5"></s:set>  
  2. <s:property value="#hello" />   
  3. <s:property value="%{#hello}" />   
  4. <s:if test="%{#hello==5}">你好</s:if>  
  5. <s:if test="#hello==5">你好</s:if>  
  6.   
  7. <s:set name="china" value="'你好'"></s:set>  
  8. <s:property value="#china" />   
  9. <s:property value="%{#china}" />   
  10. <s:if test="%{#china=='你好'}">你好1</s:if>  
  11. <s:if test="#china=='你好'">你好2</s:if>  

 

注意上面的你好需要加引号,否则没有值;

 

获取Action 中的属性值或Action 对象的某某属性值

利用 Struts2 标签的 <s:property> 可以直接获取 Action 中的引用类型 user 里面的 name 属性。同样可以通过 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

 

说明:

1 、获取集合中元素的实质就是调用它的toString() 方法;

       2 、当OGNL 取不到值的时候,它是不会报错的,而是什么都不显示出来;

       3 、<s:property value="[0]"/> 返回的是ValueStack 中从上至下的所有的Object ,<s:property value="[1]"/>返回的是ValueStack 中从上至下的第二个Object ;

       4 、<s:property value="[0].username"/> 返回的是成员变量username 的值。假设ValueStack 中存在两个Action 的话,如果第一个Action 如果没有username 变量,那么它会继续找第二个Action 。那么在什么情况下ValueStack 中会存在两个Action 呢?答案是在struts.xml 中配置的是从一个Action 通过<result type="chain"> 跳转到另一个Action ;

5 、<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>

在Struts2.1.6 、Struts2.2 中必须设置struts.ognl.allowStaticMethodAccess 为true 之后才允许使用OGNL 访问静态方法。而在Struts2.0.11 则无需设置,即可直接访问;

通过下面的Demo发现2.2版本中如果不在Struts.xml中配置< constant name ="struts.ognl.allowStaticMethodAccess" value = "true" /> 会出现普通类中的静态属性和方法可以访问,而Action中的静态属性和方法以及jdk中的静态属性方法都无法访问。

 

Demo 

web.xml :

Xml代码    收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.     xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
  5.     id="WebApp_ID" version="2.5">  
  6.     <display-name>OGNLDemo</display-name>  
  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>  

 

struts.xml :

Xml代码    收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.1.7.dtd">  
  5. <struts>  
  6.     <constant name="struts.ognl.allowStaticMethodAccess" value="true"/>  
  7.     <package name="ognl" extends="struts-default">  
  8.         <action name="login" class="com.iflytek.action.LoginAction">  
  9.             <result name="input">/login.jsp</result>  
  10.             <result name="success">/loginSuc.jsp?netname=xdwang</result>  
  11.             <!-- <result name="success" type="redirect">/loginSuc.jsp?netname=xdwang</result>   
  12.                 <result name="success" type="redirect">/loginSuc.jsp?netname=${user.username}</result> -->  
  13.         </action>  
  14.     </package>  
  15. </struts>    
 

 

Address.java:

Java代码    收藏代码
  1. package com.iflytek.entity;  
  2.   
  3. /** 
  4.  * @author xdwang 
  5.  *  
  6.  * @ceate 2012-6-27 上午12:29:38 
  7.  *  
  8.  * @description Address实体 
  9.  *  
  10.  */  
  11. public class Address {  
  12.     public static final String TIPS = "xdwang";  
  13.   
  14.     private String addr;  
  15.   
  16.     public String getAddr() {  
  17.         return addr;  
  18.     }  
  19.   
  20.     public void setAddr(String addr) {  
  21.         this.addr = addr;  
  22.     }  
  23. }  

 

Student.java:

Java代码    收藏代码
  1. package com.iflytek.entity;  
  2.   
  3. /** 
  4.  * @author xdwang 
  5.  *  
  6.  * @ceate 2012-6-27 上午12:31:07 
  7.  *  
  8.  * @description Student实体 
  9.  *  
  10.  */  
  11. public class Student {  
  12.   
  13.     private String username;  
  14.     private int grade;  
  15.   
  16.     public Student() {  
  17.     }  
  18.   
  19.     public Student(String username, int grade) {  
  20.         this.username = username;  
  21.         this.grade = grade;  
  22.     }  
  23.   
  24.     public String getUsername() {  
  25.         return username;  
  26.     }  
  27.   
  28.     public void setUsername(String username) {  
  29.         this.username = username;  
  30.     }  
  31.   
  32.     public int getGrade() {  
  33.         return grade;  
  34.     }  
  35.   
  36.     public void setGrade(int grade) {  
  37.         this.grade = grade;  
  38.     }  
  39.   
  40.     @Override  
  41.     public String toString() {  
  42.         // 如果不重写它的toString()方法的话,默认调用toString()将输出【类型+@+内存地址的哈希值】  
  43.         return "{学生姓名:" + username + ",成绩:" + grade + "}";  
  44.     }  
  45.   
  46. }  

 

User.java:

Java代码    收藏代码
  1. package com.iflytek.entity;  
  2.   
  3. /** 
  4.  *  
  5.  * @author xdwang 
  6.  *  
  7.  * @ceate 2012-6-27 上午12:29:11 
  8.  *  
  9.  * @description User实体 
  10.  *  
  11.  */  
  12. public class User {  
  13.     private String username;  
  14.     private String password;  
  15.     private Address address;  
  16.   
  17.     public String getUsername() {  
  18.         return username;  
  19.     }  
  20.   
  21.     public void setUsername(String username) {  
  22.         this.username = username;  
  23.     }  
  24.   
  25.     public String getPassword() {  
  26.         return password;  
  27.     }  
  28.   
  29.     public void setPassword(String password) {  
  30.         this.password = password;  
  31.     }  
  32.   
  33.     public Address getAddress() {  
  34.         return address;  
  35.     }  
  36.   
  37.     public void setAddress(Address address) {  
  38.         this.address = address;  
  39.     }  
  40.   
  41.     public String getVOMethod() {  
  42.         return "这是User类中的一个普通方法";  
  43.     }  
  44. }  
 

 

LoginAction.java:

Java代码    收藏代码
  1. package com.iflytek.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.iflytek.entity.Student;  
  14. import com.iflytek.entity.User;  
  15. import com.opensymphony.xwork2.ActionSupport;  
  16.   
  17. /** 
  18.  * @author xdwang 
  19.  *  
  20.  * @ceate 2012-6-27 上午12:33:18 
  21.  *  
  22.  * @description 登陆Action 
  23.  *  
  24.  */  
  25. @SuppressWarnings("serial")  
  26. public class LoginAction extends ActionSupport implements RequestAware,  
  27.         SessionAware {  
  28.     private User user;  
  29.     private List<String> testList = new ArrayList<String>();  
  30.     private Set<String> testSet = new HashSet<String>();  
  31.     private Map<String, String> testMap = new HashMap<String, String>();  
  32.     private List<Student> stus = new ArrayList<Student>();  
  33.   
  34.     private Map<String, String> request;  
  35.     private Map<String, String> session;  
  36.   
  37.     public void setRequest(Map request) {  
  38.         this.request = request;  
  39.     }  
  40.   
  41.     public void setSession(Map session) {  
  42.         this.session = session;  
  43.     }  
  44.   
  45.     public static String getStatic() {  
  46.         return "这是LoginAction中的一个静态方法";  
  47.     }  
  48.   
  49.     public String getCommon() {  
  50.         return "这是LoginAction中的一个普通方法";  
  51.     }  
  52.   
  53.     @Override  
  54.     public String execute() throws Exception {  
  55.         if (user.getUsername().trim().equalsIgnoreCase("xdwang")  
  56.                 && user.getPassword().equals("1111")) {  
  57.             testList.add("list11");  
  58.             testList.add("list22");  
  59.             testList.add("list33");  
  60.             testList.add("list44");  
  61.             testList.add("list55");  
  62.   
  63.             testSet.add("set11");  
  64.             testSet.add("set22");  
  65.             testSet.add("set33");  
  66.             testSet.add("set22");  
  67.             testSet.add("set11");  
  68.   
  69.             testMap.put("m11""map11");  
  70.             testMap.put("m22""map22");  
  71.             testMap.put("m33""map33");  
  72.             testMap.put("m44""map44");  
  73.             testMap.put("m55""map55");  
  74.   
  75.             stus.add(new Student("张三"88));  
  76.             stus.add(new Student("李四"77));  
  77.             stus.add(new Student("王五"66));  
  78.             stus.add(new Student("马六"55));  
  79.   
  80.             request.put("req""这是通过OGNL中的#号获取的request属性范围的值");  
  81.             session.put("ses""这是通过OGNL中的#号获取的session属性范围的值");  
  82.             request.put("BB""这是通过OGNL中的#号获取的request属性范围的BB");  
  83.             session.put("BB""这是通过OGNL中的#号获取的session属性范围的BB");  
  84.             return SUCCESS;  
  85.         } else {  
  86.             return INPUT;  
  87.         }  
  88.     }  
  89.   
  90.     public User getUser() {  
  91.         return user;  
  92.     }  
  93.   
  94.     public void setUser(User user) {  
  95.         this.user = user;  
  96.     }  
  97.   
  98.     public List<String> getTestList() {  
  99.         return testList;  
  100.     }  
  101.   
  102.     public void setTestList(List<String> testList) {  
  103.         this.testList = testList;  
  104.     }  
  105.   
  106.     public Set<String> getTestSet() {  
  107.         return testSet;  
  108.     }  
  109.   
  110.     public void setTestSet(Set<String> testSet) {  
  111.         this.testSet = testSet;  
  112.     }  
  113.   
  114.     public Map<String, String> getTestMap() {  
  115.         return testMap;  
  116.     }  
  117.   
  118.     public void setTestMap(Map<String, String> testMap) {  
  119.         this.testMap = testMap;  
  120.     }  
  121.   
  122.     public List<Student> getStus() {  
  123.         return stus;  
  124.     }  
  125.   
  126.     public void setStus(List<Student> stus) {  
  127.         this.stus = stus;  
  128.     }  
  129.   
  130. }  

 

login.jsp:

Jsp代码    收藏代码
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7. <meta http-equiv="pragma" content="no-cache">  
  8. <meta http-equiv="cache-control" content="no-cache">  
  9. <meta http-equiv="expires" content="0">  
  10. <title>OGNL Demo</title>  
  11. </head>  
  12. <body>  
  13.     <h1>这是测试OGNL使用的登录页面</h1>  
  14.     <h3>  
  15.         <font color="red">提示:</font>程序设定的用户名和密码各为<font color="blue"><strong>xdwang</strong></font>和<font  
  16.             color="blue"><strong>1111</strong></font>  
  17.     </h3>  
  18.     <h3>  
  19.         <font color="red">注意:</font>用户名和密码不正确时将停留在页面不动  
  20.     </h3>  
  21.     <form action="<%=request.getContextPath()%>/login.action" method="POST">  
  22.         <%--这里user.username匹配的是LoginAction中的引用类型user里面的username属性--%>  
  23.         <%--查看标签库说明的话,就知道name中指定的是对象。这里它不是字符串,而是OGNL表达式--%>  
  24.         姓名:<input type="text" name="user.username"><br> 密码:<input  
  25.             type="text" name="user.password"><br> 地址:<input  
  26.             type="text" name="user.address.addr"><br> <input  
  27.             type="submit" value="测试OGNL的输出">  
  28.     </form>  
  29. </body>  
  30. </html>  

 

loginSuc.jsp:

Jsp代码    收藏代码
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <%@ taglib prefix="s" uri="/struts-tags"%>  
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  5. <html>  
  6. <head>  
  7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  8. <meta http-equiv="pragma" content="no-cache">  
  9. <meta http-equiv="cache-control" content="no-cache">  
  10. <meta http-equiv="expires" content="0">  
  11. <title>OGNL Demo</title>  
  12. </head>  
  13. <body>  
  14.     <h1>这是使用OGNL输出的结果页面</h1>  
  15.     <table border="9">  
  16.         <tr>  
  17.             <td align="right">获取姓名属性:</td>  
  18.             <td align="left"><s:property value="user.username" /></td>  
  19.             <%-- 另外还有两种写法也是可以正常输出值栈中对象的普通属性的 --%>  
  20.             <%-- <s:property value="user['username']"/> --%>  
  21.             <%-- <s:property value="user[/"username/"]"/> --%>  
  22.             <%-- 但是如果写成下面这种形式的话,就什么都不会输出了 --%>  
  23.             <%-- <s:property value="user[username]"/> --%>  
  24.         </tr>  
  25.         <tr>  
  26.             <td align="right">获取地址属性:</td>  
  27.             <td align="left"><s:property value="user.address.addr" /></td>  
  28.         </tr>  
  29.         <tr>  
  30.             <td align="right">调用值栈中的对象的普通方法:</td>  
  31.             <td align="left"><s:property value="user.getVOMethod()" /></td>  
  32.         </tr>  
  33.         <tr>  
  34.             <td align="right">调用值栈中Action的普通方法:</td>  
  35.             <td align="left"><s:property value="getCommon()" /></td>  
  36.         </tr>  
  37.     </table>  
  38.     <hr />  
  39.     <table border="9">  
  40.         <tr>  
  41.             <td align="right">获取普通类的静态属性:</td>  
  42.             <td align="left"><s:property value="@com.iflytek.entity.Address@TIPS" /></td>  
  43.         </tr>  
  44.         <tr>  
  45.             <td align="right">访问普通类的构造方法:</td>  
  46.             <td align="left"><s:property  
  47.                     value="new com.iflytek.entity.Student('xdwang',23).username" /></td>  
  48.         </tr>  
  49.         <tr>  
  50.             <td align="right">调用Action中的静态方法:</td>  
  51.             <td align="left"><s:property value="@com.iflytek.action.LoginAction@getStatic()" /></td>  
  52.         </tr>  
  53.         <tr>  
  54.             <td align="right">调用JDK中的类的静态方法:</td>  
  55.             <td align="left"><s:property  
  56.                     value="@java.util.Calendar@getInstance().time" /></td>  
  57.         </tr>  
  58.         <tr>  
  59.             <td align="right">调用JDK中的类的静态方法:</td>  
  60.             <td align="left"><s:property  
  61.                     value="@java.lang.Math@floor(46.58)" /></td>  
  62.         </tr>  
  63.         <tr>  
  64.             <td align="right">调用JDK中的类的静态方法:</td>  
  65.             <td align="left"><s:property value="@@floor(46.58)" /></td>  
  66.         </tr>  
  67.     </table>  
  68.     <hr />  
  69.     <table border="9">  
  70.         <tr>  
  71.             <td align="right">获取List中的所有元素:</td>  
  72.             <td align="left"><s:property value="testList" /></td>  
  73.         </tr>  
  74.         <tr>  
  75.             <td align="right">获取Set中的所有元素:</td>  
  76.             <td align="left"><s:property value="testSet" /></td>  
  77.         </tr>  
  78.         <tr>  
  79.             <td align="right">获取Map中的所有元素:</td>  
  80.             <td align="left"><s:property value="testMap" /></td>  
  81.         </tr>  
  82.         <tr>  
  83.             <td align="right">获取Map中的某个m22元素:</td>  
  84.             <td align="left"><s:property value="testMap['m22']" /></td>  
  85.             <%-- 另外还有两种写法也是可以正常获取Map中的某个具体元素的 --%>  
  86.             <%-- <s:property value="testMap.m22"/> --%>  
  87.             <%-- <s:property value="testMap[/"m22/"]"/> --%>  
  88.         </tr>  
  89.         <tr>  
  90.             <td align="right">获取Set中的某个元素:</td>  
  91.             <%-- 由于Set中的元素是无顺序的,所以不能使用下标获取数据,所以这里什么也得不到 --%>  
  92.             <td align="left"><s:property value="testSet[2]" /></td>  
  93.         </tr>  
  94.         <tr>  
  95.             <td align="right">获取List中的某个元素:</td>  
  96.             <td align="left"><s:property value="testList[2]" /></td>  
  97.         </tr>  
  98.     </table>  
  99.     <hr />  
  100.     <table border="9">  
  101.         <tr>  
  102.             <td align="right">获取List的大小:</td>  
  103.             <td align="left"><s:property value="testList.size" /></td>  
  104.         </tr>  
  105.         <tr>  
  106.             <td align="right">获取Set的大小:</td>  
  107.             <td align="left"><s:property value="testSet.size" /></td>  
  108.         </tr>  
  109.         <tr>  
  110.             <td align="right">获取Map的大小:</td>  
  111.             <td align="left"><s:property value="testMap.size" /></td>  
  112.         </tr>  
  113.         <tr>  
  114.             <td align="right">获取Map中所有的键:</td>  
  115.             <td align="left"><s:property value="testMap.keys" /></td>  
  116.         </tr>  
  117.         <tr>  
  118.             <td align="right">获取Map中所有的值:</td>  
  119.             <td align="left"><s:property value="testMap.values" /></td>  
  120.         </tr>  
  121.         <tr>  
  122.             <td align="right">Lambda计算4的阶乘:</td>  
  123.             <td align="left"><s:property  
  124.                     value="#f= :[#this==1?1 : #this*#f(#this-1)],#f(4)" /></td>  
  125.         </tr>  
  126.     </table>  
  127.     <hr />  
  128.     <table border="9">  
  129.         <tr>  
  130.             <td align="right">获取List中的所有对象:</td>  
  131.             <td align="left"><s:property value="stus" /></td>  
  132.         </tr>  
  133.         <tr>  
  134.             <td align="right">利用投影获取List中对象的名字:</td>  
  135.             <td align="left"><s:property value="stus.{username}" /></td>  
  136.         </tr>  
  137.         <tr>  
  138.             <td align="right">利用投影获取List中第二个对象的名字:</td>  
  139.             <%-- 使用<s:property value="stus[1].{username}"/>获取到的值为:[李四] --%>  
  140.             <%-- 二者的区别在于:后者比前者多了一个中括号 --%>  
  141.             <td align="left"><s:property value="stus.{username}[1]" /> <s:property  
  142.                     value="stus[1].{username}" /></td>  
  143.         </tr>  
  144.         <tr>  
  145.             <td align="right">利用选择获取List中成绩及格的所有对象:</td>  
  146.             <td align="left"><s:property value="stus.{?#this.grade>=60}" /></td>  
  147.         </tr>  
  148.         <tr>  
  149.             <td align="right">利用选择获取List中成绩及格的第一个对象:</td>  
  150.             <td align="left"><s:property value="stus.{^#this.grade>=60}" /></td>  
  151.         </tr>  
  152.         <tr>  
  153.             <td align="right">利用选择获取List中成绩及格的最后一个对象:</td>  
  154.             <td align="left"><s:property value="stus.{$#this.grade>=60}" /></td>  
  155.         </tr>  
  156.     </table>  
  157.     <hr />  
  158.     <table border="9">  
  159.         <tr>  
  160.             <td align="right">利用选择获取List中成绩及格的所有对象的名字:</td>  
  161.             <td align="left"><s:property  
  162.                     value="stus.{?#this.grade>=60}.{username}" /></td>  
  163.         </tr>  
  164.         <tr>  
  165.             <td align="right">利用选择获取List中成绩及格的第二个对象的名字:</td>  
  166.             <td align="left"><s:property  
  167.                     value="stus.{?#this.grade>=60}.{username}[1]" /></td>  
  168.         </tr>  
  169.         <tr>  
  170.             <td align="right">利用选择获取List中成绩及格的第一个对象的名字:</td>  
  171.             <td align="left"><s:property  
  172.                     value="stus.{^#this.grade>=60}.{username}" /></td>  
  173.         </tr>  
  174.         <tr>  
  175.             <td align="right">利用选择获取List中成绩及格的最后一个对象的名字:</td>  
  176.             <td align="left"><s:property  
  177.                     value="stus.{$#this.grade>=60}.{username}" /></td>  
  178.         </tr>  
  179.         <tr>  
  180.             <td align="right">利用选择获取List中成绩及格的第一个对象然后求大小:</td>  
  181.             <td align="left"><s:property  
  182.                     value="stus.{^#this.grade>=60}.{username}.size" /></td>  
  183.         </tr>  
  184.     </table>  
  185.     <hr />  
  186.     <table border="9">  
  187.         <tr>  
  188.             <td align="right">利用OGNL中的#号获取attr中的属性:</td>  
  189.             <td align="left"><s:property value="#attr.BB" /></td>  
  190.         </tr>  
  191.         <tr>  
  192.             <td align="right">利用OGNL中的#号获取request范围中的属性:</td>  
  193.             <td align="left"><s:property value="#request.req" /></td>  
  194.         </tr>  
  195.         <tr>  
  196.             <td align="right">利用OGNL中的#号获取session范围中的属性:</td>  
  197.             <td align="left"><s:property value="#session.ses" /></td>  
  198.         </tr>  
  199.         <tr>  
  200.             <td align="right">利用OGNL中的#号获取Paraments对象的属性:</td>  
  201.             <td align="left"><s:property value="#parameters.netname" /></td>  
  202.         </tr>  
  203.         <tr>  
  204.             <td align="right">使用&#60;&#37;=request.getParameter&#40;""&#41;&#37;&#62;或者&#36;&#123;param.name&#125;获取链接参数值:</td>  
  205.             <td align="left">${param.netname} <%=request.getParameter("netname")%>  
  206.             </td>  
  207.         </tr>  
  208.         <tr>  
  209.             <td align="right">查看值栈中的信息:</td>  
  210.             <td align="left"><s:debug /></td>  
  211.         </tr>  
  212.     </table>  
  213. </body>  
  214. </html>  

转载于:https://my.oschina.net/u/208942/blog/68090

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值