首页 > 代码库 > [原创]java WEB学习笔记59:Struts2学习之路---OGNL,值栈,读取对象栈中的对象的属性,读取 Context Map 里的对象的属性,调用字段和方法,数组,list,map
[原创]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="http://www.mamicode.com/message" /> 等同 <s:property value="http://www.mamicode.com/[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 @Override35 public String toString() {36 return "Product [productId=" + productId + ", productName="37 + productName + ", productDesc=" + productDesc38 + ", 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 @Override41 public String toString() {42 return "Product [productId=" + productId + ", productName="43 + productName + ", productDesc=" + productDesc44 + ", 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="http://www.mamicode.com/#session.product.productName"/> <!-- 通过标签读取属性-->26 <br><br>27 28 29 ProductDesc2:${requestScope.test.productName }30 <s:property value="http://www.mamicode.com/#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=http://www.mamicode.com/“fieldName”> 也可以通过 JSP EL 来达到目的: ${fieldName}
原理: Struts2 将包装 HttpServletRequest 对象后的 org.apache.struts2.dispatcher.StrutsRequestWrapper 对象传到页面上, 而这个类重写了 getAttribute() 方法.
[原创]java WEB学习笔记59:Struts2学习之路---OGNL,值栈,读取对象栈中的对象的属性,读取 Context Map 里的对象的属性,调用字段和方法,数组,list,map