[原创]java WEB学习笔记59:Struts2学习之路---OGNL,值栈,读取对象栈中的对象的属性,读取 Context Map 里的对象的属性,调用字段和方法,数组,list,map
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用
内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。
本人互联网技术爱好者,互联网技术发烧友
微博:伊直都在0221
QQ:951226918
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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() 方法.