S7.2_Struts2_OGNL OGNL表达式的投影和选择技术范例,OGNL表达式#和$符号的使用范例,以及值栈

来源:互联网 发布:windows应用商店误删 编辑:程序博客网 时间:2024/06/04 19:28
OGNL表达式:
投影
选择
#符号的使用
$符号的使用
值栈技术

我们接下来将要创建的项目目录结构如下:
由项目S7.1_Struts2_OGNL(如何下载它)复制生成一个新项目S7.2_Struts2_OGNL

投影
#this 表示当前集合对象
?     表示获取集合里的所有元素
^     表示获取集合里的第1个元素
$     表示获取集合里的最后1个元素

第1步: 在net.nw.vo包下创建一个学生类实体Student.java

package net.nw.vo;
//学生类
public class Student {
    private String name;
    private int age;
    public Student(){}
    public Student(String name,int age){
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

第2步:在net.nw.action包中找到UserAction2.java动作类,实例化List<Student> ,实现它的get和set 方法,这样stu对象可以被压入值栈,注意红色字体标识的代码:

package net.nw.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.ApplicationAware;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import net.nw.dao.UserDao;
import net.nw.vo.Contact;
import net.nw.vo.Student;
import net.nw.vo.User;
public class UserAction2 extends ActionSupport implements ModelDriven<User>,RequestAware,SessionAware,ApplicationAware{
    /**
     * 对象序列化需要此serialVersionUID
     */
    private static final long serialVersionUID = 1L;
    private User user = new User();//注意:此处user一定要实例化
    private Map<String,Object>  request;//IOC注入来初始化对象
    private Map<String,Object>  session;
    private Map<String,Object>  application;
    public static String sid = "21377137713X";
    private List<Contact> contactors = new ArrayList<Contact>();
    private Set<String> cities = new HashSet<String>();
    private Map<String,String> dics = new HashMap<String,String>();
    private List<Student> stus = new ArrayList<Student>();
    public List<Student> getStus() {
        return stus;
    }
    public void setStus(List<Student> stus) {
        this.stus = stus;
    }

    public List<Contact> getContactors() {
        return contactors;
    }
    public void setContactors(List<Contact> contactors) {
        this.contactors = contactors;
    }
    public Set<String> getCities() {
        return cities;
    }
    public void setCities(Set<String> cities) {
        this.cities = cities;
    }
    public Map<String, String> getDics() {
        return dics;
    }
    public void setDics(Map<String, String> dics) {
        this.dics = dics;
    }
    public UserAction2() {
        System.out.println("构造方法UserAction2 ......");
        contactors.add(new Contact("tom@136.com","13000000001","beijing"));
        contactors.add(new Contact("jack@126.com","13500000001","shanghai"));
        contactors.add(new Contact("mike@qq.com","13600000001","guangzhou"));
        cities.add("beijing");
        cities.add("shanghai");
        cities.add("xi'an");
        dics.put("001", "zhangsan");
        dics.put("002", "lisi");
        dics.put("003", "wangwu");
        stus.add(new Student("杨帆",25));
        stus.add(new Student("田野",37));
        stus.add(new Student("夏天",29));
        stus.add(new Student("周季",31));
        stus.add(new Student("陈墨",30));

    }
    //调用业务层操作类的方法
    public String execute(){
        UserDao dao = new UserDao();
        if(dao.userLogin(user)){
            request.put("msg", "北京欢迎您!");
            session.put("msg", "北京欢迎您!");
            application.put("msg", "北京欢迎您!");
            return "login_success";
        } else{
            this.addFieldError("login_error","用户名称或者用户密码不正确");
            return "login_failure";
        }
    }
    @Override
    public User getModel() {
        // TODO Auto-generated method stub
        return user;
    }
    public String add(){
        System.out.println("普通用户添加 ...");
        return SUCCESS;
    }
    public String delete(){
        System.out.println("普通用户删除 ...");
        return SUCCESS;
    }
    public String modify(){
        System.out.println("普通用户修改 ...");
        return SUCCESS;
    }
    @Override
    public void setApplication(Map<String, Object> application) {
        // TODO Auto-generated method stub
        this.application = application;
    }
    @Override
    public void setSession(Map<String, Object> session) {
        // TODO Auto-generated method stub
        this.session = session;
    }
    @Override
    public void setRequest(Map<String, Object> request) {
        // TODO Auto-generated method stub
        this.request = request;
    }
    public static String greet(){
        return "Welcome to china.";
    }
}

第3步:在WebRoot/login_success.jsp文件添加红色字体标识的代码:

<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>登录成功</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <center>
        <h1>登录成功</h1>
        我们的口号是:<s:property value="#request.msg"/>(从request对象中获取)<br>
        <s:property value="#session.msg"/>(从session对象中获取)<br>
        <s:property value="#application.msg"/>(从application对象中获取)<br>
        <s:property value="#attr.msg"/>(从attribute对象中获取)<br>
        <br>
        欢迎用户:<s:property value="username"/><br>
        密码是:<s:property value="password"/><br>
        联系方式如下:<br>
        <s:property value="contact.email"/><br>
        <s:property value="contact.phone"/><br>
        <s:property value="contact.address"/><br>
        <li><a href="<%=path%>/user/User_add.action?method=添加">添加</a></li>
        <li><a href="<%=path%>/user/User_delete.action?method=删除">删除</a></li>
        <li><a href="<%=path%>/user/User_modify.action?method=修改">修改</a></li>
        <b>OGNL方法调用测试范例</b>
        <li>调用普通类的普通方法:<s:property value="contact.print()" /></li>
        <li>调用普通类的构造方法:<s:property value="new net.nw.vo.Contact(\"cat@136.com\",\"0755-12345678\",\"shenzhen\")" /></li>
        <li>调用Action类的普通方法:<s:property value="add()" /></li>
        <li>调用Action类的静态方法:<s:property value="@net.nw.action.UserAction2@greet()" /></li>
        <li>调用Action类的静态属性:<s:property value="@net.nw.action.UserAction2@sid" /></li>
        <li>调用普通类的构造方法:<s:property value="new net.nw.vo.Contact(\"cat@136.com\",\"0755-12345678\",\"shenzhen\")" /></li>
        <li>调用JDK类库的方法:<s:property value="@java.util.Calendar@getInstance()" /></li>
        <li>调用JDK类库的Math类方法:<s:property value="@@random()" /></li><br>
        <b>OGNL访问集合测试范例</b>
        <li>访问List泛型类型集合:<s:property value="contactors" /></li>
        <li>访问List泛型类型集合中某个对象:<s:property value="contactors[1]" /></li>
        <li>访问List泛型类型集合中某个属性的集合:<s:property value="contactors.{email}" /></li>
        <li>访问List泛型类型集合中某个属性的集合中的某个属性:<s:property value="contactors.{email}[0]" /></li><br>
        
        <li>访问Set泛型类型:<s:property value="cities" /></li><br>
        
        <li>访问Map泛型类型的集合:<s:property value="dics" /></li>
        <li>访问Map泛型类型的集合的keys:<s:property value="dics.keys" /></li>
        <li>访问Map泛型类型的集合的values:<s:property value="dics.values" /></li>
        <li>访问Map泛型类型的集合中某个key值对应的对象:<s:property value="dics[\"002\"]" /></li><!-- dics['002'] 单引号也可以 --><br>
        
        <b>OGNL测试投影&选择</b>
        <li>获取所有学生的集合:<s:property value="stus" /></li>

        <s:debug></s:debug>
    </center>
  </body>
</html>

第4步:发布运行程序,

分两次测试重写Student.java类默认的toString()方法,第1次不加下面的toString()重写代码,第2次重写toString()方法

    public String toString(){
        return "姓名: "+this.name+" 年龄: "+this.age;
    }

两次运行的效果图合并在一起的拼图如下:

测试选择举例:

第1步:在WebRoot/login_success.jsp页面文件中添加红色字体标识的代码测试OGNL表达式的选择功能:

<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>登录成功</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <center>
        <h1>登录成功</h1>
        我们的口号是:<s:property value="#request.msg"/>(从request对象中获取)<br>
        <s:property value="#session.msg"/>(从session对象中获取)<br>
        <s:property value="#application.msg"/>(从application对象中获取)<br>
        <s:property value="#attr.msg"/>(从attribute对象中获取)<br>
        <br>
        欢迎用户:<s:property value="username"/><br>
        密码是:<s:property value="password"/><br>
        联系方式如下:<br>
        <s:property value="contact.email"/><br>
        <s:property value="contact.phone"/><br>
        <s:property value="contact.address"/><br>
        <li><a href="<%=path%>/user/User_add.action?method=添加">添加</a></li>
        <li><a href="<%=path%>/user/User_delete.action?method=删除">删除</a></li>
        <li><a href="<%=path%>/user/User_modify.action?method=修改">修改</a></li>
        <b>OGNL方法调用测试范例</b>
        <li>调用普通类的普通方法:<s:property value="contact.print()" /></li>
        <li>调用普通类的构造方法:<s:property value="new net.nw.vo.Contact(\"cat@136.com\",\"0755-12345678\",\"shenzhen\")" /></li>
        <li>调用Action类的普通方法:<s:property value="add()" /></li>
        <li>调用Action类的静态方法:<s:property value="@net.nw.action.UserAction2@greet()" /></li>
        <li>调用Action类的静态属性:<s:property value="@net.nw.action.UserAction2@sid" /></li>
        <li>调用普通类的构造方法:<s:property value="new net.nw.vo.Contact(\"cat@136.com\",\"0755-12345678\",\"shenzhen\")" /></li>
        <li>调用JDK类库的方法:<s:property value="@java.util.Calendar@getInstance()" /></li>
        <li>调用JDK类库的Math类方法:<s:property value="@@random()" /></li><br>
        <b>OGNL访问集合测试范例</b>
        <li>访问List泛型类型集合:<s:property value="contactors" /></li>
        <li>访问List泛型类型集合中某个对象:<s:property value="contactors[1]" /></li>
        <li>访问List泛型类型集合中某个属性的集合:<s:property value="contactors.{email}" /></li>
        <li>访问List泛型类型集合中某个属性的集合中的某个属性:<s:property value="contactors.{email}[0]" /></li><br>
        
        <li>访问Set泛型类型:<s:property value="cities" /></li><br>
        
        <li>访问Map泛型类型的集合:<s:property value="dics" /></li>
        <li>访问Map泛型类型的集合的keys:<s:property value="dics.keys" /></li>
        <li>访问Map泛型类型的集合的values:<s:property value="dics.values" /></li>
        <li>访问Map泛型类型的集合中某个key值对应的对象:<s:property value="dics[\"002\"]" /></li><!-- dics['002'] 单引号也可以 --><br>
        
        <b>OGNL测试投影和选择</b>
        <li>获取所有学生的集合:<s:property value="stus" /></li>
        <li>获取所有学生年龄大于30岁的学生资料:<s:property value="stus.{?#this.age>=30}" /></li>  <!-- .{?#this.age>=30}表示选择 -->
        <s:debug></s:debug>  

</center>
  </body>
</html>

第2步:测试结果会输出以下内容:

获取所有学生年龄大于30岁的学生资料:[姓名: 田野 年龄: 37, 姓名: 周季 年龄: 31, 姓名: 陈墨 年龄: 30]


测试投影举例:

第1步:在WebRoot/login_success.jsp页面文件中找到<s:debug></s:debug>这行代码,

在它的上面插入<li>获取所有学生年龄大于30岁的学生的姓名资料:<s:property value="stus.{?#this.age>=30}.{name}" />  </li><!-- .{name}表示投影 -->

上面这行红色字体标识的代码

第2步:测试结果会输出以下内容:

获取所有学生年龄大于30岁的学生的姓名资料:[田野, 周季, 陈墨]


测试   压入值栈的对象.{?选择条件}.{投影属性名称}[n]   这种格式获得某1个属性的值举例:

第1步:在WebRoot/login_success.jsp页面文件中找到<s:debug></s:debug>这行代码,

在它的上面插入<li>获取所有学生年龄大于30岁的学生中第1个学生的姓名:<s:property value="stus.{?#this.age>=30}.{name}[0]" /></li>  <!-- 结果格式是对象 -->

上面这行红色字体标识的代码

第2步:测试结果会输出以下内容,结果格式是对象:

获取所有学生年龄大于30岁的学生中第1个学生的姓名:田野


测试   压入值栈的对象.{^选择条件}.{投影属性名称}  这种格式获得顺数第1个属性的值举例:

第1步:在WebRoot/login_success.jsp页面文件中找到<s:debug></s:debug>这行代码,
在它的上面插入
<li>获取所有学生年龄大于30岁的学生中第1个学生的姓名:<s:property value="stus.{^#this.age>=30}.{name}" /></li> <!-- 结果格式是集合 -->

上面这行红色字体标识的代码

第2步:测试结果会输出以下内容,结果格式是集合(注意中括号表示的结果是集合):

获取所有学生年龄大于30岁的学生中第1个学生的姓名:[田野]


测试   压入值栈的对象.{$选择条件}.{投影属性名称}  这种格式获得倒数第1个属性的值举例:

第1步:在WebRoot/login_success.jsp页面文件中找到<s:debug></s:debug>这行代码,
在它的上面插入
<li>获取所有学生年龄大于30岁的学生中倒数第1个学生的姓名:<s:property value="stus.{$#this.age>=30}.{name}" /></li><br>

上面这行红色字体标识的代码

第2步:测试结果会输出以下内容,结果格式是集合(注意中括号表示的结果是集合):

获取所有学生年龄大于30岁的学生中倒数第1个学生的姓名:[陈墨]


#符号的用途
访问根对象        例如  访问值栈里面的对象 还有值栈的上下文对象
用于选择和投影  例如  #this
构造Map          例如  #{'foo1':'bar1','foo2':'bar2'}

struts2中值栈里面的对象为根对象,如OGNL上下文还有action上下文,#相当于ActionContext.getContext();
下面列有几个ActionContext中有用的属性:
#parameters
#request
#session
#application
#attr

#parameters.id        | request.getParameter("id")          获得通过URL地址传递过来的参数值
#parameters.id[0]     | request.getParameter("id")          获得通过URL地址传递过来的参数值

#request.userName     | request.getAttribute("userName")                                                            这一个前面已经用过了
#session.userName     | session.getAttribute("userName")                                                         这一个前面已经用过了
#application.userName | application.getAttribute("userName")                                                    这一个前面已经用过了
attr 用于按request > session > application的顺序访问其属性(attribute),
#attr.userName相当于按顺序在以上3个范围(scope)内读取userName属性,直到找到为止。
这一个前面已经用过了

这里只举例讲解#parameters的用法:

第1步:在src/struts.xml配置文件中到到子包user将父包default中成功登陆跳转的地址在子包user里面把它覆盖掉(做法是添加红色字体标识的代码),

然后让URL地址传递一个hi=nihao的参数值

<?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>
    <constant name="struts.devMode" value="true" ></constant>
    <constant name="struts.i18n.encoding" value="utf-8" ></constant>
    <constant name="struts.custom.i18n.resources" value="App"></constant>
    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
     <!-- 父包default -->
     <package name="default" namespace="" extends="struts-default">
        <global-results>
            <result name="login_success">/login_success.jsp</result>
            <result name="login_failure">/login_failure.jsp</result>
            <result name="error">/error.jsp</result>
        </global-results>
        <global-exception-mappings>
            <exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
        </global-exception-mappings>
        <action name="exit">
            <result>/login.jsp</result>
        </action>
        <action name="language">
            <result>/login.jsp</result>
        </action>
     </package>
    <!-- 子包user继承于父包default -->
    <package name="user" namespace="/user" extends="default">
        <global-results>
            <result>/user/result.jsp</result>
        </global-results>
        <action name="login*" class="net.nw.action.UserAction{1}">
            <result name="login_success">/login_success.jsp?hi=nihao</result>
            <result name="input">/login.jsp</result>
        </action>
        <action name="*_*" class="net.nw.action.{1}Action4" method="{2}">
        </action>
    </package>
    <include file="admin.xml"></include>
    <package name="test" namespace="" extends="default">
        <action name="test1" class="net.nw.action.TestAction1">
            <!-- 默认result类型等于dispatcher -->
            <result>/test/test1.jsp</result>
        </action>
        <action name="test2" class="net.nw.action.TestAction2">
            <!-- result类型等于redirect -->
            <result type="redirect">/test/test2.jsp</result>
        </action>
        <action name="test3" class="net.nw.action.TestAction2">
            <!-- result类型等于chain -->
            <result type="chain">test1</result>
        </action>
        <action name="test4" class="net.nw.action.TestAction2">
            <!-- result类型等于redirectAction -->
            <result type="redirectAction">test1</result>
        </action>
        <action name="test5" class="net.nw.action.TestAction2">
            <!-- result类型等于plainText -->
            <result type="plainText">/test/test2.jsp</result>
        </action>
     </package>
    <package name="error" namespace="" extends="default">
        <action name="**">
            <result>/error.jsp</result>
        </action>
     </package>
</struts>

第2步:在WebRoot/login_success.jsp页面文件中找到<s:debug></s:debug>这行代码,

在它的上面插入

        <b>OGNL测试#parameters</b><br>
        <li>获得URL地址传递过来的参数值:<s:property value="#parameters.hi[0]"/></li>

上面这两行红色字体标识的代码#parameters.hi[0] 等价于#parameters.hi
第3步:测试结果会输出以下内容:

获得URL地址传递过来的参数值:nihao


$符号的用途
1. 用于在国际化资源文件中,引用OGNL表达式; 在UserAction2-validation.xml中就已经引用了OGNL表达式 回头在UserAction2-validation.xml中看看$符号的使用
2. 在struts2配置文件中,引用OGNL表达式(
不推荐 因为在URL地址中传递中文会出错 也不能在URL地址中传递对象类型参数)

第1步:在src/struts.xml配置文件中到到子包user,将父包default中成功登陆跳转的地址在子包user里面把它覆盖掉(做法是添加红色字体标识的代码),
然后让URL地址传递一个hi=nihao的参数值,还加上一个ognl表达式参数值 username=${username}:
XML中的特殊字符(本范例中注意URL地址中的&amp;)
字符 转义字符 描述
&    &amp;    和
<   &lt;     小于号
>   &gt;     大于号
"    &quot;   双引号
'    &apos;   单引号

<?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>
    <constant name="struts.devMode" value="true" ></constant>
    <constant name="struts.i18n.encoding" value="utf-8" ></constant>
    <constant name="struts.custom.i18n.resources" value="App"></constant>
    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
     <!-- 父包default -->
     <package name="default" namespace="" extends="struts-default">
        <global-results>
            <result name="login_success">/login_success.jsp</result>
            <result name="login_failure">/login_failure.jsp</result>
            <result name="error">/error.jsp</result>
        </global-results>
        <global-exception-mappings>
            <exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
        </global-exception-mappings>
        <action name="exit">
            <result>/login.jsp</result>
        </action>
        <action name="language">
            <result>/login.jsp</result>
        </action>
     </package>
    <!-- 子包user继承于父包default -->
    <package name="user" namespace="/user" extends="default">
        <global-results>
            <result>/user/result.jsp</result>
        </global-results>

        <action name="login*" class="net.nw.action.UserAction{1}">
            <!-- ${username}同样适用于客户端跳转传递值栈里的属性值  -->
            <result name="login_success">/login_success.jsp?hi=nihao&amp;username=${username}</result>

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

        <action name="*_*" class="net.nw.action.{1}Action4" method="{2}">
        </action>
    </package>
    <include file="admin.xml"></include>
    <package name="test" namespace="" extends="default">
        <action name="test1" class="net.nw.action.TestAction1">
            <!-- 默认result类型等于dispatcher -->
            <result>/test/test1.jsp</result>
        </action>
        <action name="test2" class="net.nw.action.TestAction2">
            <!-- result类型等于redirect -->
            <result type="redirect">/test/test2.jsp</result>
        </action>
        <action name="test3" class="net.nw.action.TestAction2">
            <!-- result类型等于chain -->
            <result type="chain">test1</result>
        </action>
        <action name="test4" class="net.nw.action.TestAction2">
            <!-- result类型等于redirectAction -->
            <result type="redirectAction">test1</result>
        </action>
        <action name="test5" class="net.nw.action.TestAction2">
            <!-- result类型等于plainText -->
            <result type="plainText">/test/test2.jsp</result>
        </action>
     </package>
    <package name="error" namespace="" extends="default">
        <action name="**">
            <result>/error.jsp</result>
        </action>
     </package>
</struts>

第2步:在WebRoot/login_success.jsp页面文件中找到<s:debug></s:debug>这行代码,
在它的上面插入
        <li>获得URL地址传递过来的参数值:<s:property value="#parameters.username[0]"/></li>
上面这行红色字体标识的代码 #parameters.username[0] 等价于#parameters.username
第3步:测试结果会输出以下内容:
获得URL地址传递过来的参数值:童话

#parameters和$符号在URL地址中传递参数值的测试效果截图如下:

WebRoot/login_success.jsp页面代码:

<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>登录成功</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <center>
        <h1>登录成功</h1>
        我们的口号是:<s:property value="#request.msg"/>(从request对象中获取)<br>
        <s:property value="#session.msg"/>(从session对象中获取)<br>
        <s:property value="#application.msg"/>(从application对象中获取)<br>
        <s:property value="#attr.msg"/>(从attribute对象中获取)<br>
        <br>
        欢迎用户:<s:property value="username"/><br>
        密码是:<s:property value="password"/><br>
        联系方式如下:<br>
        <s:property value="contact.email"/><br>
        <s:property value="contact.phone"/><br>
        <s:property value="contact.address"/><br>
        <li><a href="<%=path%>/user/User_add.action?method=添加">添加</a></li>
        <li><a href="<%=path%>/user/User_delete.action?method=删除">删除</a></li>
        <li><a href="<%=path%>/user/User_modify.action?method=修改">修改</a></li>
        <b>OGNL方法调用测试范例</b>
        <li>调用普通类的普通方法:<s:property value="contact.print()" /></li>
        <li>调用普通类的构造方法:<s:property value="new net.nw.vo.Contact(\"cat@136.com\",\"0755-12345678\",\"shenzhen\")" /></li>
        <li>调用Action类的普通方法:<s:property value="add()" /></li>
        <li>调用Action类的静态方法:<s:property value="@net.nw.action.UserAction2@greet()" /></li>
        <li>调用Action类的静态属性:<s:property value="@net.nw.action.UserAction2@sid" /></li>
        <li>调用普通类的构造方法:<s:property value="new net.nw.vo.Contact(\"cat@136.com\",\"0755-12345678\",\"shenzhen\")" /></li>
        <li>调用JDK类库的方法:<s:property value="@java.util.Calendar@getInstance()" /></li>
        <li>调用JDK类库的Math类方法:<s:property value="@@random()" /></li><br>
        <b>OGNL访问集合测试范例</b>
        <li>访问List泛型类型集合:<s:property value="contactors" /></li>
        <li>访问List泛型类型集合中某个对象:<s:property value="contactors[1]" /></li>
        <li>访问List泛型类型集合中某个属性的集合:<s:property value="contactors.{email}" /></li>
        <li>访问List泛型类型集合中某个属性的集合中的某个属性:<s:property value="contactors.{email}[0]" /></li><br>
        
        <li>访问Set泛型类型:<s:property value="cities" /></li><br>
        
        <li>访问Map泛型类型的集合:<s:property value="dics" /></li>
        <li>访问Map泛型类型的集合的keys:<s:property value="dics.keys" /></li>
        <li>访问Map泛型类型的集合的values:<s:property value="dics.values" /></li>
        <li>访问Map泛型类型的集合中某个key值对应的对象:<s:property value="dics[\"002\"]" /></li><!-- dics['002'] 单引号也可以 --><br>
        
        <b>OGNL测试投影和选择</b>
        <li>获取所有学生的集合:<s:property value="stus" /></li>
        <li>获取所有学生年龄大于30岁的学生资料:<s:property value="stus.{?#this.age>=30}" /></li>  <!-- .{?#this.age>=30}表示选择 -->
        <li>获取所有学生年龄大于30岁的学生的姓名资料:<s:property value="stus.{?#this.age>=30}.{name}" />  </li><!-- .{name}表示投影 -->
        <li>获取所有学生年龄大于30岁的学生中第1个学生的姓名:<s:property value="stus.{?#this.age>=30}.{name}[0]" /></li>  <!-- 结果格式是对象 -->
        <li>获取所有学生年龄大于30岁的学生中第1个学生的姓名:<s:property value="stus.{^#this.age>=30}.{name}" /></li>  <!-- 结果格式是集合 -->
        <li>获取所有学生年龄大于30岁的学生中倒数第1个学生的姓名:<s:property value="stus.{$#this.age>=30}.{name}" /></li><br>
        
        <b>OGNL测试#parameters</b><br>
        <li>获得URL地址传递过来的参数值:<s:property value="#parameters.hi[0]"/></li>
        <li>获得URL地址传递过来的参数值(input标签输入的username内容):<s:property value="#parameters.username[0]"/></li>

        <s:debug></s:debug>
    </center>
  </body>
</html>


值栈技术
1. struts2为每一次请求生成一个值栈,不同的请求对应不同的值栈;
2. struts2接收到一个action请求,首先创建action类的实例对象,把该对象压进值栈,此时action中的所有属性都是默认值,然后执行定义在该action上的所有拦截器,

     最后执行action动作;
总结步骤:构造方法 ---> 拦截器 ---> 动作方法
注意:拦截器可以改变属性的值,当改变某个属性值后,action类的相应属性值就会变成在拦截器中最后改变该属性的这个值;

在两个action之间采用的是服务器跳转,如果两个action有名字相同的属性,则前一个action是否会同步传递属性的值给后一个action属性,对后一个action属性的修改是否会覆盖前一个action的属性值要分两种情况讨论?

1.  属性是对象属性  例如 实例化的对象 ,必须实现对象的get和set方法才能压入值栈   ------ 从第1个action跳转跳转到第2个action时(服务器内部跳转),会同步传递对象属性的值,但是跳转之后,再修改第2个action里面的属性值不会影响到第1个action对象里面的属性值,因为这是两个独立的对象属性值栈,故不会覆盖;

2.  属性是基本类型的字段属性,例如   整型  字符串型  货币型 单精度或者双精度浮点型 布尔型,必须实现字段的get和set方法才能压入值栈 ------从第1个action跳转跳转到第2个action时(服务器内部跳转),不会同步传递字段属性的值,但是跳转之后,再修改第2个action里面的字段属性的值不会影响到第1个action对象里面的字段属性的值,因为这是两个独立的对象属性值栈,故不会覆盖;

1.  属性是对象属性 举例:

第1步:在WebRoot/test_result.jsp页面中,添加红色字体标识的代码(注意输入框html标签命名的格式  对象名称.字段名称 均小写):

<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>测试Result类型</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <center>
        <h1>测试Result类型</h1>
        <hr>
        <form name="testForm" action="<%=path%>/test3.action" method="post">
            姓名:<input type="text" name="stu.name"/><br>
            年龄:<input type="text" name="stu.age"/><br>
                   <input type="submit" value="确定"/><br>
        </form>

        <!--  
        <li><a href="<%=path%>/test1.action">测试Dispatcher类型</a></li>
        <li><a href="<%=path%>/test2.action">测试Redirect类型</a></li>
        <li><a href="<%=path%>/test3.action">测试Chain类型</a></li>
        <li><a href="<%=path%>/test4.action">测试RedirectAction类型</a></li>
        <li><a href="<%=path%>/test5.action">测试plainText类型</a></li>
        <a href="<%=path%>/exit.action">返回</a>
        -->
    </center>
  </body>
</html>

第2步:在src/struts.xml配置文件中找到名称为test的package包内的action名称为test3动作配置代码
        <action name="test3" class="net.nw.action.TestAction1">
            <!-- result类型等于chain -->
            <result type="chain">test2</result>
        </action>
将以上配置部分的代码改成如下配置:
        <action name="test3" class="net.nw.action.TestAction2">
            <!-- result类型等于chain -->
            <result type="chain">test1</result>
        </action>

src/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>
    <constant name="struts.devMode" value="true" ></constant>
    <constant name="struts.i18n.encoding" value="utf-8" ></constant>
    <constant name="struts.custom.i18n.resources" value="App"></constant>
    <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
     <!-- 父包default -->
     <package name="default" namespace="" extends="struts-default">
        <global-results>
            <result name="login_success">/login_success.jsp</result>
            <result name="login_failure">/login_failure.jsp</result>
            <result name="error">/error.jsp</result>
        </global-results>
        <global-exception-mappings>
            <exception-mapping result="error" exception="java.lang.Exception"></exception-mapping>
        </global-exception-mappings>
        <action name="exit">
            <result>/login.jsp</result>
        </action>
        <action name="language">
            <result>/login.jsp</result>
        </action>
     </package>
    <!-- 子包user继承于父包default -->
    <package name="user" namespace="/user" extends="default">
        <global-results>
            <result>/user/result.jsp</result>
        </global-results>
        <action name="login*" class="net.nw.action.UserAction{1}">
            <!-- ${username}同样适用于客户端跳转传递值栈里的属性值  -->
            <result name="login_success">/login_success.jsp?hi=nihao&amp;username=${username}</result>
            <result name="input">/login.jsp</result>
        </action>
        <action name="*_*" class="net.nw.action.{1}Action4" method="{2}">
        </action>
    </package>
    <include file="admin.xml"></include>
    <package name="test" namespace="" extends="default">
        <action name="test1" class="net.nw.action.TestAction1">
            <!-- 默认result类型等于dispatcher -->
            <result>/test/test1.jsp</result>
        </action>
        <action name="test2" class="net.nw.action.TestAction2">
            <!-- result类型等于redirect -->
            <result type="redirect">/test/test2.jsp</result>
        </action>
        <action name="test3" class="net.nw.action.TestAction2">
            <!-- result类型等于chain -->
            <result type="chain">test1</result>
        </action>

        <action name="test4" class="net.nw.action.TestAction2">
            <!-- result类型等于redirectAction -->
            <result type="redirectAction">test1</result>
        </action>
        <action name="test5" class="net.nw.action.TestAction2">
            <!-- result类型等于plainText -->
            <result type="plainText">/test/test2.jsp</result>
        </action>
     </package>
    <package name="error" namespace="" extends="default">
        <action name="**">
            <result>/error.jsp</result>
        </action>
     </package>
</struts>

第3步: 在net.nw.action包下找到TestAction2动作类,让html标签输入的值填充到stu对象中(这是领域模型填充标签值的做法),添加红色字体标识的代码:
package net.nw.action;
import net.nw.vo.Student;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction1 extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private Student stu;
    public Student getStu() {
        return stu;
    }
    public void setStu(Student stu) {
        this.stu = stu;
    }
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        return super.execute();
    }

}

第4步: 在net.nw.action包下找到TestAction1动作类,也加入红色字体标识的代码:
package net.nw.action;
import net.nw.vo.Student;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction1 extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private Student stu;
    public Student getStu() {
        return stu;
    }
    public void setStu(Student stu) {
        this.stu = stu;
    }
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        return super.execute();
    }

}

