先來說說
關於值棧
${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“。
ONGL(如何顯示值棧裏的內容)
1.在jsp頁面上可以利用ONGL訪問到值棧裏的對象屬性。
2.若希望訪問值棧中ContextMap中的數據,需要給ONGL表達式加上一個前綴字符#,如果沒有前綴字符#,搜索將在ObjectStack裏進行。
1. Struts2利用s:property標籤和OGNL表達式來讀取值棧的屬性值
值棧的屬性值 :對於對象棧:對象棧中的某一個對象的屬性值
對於 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自動的放入值棧的棧頂。
2.讀取ContextMap裏的對象的屬性
若想訪問ContextMap裏的某個對象的屬性,可以使用以下幾種形式之一
#object.propertyName; #object.['propertyName']; #object.["propertyName"];
示例:
返回session中的code屬性:#session.code
返回request中的customer屬性的name屬性值:#request.customer.name
返回域對象(按request,session,application的順序)的lastAccessDate屬性:#attr.lastAccessDate
3.OGNL調用字段和方法
任何一個java類裏的靜態字段或方法
以及 被壓入到ValueStack棧的對象上的公共字段和方法
<!--使用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')"/>
4.訪問數組類型的屬性
<!-- 調用數組對象的屬性 -->
<%
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等也可以在這不舉例
一般使用EL訪問值棧中的對象的屬性
<s:property value="fieldName">也可以通過JSP EL來達到目標:${fieldName}原理:struts2將包裝HttpServletRequest對象後的org.apache.struts2.dispatcher.StrutsRequestWrapper對象傳到頁面上,而這個類重寫了getAttribute()方法
用EL的肯定能用OGNL,用OGNL的不一定能用EL
<?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>
Product.java
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.javapackage 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;
}
}