struts2中的OGNL表达式(转)

转载:http://blog.csdn.net/jadyer/article/details/6174555

浅析值栈

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   I

terator的伪属性: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测试的工程代码

1. web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
      <filter>
          <filter-name>struts2</filter-name>
          <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>struts2</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>
</web-app>

2. 测试页面login.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page isELIgnored="false"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<h1>这是测试OGNL使用的登录页面</h1>
<h3><font color="red">提示:</font>程序设定的用户名和密码各为<font color="blue"><strong>admin</strong></font><font color="blue"><strong>jadyer</strong></font></h3>
<h3><font color="red">注意:</font>用户名和密码不正确时将停留在页面不动</h3>
<s:form action="loginOgnl.action" method="post">
    <%--这里user.username匹配的是LoginAction中的引用类型user里面的username属性--%>
    <%--查看标签库说明的话,就知道name中指定的是对象。这里它不是字符串,而是OGNL表达式--%>
    姓名:<s:textfield name="user.username"></s:textfield>
    <br/>
    密码:<s:textfield name="user.password"></s:textfield>
    <br/>
    地址:<s:textfield name="user.address.addr"></s:textfield>
    <br/>
    <s:submit value="测试OGNL的输出"></s:submit>
    <s:actionerror />
</s:form>

3. 显示结果的loginSuc.jsp页面

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<h1>这是使用OGNL输出的结果页面</h1>
<table border="9">
    <tr>
        <td align="right">获取姓名属性:</td>
        <td align="left"><s:property value="user.username"/></td>
        <%-- 另外还有两种写法也是可以正常输出值栈中对象的普通属性的 --%>
        <%-- <s:property value="user['username']"/> --%>
        <%-- <s:property value="user[/"username/"]"/> --%>
        <%-- 但是如果写成下面这种形式的话,就什么都不会输出了 --%>
        <%-- <s:property value="user[username]"/> --%>
    </tr>
    <tr>
        <td align="right">获取地址属性:</td>
        <td align="left"><s:property value="user.address.addr"/></td>
    </tr>
    <tr>
        <td align="right">调用值栈中的对象的普通方法:</td>
        <td align="left"><s:property value="user.getVOMethod()"/></td>
    </tr>
    <tr>
        <td align="right">调用值栈中Action的普通方法:</td>
        <td align="left"><s:property value="getCommon()"/></td>
    </tr>
</table>
<hr/>
<table border="9">
    <tr>
        <td align="right">获取普通类的静态属性:</td>
        <td align="left"><s:property value="@com.clzhang.ssh.demo7.Address@TIPS"/></td>
    </tr>
    <tr>
        <td align="right">访问普通类的构造方法:</td>
        <td align="left"><s:property value="new com.clzhang.ssh.demo7.Student('张小三',22).username"/></td>
    </tr>
    <tr>
        <td align="right">调用Action中的静态方法:</td>
        <td align="left"><s:property value="@com.clzhang.ssh.demo7.LoginAction@getStatic()"/></td>
    </tr>
    <tr>
        <td align="right">JDK中类静态方法(生成实例,调用方法):</td>
        <td align="left">当前日期:<s:property value="@java.util.Calendar@getInstance().time"/></td>
    </tr>
    <tr>
        <td align="right">JDK类静态方法(带参数):</td>
        <td align="left">ceil(46.58)=<s:property value="@java.lang.Math@ceil(46.58)"/></td>
    </tr>
    <tr>
        <td align="right">JDK类静态方法(省略类名):</td>
        <td align="left">floor(46.58)=<s:property value="@@floor(46.58)"/></td>
    </tr>
</table>
<hr/>
<table border="9">
    <tr>
        <td align="right">获取List中的所有元素:</td>
        <td align="left"><s:property value="testList"/></td>
    </tr>
    <tr>
        <td align="right">获取Set中的所有元素:</td>
        <td align="left"><s:property value="testSet"/></td>
    </tr>
    <tr>
        <td align="right">获取Map中的所有元素:</td>
        <td align="left"><s:property value="testMap"/></td>
    </tr>
    <tr>
        <td align="right">获取Map中的某个元素:</td>
        <td align="left">m22对应的值=<s:property value="testMap['m22']"/></td>
        <%-- 另外还有两种写法也是可以正常获取Map中的某个具体元素的 --%>
        <%-- <s:property value="testMap.m22"/> --%>
        <%-- <s:property value="testMap[/"m22/"]"/> --%>
    </tr>
    <tr>
        <td align="right">获取Set中的某个元素:</td>
        <%-- 由于Set中的元素是无顺序的,所以不能使用下标获取数据,所以这里什么也得不到 --%>
        <td align="left">Set为无序,所以获取不到值!<s:property value="testSet[2]"/></td>
    </tr>
    <tr>
        <td align="right">获取List中的某个元素:</td>
        <td align="left">List有序,所以有值:<s:property value="testList[2]"/></td>
    </tr>
