S7.2_Struts2_OGNL OGNL表达式的投影和选择技术范例,OGNL表达式#和$符号的使用范例,以及值栈
来源:互联网 发布:windows应用商店误删 编辑:程序博客网 时间:2024/06/04 19:28
投影
选择
#符号的使用
$符号的使用
值栈技术
我们接下来将要创建的项目目录结构如下:
由项目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>
在它的上面插入
<b>OGNL测试#parameters</b><br>
<li>获得URL地址传递过来的参数值:<s:property value="#parameters.hi[0]"/></li>
第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地址中的&)
字符 转义字符 描述
& & 和
< < 小于号
> > 大于号
" " 双引号
' ' 单引号
<?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>
<!-- ${username}同样适用于客户端跳转传递值栈里的属性值 -->
<result name="login_success">/login_success.jsp?hi=nihao&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&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步:发布运行程序,测试效果截图如下:
本项目的下载地址:
- S7.2_Struts2_OGNL OGNL表达式的投影和选择技术范例,OGNL表达式#和$符号的使用范例,以及值栈
- S7.1_Struts2_OGNL OGNL对象导航图范例&OGNL方法调用范例还有集合访问的范例
- ognl表达式的使用和值栈
- ognl表达式的使用和值栈
- OGNL表达式和值栈
- OGNL表达式的使用
- OGNL表达式的使用
- OGNL表达式的使用
- OGNL表达式的使用
- Ognl表达式的使用
- OGNL表达式的使用
- EL表达式和OGNL表达式的区别
- el表达式和ognl表达式的区别
- struts2的EL表达式和Ognl表达式
- Struts2中关于值栈和OGNL表达式的理解
- #、%和$符号在OGNL表达式中的作用
- OGNL表达式的基本语法和用法
- OGNL表达式的基本语法和用法
- 白盒测试概述及其方法简介
- The major advancements in Deep Learning in 2016
- Android单例设计模式简介和实例
- Xpath使用总结,javaScripe用来寻找元素的强大工具
- Nginx源码分析之ngx_array_t
- S7.2_Struts2_OGNL OGNL表达式的投影和选择技术范例,OGNL表达式#和$符号的使用范例,以及值栈
- C++ 函数调用运算符 () 重载
- 最大连续子序列和----动态规划
- source insight 自动对齐设置
- 技术知识整理
- Android_仿爱奇艺Loading效果
- git简明教程
- cmd命令行简单的操作
- 用Qemu模拟vexpress-a9 (二) --- 创建根文件系统