request变成了struts重写的StrutsRequestWrapper
关于值栈:
helloWorld时,${productName}读取productName值,实际上该属性并不在request等域中,而是从值栈中获取的。
ValueStack:
可以从ActionContext中获取值栈对象
值栈分为两个逻辑部分:
1.Map栈:实际上是OgnlContext类型,是个Map,也是对ApplicationContext的一个引用,里边保存着各种Map,requestMap,sessionMap,applicationMap,parametersMap,attr
2.对象栈:实际上是CompoundRoot类型,是一个使用ArrayList定义的栈。里面保存各种和当前Action实例相关的对象。是一个数据结构意义的栈。
OGNL(Object-Graph Navigation Language,对象-图导航语言)访问到值栈(ValueStack)里的对象属性。
如果希望访问值栈中ContextMap中的数据,需要给OGNL表达式加上一个前缀字符#。如果没有前缀字符#,搜索将在ObjectStack里进行。
struts2利用s:property标签和OGNL表达式来读取值栈中的属性值
值栈中的属性值:
对于对象栈:对象栈中某一个对象的属性值
Map栈:request,session,application的一个属性值或者一个请求参数的值。
读取ObjectStack里的对象的属性
弱项访问ObjectStack里的某个对象的属性,可以使用一下几种方式之一:
object.propertyName
object['propertyName']
object["propertyName"]
ObjectStack里的对象可以通过一个从0开始的下标来引用
ObjectStack里的暂定对象可以用[0]来引用,它下面的那个对象可以用[1]引用,若希望返回栈顶对象的message属性值:[0].message或者[0]["message"]或者[0]['message']
若在指定的对象里没有找到指定的属性,则到指定的最想的下一个对象里继续找,即[n]的含义是从n个开始搜索,而不是执手锁第n个对象。
若从栈顶对象开始搜索,则可以省略下标部分。
默认情况下,Action对象会被struts2自动的放到值栈的栈顶。
看代码:
package logan.struts.study; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.util.ValueStack; public class Product { 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); ValueStack valueStack = ActionContext.getContext().getValueStack(); Test test = new Test(); test.setProductDesc("AABBCCDD"); test.setProductName("ABCD"); valueStack.push(test); return "success"; } }
package logan.struts.study; 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.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="logan.struts.study.Product" method="save"> <result>/details.jsp</result> </action> </package> </struts>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>struts2-5</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> </web-app>
details.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib prefix="s" uri="/struts-tags"%> <!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=ISO-8859-1"> <title>Insert title here</title> </head> <body> <s:debug></s:debug> productId:${productId } <br><br> productName:${productName } <br><br> productDesc:${productDesc } <br><br> productPrice:${productPrice } <br><br> productPrice:<s:property value="productPrice"/> <br><br> <%=request %> </body> </html>
input.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!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=ISO-8859-1"> <title>Insert title here</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"> <br><br> </form> </body> </html>
读取Context Map里的对象属性
如果想访问ContextMap里的某个对象的属性,可以用一下几种形式之一:
#object.propertyName
#object['propertyName']
#object["propertyName"]
示例:
--返回session中的code属性:#session.code
--返回request中的customer属性的name属性值:#request.cuntomer.name
--返回域对象(按request,session,application的顺序)的lastAccessDate属性:#attr.lastAccessDate
看代码:
package logan.struts.study; 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); ValueStack valueStack = ActionContext.getContext().getValueStack(); Test test = new Test(); test.setProductDesc("AABBCCDD"); test.setProductName("ABCD"); valueStack.push(test); session.put("product", this); request.put("test", test); return "success"; } private Map<String, Object> session; private Map<String, Object> request; @Override public void setSession(Map<String, Object> session) { // TODO Auto-generated method stub this.session = session; } @Override public void setRequest(Map<String, Object> request) { // TODO Auto-generated method stub this.request = request; } }
package logan.struts.study; 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; } }
dateils.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib prefix="s" uri="/struts-tags"%> <!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=ISO-8859-1"> <title>Insert title here</title> </head> <body> <s:debug></s:debug> productId:${productId } <br><br> productName:${productName } <br><br> productDesc:${productDesc } <br><br> productPrice:${productPrice } <br><br> productPrice:<s:property value="productPrice"/> <br><br> productName1:${sessionScope.product.productName } <br><br> productName1.1:<s:property value="#session.product.productName"/> <br><br> productName2:${requestScope.test.productName } <br><br> productName2.1:<s:property value="#request.test.productName"/> <br><br> </body> </html>
调用字段和方法
可以利用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].dataPattern
--.object.methodName(argumentList):[0].repeat(3,"Hello");
看代码:
details.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib prefix="s" uri="/struts-tags"%> <!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=ISO-8859-1"> <title>Insert title here</title> </head> <body> <s:debug></s:debug> productId:${productId } <br><br> productName:${productName } <br><br> productDesc:${productDesc } <br><br> productPrice:${productPrice } <br><br> productPrice:<s:property value="productPrice"/> <br><br> productName1:${sessionScope.product.productName } <br><br> productName1.1:<s:property value="#session.product.productName"/> <br><br> productName2:${requestScope.test.productName } <br><br> productName2.1:<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)"/> <br><br> <!-- 调用对象栈的方法为一个属性赋值 --> <s:property value="setProductName('logan')"/> <br><br> <s:property value="productName"/> </body> </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> <!-- 打开静态方法调用的限制 --> <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant> <package name="default" namespace="/" extends="struts-default"> <action name="product-save" class="logan.struts.study.Product" method="save"> <result>/details.jsp</result> </action> </package> </struts>
访问数组类型的属性
有些属性将返回一个对象数组而不是单个对象,可以像读取任何其他对象属性那样读取他们。这种数组型属性的各个元素以都好分隔,并且不再方括号
可以使用下标访问数组中指定的元素:colors[0]
可以通过调用其length字段查出给定数组中有多少个元素:colors.length
看代码:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib prefix="s" uri="/struts-tags"%> <!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=ISO-8859-1"> <title>Insert title here</title> </head> <body> <s:debug></s:debug> productId:${productId } <br><br> productName:${productName } <br><br> productDesc:${productDesc } <br><br> productPrice:${productPrice } <br><br> productPrice:<s:property value="productPrice"/> <br><br> productName1:${sessionScope.product.productName } <br><br> productName1.1:<s:property value="#session.product.productName"/> <br><br> productName2:${requestScope.test.productName } <br><br> productName2.1:<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)"/> <br><br> <!-- 调用对象栈的方法为一个属性赋值 --> <s:property value="setProductName('logan')"/> <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[2]:<s:property value="#attr.names[2]"/> </body> </html>
访问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类型的属性将以如下所示的格式返回它所有的键值对:
{key-1=value-1,key-2=value-2,key-3=value-3}
如果希望检索出某个Map的值,需要使用如下格式:map[key]
可以使用size或者size()得出某个给定的Map的键值对的个数
可以使用isEmpty或者isEmpty()检查出某个给定Map是不是空。
可以使用如下语法来创建一个Map:
#{key-1=value-1,key-2=value-2,key-3=value-3}
看代码:
<%@page import="java.util.HashMap"%> <%@page import="java.util.Map"%> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib prefix="s" uri="/struts-tags"%> <!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=ISO-8859-1"> <title>Insert title here</title> </head> <body> <s:debug></s:debug> productId:${productId } <br><br> productName:${productName } <br><br> productDesc:${productDesc } <br><br> productPrice:${productPrice } <br><br> productPrice:<s:property value="productPrice"/> <br><br> productName1:${sessionScope.product.productName } <br><br> productName1.1:<s:property value="#session.product.productName"/> <br><br> productName2:${requestScope.test.productName } <br><br> productName2.1:<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)"/> <br><br> <!-- 调用对象栈的方法为一个属性赋值 --> <s:property value="setProductName('logan')"/> <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[2]:<s:property value="#attr.names[2]"/> <br><br> <% Map<String,String> letters = new HashMap<String,String>(); request.setAttribute("letters", letters); letters.put("AA", "a"); letters.put("BB", "b"); letters.put("CC", "c"); %> <!-- 使用OGNL访问Map --> <s:property value="#attr.letters.size"/> <br><br> AA:<s:property value="#attr.letters['AA']"/> </body> </html>