</table>
<hr/>
<table border="9">
    <tr>
        <td align="right">获取List的大小:</td>
        <td align="left"><s:property value="testList.size"/></td>
    </tr>
    <tr>
        <td align="right">获取Set的大小:</td>
        <td align="left"><s:property value="testSet.size"/></td>
    </tr>
    <tr>
        <td align="right">获取Map的大小:</td>
        <td align="left"><s:property value="testMap.size"/></td>
    </tr>
    <tr>
        <td align="right">获取Map中所有的键:</td>
        <td align="left"><s:property value="testMap.keys"/></td>
    </tr>
    <tr>
        <td align="right">获取Map中所有的值:</td>
        <td align="left"><s:property value="testMap.values"/></td>
    </tr>
    <tr>
        <td align="right">Lambda计算4的阶乘:</td>
        <td align="left"><s:property value="#f= :[#this==1?1 : #this*#f(#this-1)],#f(4)"/></td>
    </tr>
</table>
<hr/>
<table border="9">
    <tr>
        <td align="right">获取List中的所有对象:</td>
        <td align="left"><s:property value="stus"/></td>
    </tr>
    <tr>
        <td align="right">利用投影获取List中对象的名字:</td>
        <td align="left"><s:property value="stus.{username}"/></td>
    </tr>
    <tr>
        <td align="right">利用投影获取List中第二个对象的名字:</td>
        <%-- 使用<s:property value="stus[1].{username}"/>获取到的值为:[李四] --%>
        <%-- 二者的区别在于:后者比前者多了一个中括号 --%>
        <td align="left">
            方式1:<s:property value="stus.{username}[1]"/>
            方式2:<s:property value="stus[1].{username}"/>
        </td>
    </tr>
    <tr>
        <td align="right">利用选择获取List中成绩及格的所有对象:</td>
        <td align="left"><s:property value="stus.{?#this.grade>=60}"/></td>
    </tr>
    <tr>
        <td align="right">利用选择获取List中成绩及格的第一个对象:</td>
        <td align="left"><s:property value="stus.{^#this.grade>=60}"/></td>
    </tr>
    <tr>
        <td align="right">利用选择获取List中成绩及格的最后一个对象:</td>
        <td align="left"><s:property value="stus.{$#this.grade>=60}"/></td>
    </tr>
</table>
<hr/>
<table border="9">
    <tr>
        <td align="right">利用选择获取List中成绩及格的所有对象的名字:</td>
        <td align="left"><s:property value="stus.{?#this.grade>=60}.{username}"/></td>
    </tr>
    <tr>
        <td align="right">利用选择获取List中成绩及格的第二个对象的名字:</td>
        <td align="left"><s:property value="stus.{?#this.grade>=60}.{username}[1]"/></td>
    </tr>
    <tr>
        <td align="right">利用选择获取List中成绩及格的第一个对象的名字:</td>
        <td align="left"><s:property value="stus.{^#this.grade>=60}.{username}"/></td>
    </tr>
    <tr>
        <td align="right">利用选择获取List中成绩及格的最后一个对象的名字:</td>
        <td align="left"><s:property value="stus.{$#this.grade>=60}.{username}"/></td>
    </tr>
    <tr>
        <td align="right">利用选择获取List中成绩及格的第一个对象然后求大小:</td>
        <td align="left"><s:property value="stus.{^#this.grade>=60}.{username}.size"/></td>
    </tr>
