ValueStack是Struts2的一个接口,字面意义为值栈,OgnlValueStack是 ValueStack的实现类,客 户端发起一个请求,Struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例, OgnlValueStack贯穿整个Action的生命周期,Struts2中使用OGNL将请求Action的参数封装为对象存储 到值栈中,并通过OGNL表达式读取值栈中的对象属性值。
下面以实际例子进行演示:
1.创建一个Test实体类
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; } }
2.创建一个提交请求页面
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <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="提交"/> </form> </body> </html>
3.配置struts.xml文件
<struts> <package name="default" extends="struts-default" > <!-- 测试OGNL --> <action name="product-save" class="com.struts2.action.Product" method="save"> <result>/details.jsp</result> </action> </package> <!-- 打开静态方法调用的限制 --> <constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant> </struts>
4.创建一个Action类:Product,进行值栈的操作。
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; } public Product(Integer productId, String productName, String productDesc, Double productPrice) { super(); this.productId = productId; this.productName = productName; this.productDesc = productDesc; this.productPrice = productPrice; } public Product() { super(); } @Override public String toString() { return "Product [productId=" + productId + ", productName=" + productName + ", productDesc=" + productDesc + ", productPrice=" + productPrice + "]"; } public String save() { System.out.println("save:"+this); //1.获取值栈 ValueStack valueStack = ActionContext.getContext().getValueStack(); //2.创建一个Test对象并对其属性赋值 Test test = new Test(); test.setProductDesc("English"); test.setProductName("AAAAAA"); //3.把Test对象压入到值栈的栈顶 valueStack.push(test); //结果:此时在栈顶的对象就变成了这里的English和AAAAAA,details获取到的默认值就是处于栈顶的他俩 //而不是在input页面提交的值 //测试访问Map栈里的某个对象的属性 sessionMap.put("product", this); requestMap.put("test", test); return "success"; } private Map<String,Object> sessionMap; private Map<String,Object> requestMap; @Override public void setSession(Map<String, Object> sessionMap) { this.sessionMap = sessionMap; } @Override public void setRequest(Map<String, Object> requestMap) { this.requestMap = requestMap; } public String testTag() { return "success"; } }
5.在detail.jsp页面获取值栈对象
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!--导入ORGN标签库--> <!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>Insert title here</title> </head> <body> <s:debug>Debug</s:debug> <hr> ProductName:<%=request.getAttribute("productName") %> <!-- 正常的访问方式 --> <h5>通过OGNL访问对象栈的属性的方式</h5> <br><br> ProductDesc:①${productDesc } <!-- 在调用Product类中的save方法之后,栈顶的productDesc已经变成AAAAA --> ②<s:property value="[1].productDesc"/> <!-- 栈顶的下一位[1]才是action提交的请求参数属性值 --> <br><br> ProductPrice:${productPrice } <br><br> <!-- 注意顶上导入的哪个标签库,别忘了 --> ProductPriceOGNL:①<s:property value="[0].productPrice"/> ②<s:property value="productPrice"/> <!-- 读取栈顶对象属性值时可以省略[0] --> <br><br> <hr> <h5>访问Map栈中的属性</h5> ProductName1:${sessionScope.product.productName } + <s:property value="#session.product.productName"/> <br><br> ProductName2: ${requestScope.test.productName } + <s:property value="#request.test.productName"/> <br><br><hr> <h5>使用OGNL 调用public 类的 public 类型的静态字段和静态方法</h5> <s:property value="@java.lang.Math@PI"/><br> <s:property value="@java.lang.Math@cos(0)"/><br> <!-- 调用Java类的数学API --> <h5>调用对象栈的方法为一个属性赋值</h5> <s:property value="setProduceName('atguigu')"/> </body> </html>