第5步:在WebRoot/test1.jsp中显示姓名和年龄:
<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>Test1.jsp</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <center>
      <h1>Test1.jsp</h1>
      <hr>
      姓名:<s:property value="stu.name"/><br>
      年龄:<s:property value="stu.age"/><br>

      <s:debug></s:debug>
    </center>
  </body>
</html>

第6步:发布运行程序,测试效果截图如下:

1.  属性是对象属性  但是跳转之后,再修改第2个action里面的属性值不会影响到第1个action对象里面的属性值,因为这是两个独立的对象属性值栈,故不会覆盖;

为了演示不会覆盖的结论,按如下步骤进行:

第1步:在net.nw.action包下找到TestAction1动作类,加入红色字体标识的代码:
package net.nw.action;
import net.nw.vo.Student;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction1 extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private Student stu;
    public Student getStu() {
        return stu;
    }
    public void setStu(Student stu) {
        this.stu = stu;
    }
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub

        stu.setName("李四");

        return super.execute();
    }
}

第2步:发布运行程序,测试效果截图如下:

2.  属性是字段属性 基本类型中的整型字段举例:

第1步:在TestAction2.java动作类中添加红色字体标识的字段属性,并且在构造器内给该字段赋一个值,代码如下:

package net.nw.action;
import net.nw.vo.Student;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction2 extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private Student stu;
    private int age;
    public TestAction2(){
        this.age = 39;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public Student getStu() {
        return stu;
    }
    public void setStu(Student stu) {
        this.stu = stu;
    }
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        return super.execute();
    }
}

