Struts2_OGNL

    先來說說

   關於值棧  

         ${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調用字段和方法 

可以利用OGNL調用
     
                      任何一個java類裏的靜態字段或方法
   
                        以及 被壓入到ValueStack棧的對象上的公共字段和方法
默認情況下,struts2不允許調用任意java類靜態方法,需要重新設置struts.ognl.allowStaicMethodAccess標記變量的值爲true
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>

調用靜態字段或方法
<!--使用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

下面給出該章內容範例
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>
	<!-- 打開靜態方法的調用 -->
	<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.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;
	}
	
	
}





發佈了1 篇原創文章 · 獲贊 7 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章