值栈中的值的获取方式
1.关于 值栈
1).helloworld 时,${productName} 读取productName 值,实际上该属性不在request 等域对象中,而是从值栈中获取的。
2).valueStack:可以从ActionContext 中获取值栈对象,值栈分为两个逻辑部门,
> Map 栈( ContextMap ):实际上是OgnlContext 类型,是一个Map,也是多ActionContext的一个引用。里面保存着各种MaprequsetMap,sessionMap,parameterMap,applicationMap,attr
Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application
> 对象栈( ObjectStack ):实际是CompoundRoot类型,是一个使用了ArrayList定义的栈,里面保存着和当前Action实例相关的对象。是一个数据结构意义的栈
ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个 ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.
Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中
2.OGNL
1)在 JSP 页面上可以可以利用 OGNL(Object-Graph Navigation Language: 对象-图导航语言) 访问到值栈(ValueStack) 里的对象属性.
2)若希望访问值栈中 ContextMap 中的数据, 需要给 OGNL 表达式加上一个前缀字符 #. 如果没有前缀字符 #, 搜索将在 ObjectStack 里进行.
3)Struts2利用s:property 标签和OGNL 表达式来读取值栈中的属性值
>对于对象栈:读取的是对象栈中的某一个对象的属性值
>map栈:request,session,application 的一个属性值 或 一个请求参数的值
①读取对象栈中的对象的属性:
>若想访问 Object Stack 里面某个对象的属性。可以使用一下几种形式之一:
推荐第一种: object.propertyName; object['propertyName']; object["propertyName"];
>ObjectStack 里的对象可以通过一个从零开始的下标来引用. ObjectStack 里的栈顶对象可以用 [0] 来引用,它下面的那个对象可以用 [1] 引用.
[0].message
>[n] 的含义从第n 个开始搜索,而不只是搜索第n 个对象
>若从栈顶对象开始搜索,则可以省略下标部门:message
>结合s:property 标签:<s:property value="message" /> 等同 <s:property value="[0].message" />
注意:默认情况下,Action对象会被Struts2 自动的放到值栈的栈顶
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ taglib prefix="s" uri="/struts-tags" %> 导入标签库 4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>detail page</title> 9 </head> 10 <body> 11 12 <s:debug></s:debug> 13 <br><br> 14 ProductName:${productName } 15 <br><br> 16 ProductDesc:${productDesc } 17 <br><br> 18 19 ProductPrice:<s:property value="[1].productPrice"/> //使用标签进行访问值栈 20 <!-- ProductPrice:${productPrice } --> 21 <br><br> 22 23 24 </body> 25 </html>
Product.java
1 package com.jason.struts2; 2 3 import com.opensymphony.xwork2.ActionContext; 4 import com.opensymphony.xwork2.util.ValueStack; 5 6 public class Product { 7 8 private Integer productId; 9 private String productName; 10 private String productDesc; 11 12 private double productPrice; 13 14 15 16 public String save(){ 17 18 System.out.println(this); 19 //1.获取值栈 20 ValueStack valueStack = ActionContext.getContext().getValueStack(); 21 22 //2.创建 Test 对象,并对其赋值 23 Test test = new Test(); 24 test.setProductDesc("testProductDesc"); 25 test.setProductName("testProductName"); 26 27 //3.把Test 对象压入 值栈的栈顶 28 valueStack.push(test); 29 30 return "success"; 31 } 32 33 34 @Override 35 public String toString() { 36 return "Product [productId=" + productId + ", productName=" 37 + productName + ", productDesc=" + productDesc 38 + ", productPrice=" + productPrice + "]"; 39 } 40 41 public Integer getProductId() { 42 return productId; 43 } 44 45 public void setProductId(Integer productId) { 46 this.productId = productId; 47 } 48 49 public String getProductName() { 50 return productName; 51 } 52 53 public void setProductName(String productName) { 54 this.productName = productName; 55 } 56 57 public String getProductDesc() { 58 return productDesc; 59 } 60 61 public void setProductDesc(String productDesc) { 62 this.productDesc = productDesc; 63 } 64 65 public double getProductPrice() { 66 return productPrice; 67 } 68 69 public void setProductPrice(double productPrice) { 70 this.productPrice = productPrice; 71 } 72 73 74 75 76 }
Test.java
1 package com.jason.struts2; 2 3 public class Test { 4 private String productName; 5 private String productDesc; 6 public String getProductName() { 7 return productName; 8 } 9 public void setProductName(String productName) { 10 this.productName = productName; 11 } 12 public String getProductDesc() { 13 return productDesc; 14 } 15 public void setProductDesc(String productDesc) { 16 this.productDesc = productDesc; 17 } 18 19 20 }
struts.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE struts PUBLIC 3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 4 "http://struts.apache.org/dtds/struts-2.3.dtd"> 5 6 <struts> 7 8 <package name="default" namespace="/" extends="struts-default"> 9 10 <action name="product-save" class="com.jason.struts2.Product" method="save"> 11 <result name="success">/details.jsp</result> 12 </action> 13 14 </package> 15 16 </struts>
② 读取 Context Map 里的对象的属性
>若想访问 ContextMap 里的某个对象的属性, 可以使用以下几种形式之一
推荐第一种: #object.propertyName; #object['propertyName']; #object["propertyName"];
>示例:
返回 session 中的 code 属性: #session.code
返回 request 中的 customer 属性的 name 属性值: #request.customer.name
返回域对象(按 request, session, application 的顺序)的 lastAccessDate 属性: #attr.lastAccessDate
Product.java
1 package com.jason.struts2; 2 3 import java.util.Map; 4 5 import org.apache.struts2.interceptor.RequestAware; 6 import org.apache.struts2.interceptor.SessionAware; 7 8 import com.opensymphony.xwork2.ActionContext; 9 import com.opensymphony.xwork2.util.ValueStack; 10 11 public class Product implements RequestAware,SessionAware{ 12 13 private Integer productId; 14 private String productName; 15 private String productDesc; 16 private double productPrice; 17 18 19 20 public String save(){ 21 22 System.out.println(this); 23 //1.获取值栈 24 ValueStack valueStack = ActionContext.getContext().getValueStack(); 25 26 //2.创建 Test 对象,并对其赋值 27 Test test = new Test(); 28 test.setProductDesc("testProductDesc"); 29 test.setProductName("testProductName"); 30 31 //3.把Test 对象压入 值栈的栈顶 32 valueStack.push(test); 33 sessionMap.put("product", this); 34 requestMap.put("test", test); 35 36 return "success"; 37 } 38 39 40 @Override 41 public String toString() { 42 return "Product [productId=" + productId + ", productName=" 43 + productName + ", productDesc=" + productDesc 44 + ", productPrice=" + productPrice + "]"; 45 } 46 47 public Integer getProductId() { 48 return productId; 49 } 50 51 public void setProductId(Integer productId) { 52 this.productId = productId; 53 } 54 55 public String getProductName() { 56 return productName; 57 } 58 59 public void setProductName(String productName) { 60 this.productName = productName; 61 } 62 63 public String getProductDesc() { 64 return productDesc; 65 } 66 67 public void setProductDesc(String productDesc) { 68 this.productDesc = productDesc; 69 } 70 71 public double getProductPrice() { 72 return productPrice; 73 } 74 75 public void setProductPrice(double productPrice) { 76 this.productPrice = productPrice; 77 } 78 79 80 private Map<String, Object> sessionMap; 81 public void setSession(Map<String, Object> arg0) { 82 this.sessionMap = arg0; 83 84 } 85 86 87 private Map<String,Object> requestMap; 88 public void setRequest(Map<String, Object> arg0) { 89 this.requestMap = arg0; 90 91 } 92 93 94 95 96 }
details.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ taglib prefix="s" uri="/struts-tags" %> 4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>detail page</title> 9 </head> 10 <body> 11 12 <s:debug></s:debug> 13 <br><br> 14 ProductName:${productName } 15 <br><br> 16 ProductDesc:${productDesc } 17 <br><br> 18 19 ProductPrice:<s:property value="[1].productPrice"/> 20 <!-- ProductPrice:${productPrice } --> 21 <br><br> 22 23 24 ProductDesc1:${sessionScope.product.productName } 25 <s:property value="#session.product.productName"/> <!-- 通过标签读取属性--> 26 <br><br> 27 28 29 ProductDesc2:${requestScope.test.productName } 30 <s:property value="#request.test.productName"/> 31 <br><br> 32 33 </body> 34 </html>
input.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 <title>input page</title> 8 </head> 9 <body> 10 11 <form action="product-save.action" method="post"> 12 ProductName:<input type="text" name="productName"/> 13 <br><br> 14 15 ProductDesc:<input type="text" name="productDesc"/> 16 <br><br> 17 18 ProductPrice:<input type="text" name="productPrice"/> 19 <br><br> 20 21 <input type="submit" value="submit" /> 22 </form> 23 </body> 24 </html>
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="default" namespace="/" extends="struts-default"> <action name="product-save" class="com.jason.struts2.Product" method="save"> <result name="success">/details.jsp</result> </action> </package> </struts>
③调用字段和方法,数组
>可以利用 OGNL 调用
任何一个 Java 类里的静态字段或方法. 被压入到 ValueStack 栈的对象上的公共字段和方法
>默认情况下, Struts2 不允许调用任意 Java 类静态方法, 需要重新设置 struts.ognl.allowStaticMethodAccess 标记变量的值为 true.
>调用静态字段或方法需要使用如下所示的语法:
-- @fullyQualifiedClassName@fieldName:
@java.util.Calendar@DECEMBER
- -@fullyQualifiedClassName@methodName(argumentList):
@app4.Util@now()
>调用一个实例字段或方法的语法, 其中 object 是 Object Stack 栈里的某个对象的引用:
-- .object.fieldName: [0].datePattern
-- .object.methodName(argumentList): [0].repeat(3, “Hello”);
例子:
1 <!-- 使用ognl,调用public 类的public类型的静态字段和静态方法 --> 2 <s:property value="@java.lang.Math@PI"/> 3 <br><br> 4 <s:property value="@java.lang.Math@cos(0)"/> 5 <br><br> 6 7 <!-- 调用对象栈的方法为一个属性赋值 --> 8 <s:property value="setProductName('jason') "/> 9 <br><br> 10 <s:property value="productName"/>
>调用数组对象的属性
1 <!-- 调用数组对象的属性 --> 2 <% 3 String[] names = new String[] {"aa","bb","cc"}; 4 request.setAttribute("names", names); 5 %> 6 <br><br> 7 length:<s:property value="#attr.names.length"/> 8 <br><br> 9 names[2]:<s:property value="#attr.names[2]"/>
>访问 List 类型的属性
有些属性将返回的类型是 java.util.List, 可以像读取任何其他属性那样读取它们. 这种 List 的各个元素是字符串, 以逗号分隔, 并且带方括号
可以使用下标访问 List 中指定的元素: colors[0]
可以通过调用其 size 方法或专用关键字 size 的方法查出给定List 的长度: colors.size 或 colors.size()
可以通过使用 isEmpty() 方法或专用关键字 isEmpty 来得知给定的 List 是不是空. colors.isEmpty 或 colors.isEmpty()
还可以使用 OGNL 表达式来创建 List, 创建一个 List 与声明一个 Java 数组是相同的: {“Red”, “Black”, “Green”}
>访问 Map 类型的属性
读取一个 Map 类型的属性将以如下所示的格式返回它所有的键值对:
若希望检索出某个 Map 的值, 需要使用如下格式: map[key]
可以使用 size 或 size() 得出某个给定的 Map 的键值对的个数
可以使用 isEmpty 或 isEmpty() 检查某给定 Map 是不是空.
1 <!-- 使用ognl 访问map 操作 --> 2 <% 3 Map<String, String> letters = new HashMap<String, String>(); 4 letters.put("AA", "a"); 5 letters.put("BB", "b"); 6 letters.put("CC", "c"); 7 request.setAttribute("letters", letters); 8 %> 9 letters.length:<s:property value="#attr.letters.size"/> 10 <br><br> 11 AA:<s:property value="#attr.letters['AA']"/>
使用 EL 访问值栈中对象的属性
<s:property value=“fieldName”> 也可以通过 JSP EL 来达到目的: ${fieldName}
原理: Struts2 将包装 HttpServletRequest 对象后的 org.apache.struts2.dispatcher.StrutsRequestWrapper 对象传到页面上, 而这个类重写了 getAttribute() 方法.