先来说说
${producName}读取productName 值,实际上该属性并不在request (request 不是HttpRequest 而是struts重新包装的的request,是org.apache.struts2.dispatcher.StrutsRequestWrapper)等域对象中,而是从值栈中获取到的。
在StrutsRequestWrapper类中的ValueStack(值栈)里,有Context(OgnlContext)和root(CompoundRoot)两个比较重要的属性
OgnlContext:ActionContext其实就相当于OgnlContext,其里面只有一个属性即是OgnlContext,两个都是Map类型OgnlContext,ActionContext只是把OgnlContext 包装了下。
CompoundRoot:是一个使用ArrayList定义的栈,里面保存着各种和当前Action实例相关的对象。是一个数据结构意义的栈。
${producName}读取productName 值实际上就是从值栈的root属性中读取的值
在ValueStack对象的内部有两个逻辑部分:
1.ContextMap : struts把各种各样的映射关系(一些Map类型的对象)压入ContextMap中,实际上就是对ActionContext的一个引用,
struts会把parameters,request,session,application,attr(该Map按request,session,application顺序
来检索某个属性)这些映射压入ContextMap中。就是Context(OgnlContext),Map栈 。
2.ObjectStack:struts把各种和当前Action实例相关的对象压入Object中。就是root(CompoundRoot),对象栈。
值栈:贯穿整个action生命周期,一个请求一个action,每一个请求创建一个值栈,相当于一个数据的中转站,值栈保存了当前action对象和所有相关对象,
struts框架把值栈对象也保存在了request中,键是”struts.valueStack“。
1.在jsp页面上可以利用ONGL访问到值栈里的对象属性。
2.若希望访问值栈中ContextMap中的数据,需要给ONGL表达式加上一个前缀字符#,如果没有前缀字符#,搜索将在ObjectStack里进行。
值栈的属性值 :对于对象栈:对象栈中的某一个对象的属性值
对于 Map栈:request,session,application的一个属性值或一个请求参数的值
1.如何读取对象栈中的属性:
>若想访问ObjectStack里的某个对象的属性,可以使用以下几种形式之一:
object.propertyName ; object['propertyName'] ; object["propertyName"]
>ObjectStack里的对象可以通过一个从0开始的下标来引用,ObjectStack里的栈顶对象可以用[0]来引用,它下面的那个对象可以用[1]引用 [1].message
>[n]的含义是从第n个开始搜索,而不是只搜索第n个对象
>若从栈顶对象开始搜索,则可以省略下标部分:message
>结合s:property 标签:<s:property value="[0].message"/>等同于<s:property value="message"/>
2.默认情况下,Action对象会被Struts2自动的放入值栈的栈顶。
若想访问ContextMap里的某个对象的属性,可以使用以下几种形式之一
#object.propertyName; #object.['propertyName']; #object.["propertyName"];
示例:
返回session中的code属性:#session.code
返回request中的customer属性的name属性值:#request.customer.name
返回域对象(按request,session,application的顺序)的lastAccessDate属性:#attr.lastAccessDate
<!--使用OGNL调用public类的public类型的静态字段和静态方法--> <s:property value="@java.lang.Math@PI"/> <br><br> <s:property value="@java.lang.Math@cos(0)"/>
<!-- 调用对象栈的方法为一个属性赋值 --> <s:property value="setProductName('207')"/>
<!-- 调用数组对象的属性 --> <% String[] names = new String[]{"aa","bb","cc","dd"}; request.setAttribute("names",names); %> 数组length:<s:property value="#attr.names.length"/> <br><br> names[0]:<s:property value="#attr.names[0]"/> <br><br> <!-- 调用Map对象属性 --> <% Map<String,String> letters = new HashMap<String,String>(); request.setAttribute("letters",letters); letters.put("AA","a"); letters.put("BB","b"); letters.put("CC","c"); %> <s:property value="#attr.letters.size"/> <br><br> BB:<s:property value="#attr.letters['AA']"/>List等也可以在这不举例
<?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.ognl.allowStaticMethodAccess" value="true"></constant> <package name="wul" namespace="/" extends="struts-default"> <action name="product-save" class="com.wul.strust2.ValueStack.Product" method="save"> <result>/details.jsp</result> </action> </package> </struts>input.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Hello</title> </head> <body> <form action="product-save.action" method="post"> ProductName:<input type="text" name="productName"/> <br><br> ProductDesc:<input type="text" name="productDesc"/> <br><br> ProductPrice:<input type="text" name="productPrice"/> <br><br> <input type="submit" value="Submit"/> </form> </body> </html>details.jsp
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <%@page import="java.util.*"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Hello</title> </head> <body> <s:debug></s:debug> ProductName: <s:property value="productName"/> <br><br> ProductDesc: <s:property value="[1].productDesc"/> <br><br> ProductPrice: <s:property value="[0].productPrice"/> <br><br> ProductName1: ${sessionScope.product.productName } <s:property value="#session.product.productName"/> <br><br> ProductName2: ${requestScope.test.productName } <s:property value="#request.test.productName"/> <br><br> <!--使用OGNL调用public类的public类型的静态字段和静态方法--> <s:property value="@java.lang.Math@PI"/> <br><br> <s:property value="@java.lang.Math@cos(0)"/> <!-- 调用对象栈的方法为一个属性赋值 --> <s:property value="setProductName('207')"/> <br><br> <s:property value="productName"/> <br><br> <!-- 调用数组对象的属性 --> <% String[] names = new String[]{"aa","bb","cc","dd"}; request.setAttribute("names",names); %> 数组length:<s:property value="#attr.names.length"/> <br><br> names[0]:<s:property value="#attr.names[0]"/> <br><br> <!-- 调用Map对象属性 --> <% Map<String,String> letters = new HashMap<String,String>(); request.setAttribute("letters",letters); letters.put("AA","a"); letters.put("BB","b"); letters.put("CC","c"); %> <s:property value="#attr.letters.size"/> <br><br> BB:<s:property value="#attr.letters['AA']"/> </body> </html>
package com.wul.strust2.ValueStack; import java.util.Map; import org.apache.struts2.interceptor.RequestAware; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.util.ValueStack; public class Product implements RequestAware,SessionAware{ private Integer productId; private String productName; private String productDesc; private double productPrice; public Integer getProductId() { return productId; } public void setProductId(Integer productId) { this.productId = productId; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductDesc() { return productDesc; } public void setProductDesc(String productDesc) { this.productDesc = productDesc; } public double getProductPrice() { return productPrice; } public void setProductPrice(double productPrice) { this.productPrice = productPrice; } @Override public String toString() { return "Product [productId=" + productId + ", productName=" + productName + ", productDesc=" + productDesc + ", productPrice=" + productPrice + "]"; } public String save(){ System.out.println("save: "+this.toString()); //1.获取值栈 ValueStack valueStack = ActionContext.getContext().getValueStack(); //2.创建Test对象,并为其属性赋值 Test test = new Test(); test.setProductDesc("wul"); test.setProductName("520"); //3.把Test对象压入值栈的栈顶 valueStack.push(test); //ProductPrice: <s:property value="[0].productPrice"/>会读取“wul”和“520” sessionMap.put("product", this); requestMap.put("test", test); return "success"; } private Map<String,Object> sessionMap; @Override public void setSession(Map<String, Object> sessionMap) { // TODO 自动生成的方法存根 this.sessionMap = sessionMap; } private Map<String,Object> requestMap; @Override public void setRequest(Map<String, Object> requestMap) { // TODO 自动生成的方法存根 this.requestMap = requestMap; } }Test.java
package com.wul.strust2.ValueStack; public class Test { private String productName; private String productDesc; public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductDesc() { return productDesc; } public void setProductDesc(String productDesc) { this.productDesc = productDesc; } }