面向对象面向君,不负代码不负卿。 *^o^* |
- 关于值栈:
ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个 ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.
Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中
为了便于说明:
首先有这么一个Action类。名字叫做ValueStack,位置:com.struts.valuestack.ValueStack包下。
public class ValueStack implements SessionAware,RequestAware {
private String name ;
private String price ;
private Map<String,Object> sessionMap ;
private Map<String,Object> requestMap ;
public String getName() {
return name;
}
public String getPrice() {
return price;
}
public void setName(String name) {
this.name = name;
}
public void setPrice(String price) {
this.price = price;
}
public ValueStack(){
}
public String execute(){
requestMap.put("test",new Test()) ;
sessionMap.put("file",this) ;
return "OK" ;
}
@Override
public void setRequest(Map<String, Object> map) {
requestMap = map;
}
@Override
public void setSession(Map<String, Object> map) {
sessionMap = map;
}
}
然后一个index.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<s:debug></s:debug>
<br><br>
<form action="valuestack.action" method="post">
<input type="text" name="name"><br>
<input type="text" name="price"><br>
<input type="submit" value="submit">
</form>
</body>
</html>
struts.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<%--开启允许访问静态的方法--%>
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>
<package name="valuestack_1" extends="struts-default">
<action name="valuestack" class="com.struts.valuestack.ValueStack" method="execute">
<result name="OK" >/success.jsp</result>
</action>
</package>
</struts>
success.jsp页面
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<s:debug></s:debug>
name:${name}
<br>
<%--读取对象栈中的属性值--%>
name:^$<s:property value="name"></s:property>
<br>
price:${price}
<br>
<%--读取Map栈中的属性值--%>
map+name:<s:property value="#session.file.name"></s:property>
map+test:<s:property value="#request.test.test_K"></s:property>
<br>
<%--这个request并不是原生的了 是被struts包装过的了--%>
request:<%=request%>
<br>
<%--OGNL 访问静态字段和静态方法 struts.xml 需要开启--%>
<%--访问Java的Math下的PI 页面显示3.142--%>
<s:property value="@java.lang.Math@PI"></s:property>
<br>
<%--访问Java的Math下的cos() 传入0 cos为1 页面显示1--%>
<s:property value="@java.lang.Math@cos(0)"></s:property>
<br>
<%--调用对象栈中的方法,为属性赋值--%>
<s:property value="setName('wewie')" ></s:property>
<s:property value="name"></s:property>
<br>
<%--访问数组--%>
<%
String names[] = {"aa","bb","cc"} ;
request.setAttribute("names",names);
%>
<%--数组长度 页面显示 3--%>
<s:property value="#attr.names.length"></s:property>
<br>
<%--数组的第一个值 页面显示 aa--%>
<s:property value="#attr.names[0]"></s:property>
<%--数组的第3个值 页面显示 cc--%>
<br>
^^^:${requestScope.names[2]}
<br>
<%--使用OGNL 访问Map--%>
<%
Map<String,String> letters = new HashMap<>() ;
letters.put("AA","a") ;
letters.put("BB","b") ;
letters.put("CC","c") ;
request.setAttribute("letters",letters);
%>
<%--map长度 页面显示3--%>
<br>
<s:property value="#attr.letters.size"></s:property>
<%--map第一个 页面显示a--%>
<br>
<s:property value="#attr.letters['AA']"></s:property>
</body>
</html>
在index输出参数2321和2131
success.jsp界面显示
[Debug] name:2321
name:^$2321
price:2131
map+name:2321 map+test:test
request:org.apache.struts2.dispatcher.StrutsRequestWrapper@566133d8
3.142
1.0
name:wewie
3
aa
^^^:cc
3
a
1). 在success.jsp页面, ${name}
,${price}
读取 name和price 值, 实际上该属性并不在 request 等域对象中, 而是从值栈中获取的.
2). ValueStack:
I. 可以从 ActionContext 中获取值栈对象
II. 值栈分为两个逻辑部分
在 ValueStack 对象的内部有两个逻辑部分:
ObjectStack: Struts 把 Action 和相关对象压入 ObjectStack 中
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中. 实际上就是 对 ActionContext 的一个引用
Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application
Map 栈: 实际上是 OgnlContext 类型, 是个 Map, 也是对 ActionContext 的一个引用. 里边保存着各种 Map: requestMap, sessionMap, applicationMap, parametersMap, attr
对象栈: 实际上是 CompoundRoot 类型, 是一个使用 ArrayList 定义的栈. 里边保存各种和当前 Action 实例相关的对象.是一个数据结构意义的栈.
Struts2 利用 s:property 标签和 OGNL 表达式来读取值栈中的属性值
关于OGNL概念:参考百度百科的OGNL。OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。Struts 2默认的表达式语言是OGNL,原因是它相对其它表达式语言具有下面几大优势:
支持对象方法调用,如xxx.doSomeSpecial();
支持类静态的方法调用和值访问,表达式的格式为@[类全名(包括包路径)]@[方法名 | 值名],例如:@java.lang.String@format(‘foo %s’, ‘bar’)或@tutorial.MyConstant@APP_NAME;
支持赋值操作和表达式串联,如price=100, discount=0.8, calculatePrice(price*discount),这个表达式会返回80;
访问OGNL上下文(OGNL context)和ActionContext;
操作集合对象。
可以直接new一个对象。1). 值栈中的属性值:
对于对象栈: 对象栈中某一个对象的属性值
Map 栈: request, session, application 的一个属性值 或 一个请求参数的值.
2). 读取对象栈中对象的属性:
若想访问 Object Stack 里的某个对象的属性. 可以使用以下几种形式之一:
object.propertyName ; object[‘propertyName’] ; object[“propertyName”]
ObjectStack 里的对象可以通过一个从零开始的下标来引用. ObjectStack 里的栈顶对象可以用 [0] 来引用,
它下面的那个对象可以用 [1] 引用.[0].message
[n] 的含义是从第 n 个开始搜索, 而不是只搜索第 n 个对象
若从栈顶对象开始搜索, 则可以省略下标部分: message
结合 s:property 标签:
3). 默认情况下, Action 对象会被 Struts2 自动的放到值栈的栈顶.
4).若希望访问值栈中 ContextMap 中的数据, 需要给 OGNL 表达式加上一个前缀字符 #. 如果没有前缀字符 #, 搜索将在 ObjectStack 里进行读取 Context Map 里的对象的属性:
若想访问 ContextMap 里的某个对象的属性, 可以使用以下几种形式之一:
#object.propertyName ; #object['propertyName'] ;#object["propertyName"]
示例:
返回 session 中的 code 属性: #session.code
返回 request 中的 customer 属性的 name 属性值: #request.customer.name
返回域对象(按 request, session, application 的顺序)的 lastAccessDate 属性: #attr.lastAccessDate
调用字段和方法
可以利用 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].datePattern
.object.methodName(argumentList): [0].repeat(3, “Hello”);
访问数组类型的属性
有些属性将返回一个对象数组而不是单个对象, 可以像读取任何其他对象属性那样读取它们. 这种数组型属性的各个元素以逗号分隔, 并且不带方括号
可以使用下标访问数组中指定的元素: colors[0]
可以通过调用其 length 字段查出给定数组中有多少个元素: colors.length
访问 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,......}
若希望检索出某个 Map 的值, 需要使用如下格式: map[key]
可以使用 size 或 size() 得出某个给定的 Map 的键值对的个数
可以使用 isEmpty 或 isEmpty() 检查某给定 Map 是不是空.
可以使用如下语法来创建一个 Map:
#{key_1=value_1,........}
使用 EL 访问值栈中对象的属性
<s:property value=“fieldName”> 也可以通过 JSP EL 来达到目的: ${fieldName}
原理: Struts2 将包装 HttpServletRequest 对象后的 org.apache.struts2.dispatcher.StrutsRequestWrapper 对象传到页面上, 而这个类重写了 getAttribute() 方法.
大牛,别默默看了。快登陆帮我评论吧! *^o^* |