Struts2_OGNL

    先来说说

   关于值栈  

         ${producName}读取productName 值,实际上该属性并不在request (request 不是HttpRequest 而是struts重新包装的的request,是org.apache.struts2.dispatcher.StrutsRequestWrapper)等域对象中,而是从值栈中获取到的。

在StrutsRequestWrapper类中的ValueStack(值栈)里,有Context(OgnlContext)和root(CompoundRoot)两个比较重要的属性

Struts2_OGNL_第1张图片

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

下面给出该章内容范例
Struts2_OGNL_第2张图片
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;
	}
	
	
}





你可能感兴趣的:(struts,web.xml,Web应用,struts2.0)