第2步:在TestAction1.java动作类中添加红色字体标识的字段属性,代码如下:

package net.nw.action;
import net.nw.vo.Student;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction1 extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private Student stu;
    private int age;
    public TestAction1(){
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }

    public Student getStu() {
        return stu;
    }
    public void setStu(Student stu) {
        this.stu = stu;
    }
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        stu.setName("李四");
        return super.execute();
    }
}

第3步:发布运行程序,测试效果截图如下:

2.  属性是基本类型的字段属性,但是跳转之后,再修改第2个action里面的字段属性的值不会影响到第1个action对象里面的字段属性的值,因为这是两个独立的对象属性值栈,故不会覆盖;

为了演示不会覆盖的结论,按如下步骤进行:

第1步:在TestAction1.java动作类中,即是在后一个action里面,给基本类型的age字段,在execute方法中赋一个初值,如红色字体标识那样,代码如下:

package net.nw.action;
import net.nw.vo.Student;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction1 extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private Student stu;
    private int age;
    public TestAction1(){
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Student getStu() {
        return stu;
    }
    public void setStu(Student stu) {
        this.stu = stu;
    }
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        this.age = 18;
        stu.setName("李四");
        return super.execute();
    }
}

第2步:发布运行程序,测试效果截图如下:

