OGNL
一、值栈
我们在struts——helloWorld中的示例程序中,使用了
${productName}
读取productName 值,实际上该属性并不在request 等域对象中,而是从值栈中获取的。
值栈,ValueStack:
可以从ActionContext中获取值栈对象。
值栈可以分为两个逻辑部分:
- Map栈:实际上是OgnlContext类型。也是对ActionContext的一个引用。里面保存各种Map:
,requestMap
,sessionMap
,applicationMap
,parametersMap
.attr
- 对象栈:实际上是CompoundRoot类型,是一个使用ArrayList定义的栈。里面保存着各种和当前Action实例相关的对象。是一个数据结构意义的栈。
ValueStack(值栈): 贯穿整个 Action 的生命周期(每个 Action 类的对象实例都拥有一个 ValueStack 对象). 相当于一个数据的中转站. 在其中保存当前 Action 对象和其他相关对象.
Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中。
在 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
二、OGNL
在 JSP 页面上可以可以利用 OGNL(Object-Graph Navigation Language: 对象-图导航语言) 访问到值栈(ValueStack) 里的对象属性。
若希望访问值栈中 ContextMap 中的数据,需要给OGNL表达式加上一个前缀字符
#
。如果没有前缀字符#,搜索将在ObjectStack里进行。
1. property标签
Struts 的 property 标签用来输出值栈中的一个属性值.
jsp文件上面需要导入标签库:
<%@ taglib prefix="s" uri="/struts-tags" %>
2. 读取ObjectStack里对象的属性
- 想要访问ObjectStack里对象的属性。可以使用以下几种形式之一:
object.propertyName object['propertyName'] object["propertyName"]
- ObjectStack 里的对象可以通过一个从零开始的下标来引用。 ObjectStack 里的栈顶对象可以用 [0] 来引用, 它下面的那个对象可以用 [1] 引用.。若希望返回栈顶对象的 message 属性值:
或[0].message
或[0]["message"]
,结合property标签,可以写成:[0]['message']
或者<s:property value="[0].message" />
<s:property value="message" />
- 若在指定的对象里没有找到指定的属性, 则到指定对象的下一个对象里继续搜索. 即 [n] 的含义是从第 n 个开始搜索, 而不是只搜索第 n 个对象
- 若从栈顶对象开始搜索, 则可以省略下标部分
默认情况下,Action 对象会被Struts2自动的放到值栈的栈顶。
3. 读取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
4. 调用字段和方法
可以利用 OGNL 调用
- 任何一个 Java 类里的静态字段或方法.
- 被压入到 ValueStack 栈的对象上的公共字段和方法.
默认情况下, Struts2 不允许调用任意 Java 类静态方法, 需要重新设置
struts.ognl.allowStaticMethodAccess
标记变量的值为 true.
调用静态字段或方法需要使用如下所示的语法:
-
@[email protected]:
例如:
@[email protected]
-
@[email protected](argumentList):
例如:
@[email protected]()
调用一个实例字段或方法的语法, 其中 object 是 Object Stack 栈里的某个对象的引用:
- object.fieldName:
[0].datePattern
- object.methodName(argumentList):
[0].repeat(3, “Hello”);
5. 访问数组类型的属性
- 有些属性将返回一个对象数组而不是单个对象, 可以像读取任何其他对象属性那样读取它们。这种数组型属性的各个元素以逗号分隔, 并且不带方括号。
- 可以使用下标访问数组中指定的元素:
colors[0]
- 可以通过调用其 length 字段查出给定数组中有多少个元素:
colors.length
6. 访问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”}
7. 访问Map类型的属性
- 读取一个 Map 类型的属性将以如下所示的格式返回它所有的键值对:
{ key-1=value-1, key-2=value-2,... key-n=value-n,}
- 若希望检索出某个 Map 的值, 需要使用如下格式:
map[key]
- 可以使用
或size
得出某个给定的 Map 的键值对的个数size()
- 可以使用
或isEmpty
检查某给定 Map 是不是空.isEmpty()
- 可以使用如下语法来创建一个 Map:
#{ key-1:value-1, key-2:value-2,... key-n:value-n,}
8. 使用EL访问值栈中对象的属性
<s:property value=“fieldName”>
也可以通过 JSP EL 来达到目的:
${fieldName}
原理: Struts2 将包装
HttpServletRequest
对象后的
org.apache.struts2.dispatcher.StrutsRequestWrapper
对象传到页面上, 而这个类重写了
getAttribute()
方法.
END.