</table>
<hr/>
<table border="9">
    <tr>
        <td align="right">利用OGNL中的#号获取attr中的属性:</td>
        <td align="left"><s:property value="#attr.BB"/></td>
    </tr>
    <tr>
        <td align="right">利用OGNL中的#号获取request范围中的属性:</td>
        <td align="left"><s:property value="#request.req"/></td>
    </tr>
    <tr>
        <td align="right">利用OGNL中的#号获取session范围中的属性:</td>
        <td align="left"><s:property value="#session.ses"/></td>
    </tr>
    <tr>
        <td align="right">利用OGNL中的#号获取Paraments对象的属性:</td>
        <td align="left"><s:property value="#parameters.netname"/></td>
    </tr>
    <tr>
        <td align="right">使用&#60;&#37;=request.getParameter&#40;""&#41;&#37;&#62;或者&#36;&#123;param.name&#125;获取链接参数值:</td>
        <td align="left">
            ${param.netname}      
            <%=request.getParameter("netname")%>
        </td>
    </tr>
    <tr>
        <td align="right">查看值栈中的信息:</td>
        <td align="left"><s:debug/></td>
    </tr>
</table>

4. 创建struts.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
    
<struts>
    <package name="myStruts" extends="struts-default">
        <action name="loginOgnl" class="com.clzhang.ssh.demo7.LoginAction">
            <result name="input">/ssh/demo7/login.jsp</result>
            <result name="success">/ssh/demo7/loginSuc.jsp?netname=hongyu</result>
        </action>

    </package>

    <constant name="struts.ui.theme" value="simple"></constant>
    <constant name="struts.action.extension" value="action"></constant>
    <constant name="struts.ognl.allowStaticMethodAccess" value="true" />
</struts>

5. 三个VO类

package com.clzhang.ssh.demo7;

public class User {
    private String username;
    private String password;
    private Address address;

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    public String getVOMethod() {
        return "这是User类中的一个普通方法";
    }
}
package com.clzhang.ssh.demo7;

public class Address {
    //如果将TIPS设为private的话,loginSuc.jsp中就无法获取它的属性值了
    //事实上将一个静态的final属性设为private是毫无意义的
    //因为既然设置成了静态,那么就是供他人调用的,如果再设成private的话,别的地方根本就无法调用了
    //即使OGNL再怎么强大,它也不可能违反Java的规则,所以不要将静态的属性设为私有
    public static final String TIPS = "玄玉加油!!";

    private String addr;

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }
}
package com.clzhang.ssh.demo7;

public class Student {
    private String username;
    private int grade;
    
    //只要是重写一个类的构造方法,就必须要为这个类保留空的构造方法
    //因为框架默认的都会去调用无参的空的构造方法
    public Student(){};
    public Student(String username,int grade){
        this.username = username;
        this.grade = grade;
    }
    
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public int getGrade() {
        return grade;
    }
    public void setGrade(int grade) {
        this.grade = grade;
    }
    
    @Override
    public String toString() {
        //如果不重写它的toString()方法的话,默认调用toString()将输出【类型+@+内存地址的哈希值】
        return "{学生姓名:" + username + ",成绩:" + grade + "}";
    }
}

6. 提供OGNL测试的数据的LoginAction.java

package com.clzhang.ssh.demo7;

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.opensymphony.xwork2.ActionSupport;

@SuppressWarnings({"serial", "unchecked"})
public class LoginAction extends 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();
    
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public List getTestList() {
        return testList;
    }
    public void setTestList(List testList) {
        this.testList = testList;
    }
    public Set getTestSet() {
        return testSet;
    }
    public void setTestSet(Set testSet) {
        this.testSet = testSet;
    }
    public Map getTestMap() {
        return testMap;
    }
    public void setTestMap(Map testMap) {
        this.testMap = testMap;
    }
    public List getStus() {
        return stus;
    }
    public void setStus(List stus) {
        this.stus = stus;
    }

    private Map request;
    private Map session;
    public void setRequest(Map request) {
        this.request = request;
    }
    public void setSession(Map session) {
        this.session = session;
    }

    public static 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 {
            // 设置一些默认值,如果登录错误的话
            user.setUsername("admin");
            user.setPassword("jadyer");
            this.addActionError("您输入的用户名、密码有错,系统自动为您设置!");
            if(user.getAddress().getAddr().equals("")) {
                this.addActionError("建议输入一个地址信息,以查看实际效果!");
            }
            
            return INPUT;
        }
    }
}

7. 测试

打开IE,输入地址:http://127.0.0.1:8080/st/ssh/demo7/login.jsp

7.1 打开后,页面如下图所示:

7.2 直接提交后,如下图所示:

7.3 再度提交后,ONGL结果页面显示出来:

 

 

posted @ 2013-12-09 14:19  那些年的事儿  阅读(1267)  评论(0编辑  收藏  举报