在本篇的末尾,再演示一种特殊的情况,对象或者基本类型变量没有set和get,手动使用编码的方式把它们压入值栈是如何做的?

第1步:在TestAction1.java动作类中添加私有字串变量yourname(这是基本类型变量),代码如下:

package net.nw.action;
import net.nw.vo.Student;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction1 extends ActionSupport{
    private static final long serialVersionUID = 1L;
    private Student stu;
    private String yourname;//没有实现它的set和get方法照样有办法压入值栈
    private int age;
    public TestAction1(){
        yourname = "王五";
        ActionContext.getContext().getValueStack().push(yourname);//直接压入值栈

    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public Student getStu() {
        return stu;
    }
    public void setStu(Student stu) {
        this.stu = stu;
    }
    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        this.age = 18;
        stu.setName("李四");
        return super.execute();
    }
}

第2步:显示直接压入值栈的基本类型或者对象,在jsp页面上显示出压入值栈的内容也很特殊,在WebRoot/test/test1.jsp页面代码中添加红色字体标识的代码:

<%@ page language="java" import="java.util.*" %>
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib uri="/struts-tags" prefix="s" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>Test1.jsp</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <center>
      <h1>Test1.jsp</h1>
      <hr>
      姓名:<s:property value="stu.name"/><br>
      年龄:<s:property value="stu.age"/><br>
      <b>显示直接压入值栈的基本类型</b><br>
      <li><b>在JSP中访问第2个值栈对象本身(而不是它们的属性):</b>    <s:property value="[1].top"/></li>
      <li><b>#root[1]:</b>           <s:property value="#root[1]"/></li>
      <li><b>#root[1].top:</b>    <s:property value="#root[1].top"/></li><br>

      
      <li><b>[0]的内容:</b>    <s:property value="[0]"/></li>
      <li><b>[1]的内容:</b>    <s:property value="[1]"/></li>
      <li><b>[2]的内容:</b>    <s:property value="[2]"/></li>

      <s:debug></s:debug>
    </center>
  </body>
</html>

第3步:发布运行程序,测试效果截图如下:

本项目的下载地址:

0 0
原创粉丝点击