Structs2 HelloWorld-05 OGNL

一、值栈

1、  值栈是什么

简单的说:值栈是对应每一个请求对象的轻量级的内存数据中心。

Struts2中一个很激动人心的特性就是引入了值栈,在这里统一管理着数据,供Action、Result、Interceptor等Struts2的其他部分使用,这样一来,数据被集中管理起来而不会凌乱,大大方便了程序编写。
Struts2中关于值栈的另外一个很激动人心的特性就是:大多数情况下,你根本无需关心值栈,你不用管它在哪里,不用管它里面有什么,你只需要去获取自己需要的数据就可以了。也就是说,你可以隐式的使用值栈。
当然,如果编写自定义的Result或拦截器等较复杂功能的时候,还是需要显示访问值栈的,因此,还是需要你掌握值栈的知识。
2、 值栈能干什么
简单的说,值栈能够线程安全的为每个请求提供公共的数据存取服务。
       当有请求到达的时候,Struts2会为每个请求创建一个新的值栈,也就是说,值栈和请求是一一对应的,不同的请求,值栈也不一样,而值栈封装了一次请求所有需要操作的相关的数据。
       正是因为值栈和请求的对应关系,因而值栈能保证线程安全的为每个请求提供公共的数据存取服务。
3、  值栈有什么
事实上,到现在为止,我们一直在讲“值栈”,这种说法其实是不够准确的。为什么呢?因为在Struts2中,值栈又有广义和狭义之分:
3、1:狭义值栈
       通常指的是实现com.opensymphony.xwork2.util.ValueStack接口的对象,目前就是com.opensymphony.xwork2.ognl.OgnlValueStack对象。
       狭义值栈主要用来存取动态EL(表达式语言)运算需要的值和结果,当然OgnlValueStack对象主要是用来支持OGNL(对象图导航语言)运算的。
狭义值栈里面存放着一些OGNL可以存取访问的数据,典型如:
• Action的实例,这样就可以通过OGNL来访问Action实例中的属性的值了
• OGNL表达式运算的值,可以设置到值栈中,可以主动访问值栈对象,强行设置
• OGNL表达式产生的中间变量,比如在后面使用Struts2的标签的时候,使用循环标签,自然会有循环的变量,这些都存放在值栈中
3、2:广义值栈
通常指的是ActionContext对象,ActionContext是Action运行的上下文,每个ActionContext是一个基本的容器,包含着Action运行需要的数据,比如请求参数、会话等。
ActionContext是线程安全的,每个线程有一个独立的ActionContext,这样你就不用担心值栈中值的线程安全问题了。
ActionContext里面存放有很多的值,典型如:
  • Request的parameters:请求中的参数,要注意这里的数据是从请求对象里面拷贝出来的,因此这里数据的变化是不会影响到请求对象里面的参数的值的
  • Request的Attribute:请求中的属性,这里其实就是个Map,存放着请求对象的属性数据,这些数据和请求对象的Attribute是连动的
  • Session的Attribute:会话中的属性,这里其实就是个Map,存放着会话对象的属性数据,这些数据和会话对象的Attribute是连动的
  • Application的Attribute:应用中的属性,这里其实就是个Map,存放着应用对象的属性数据,这些数据和应用对象的Attribute是连动的
  • Value stack:也就是狭义值栈,ActionContext以value stack作为被OGNL访问的根,简单点说,OGNL在没有特别指明的情况下,访问的就是value stack里面的数据
  • attr:在所有的属性范围中获取值,依次搜索page、request、session和application。
前面已经了解到Xwork与Web是无关的,因此Action不用去依赖于任何Web容器,不用和Servlet 的API去交互,但是Action需要能访问到Web应用的数据,不仅仅是取得请求参数的值,往往也需要在Action里直接获取请求或会话的一些数据,对于这些数据,现在都可以通过ActionContext来获取到。
3、3:关于广义和狭义
你会看到,在ActionContext里面其实是包含着狭义值栈的,正是因为这个原因,再加上ActionContext还包含其他的数据,因此把ActionContext称为广义值栈。
今后在说值栈的时候,没有特别指明的情况下,多数就是指的广义值栈,反正开发的时候都是说从值栈中获取值。当然,有一种情况除外,就是在页面上使用OGNL的时候,没有特殊标识的情况下,默认是从value statck中取值的。

在structs2 第一个实例中,

1). helloWorld 时, ${productName} 读取 productName 值, 实际上该属性并不在 request 等域对象中, 而是从值栈中获取的.

2). ValueStack:

I. 可以从 ActionContext 中获取值栈对象
II. 值栈分为两个逻辑部分

> Map 栈: 实际上是 OgnlContext 类型, 是个 Map, 也是对 ActionContext 的一个引用. 里边保存着各种 Map:
requestMap, sessionMap, applicationMap, parametersMap, attr
> 对象栈: 实际上是 CompoundRoot 类型, 是一个使用 ArrayList 定义的栈. 里边保存各种和当前 Action 实例相关的对象.

是一个数据结构意义的栈.

二、读取属性值

1、ognl概述

OGNL是对象图导航语言Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(Expression Language,简称为EL),通过它简单一致的表达式语法,可以存取对象的属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。“<s:property value="account"/>”。

2、取得属性的值

Struts2 利用 s:property 标签和 OGNL 表达式来读取值栈中的属性值

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 标签: <s:property value="[0].message" /> <s:property value="message" />

3). 默认情况下, Action 对象会被 Struts2 自动的放到值栈的栈顶. 

4).若想访问 ContextMap 里的某个对象的属性, 可以使用以下几种形式之一:

示例:

  • 返回 session 中的 code 属性: #session.code
  • 返回 request 中的 customer 属性的 name 属性值: #request.customer.name
  • 返回域对象(按 request, session, application 的顺序)的 lastAccessDate 属性: #attr.lastAccessDate

5)调用字段和方法

可以利用 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”);

6)调用数组

有些属性将返回一个对象数组而不是单个对象, 可以像读取任何其他对象属性那样读取它们. 这种数组型属性的各个元素以逗号分隔, 并且不带方括号

可以使用下标访问数组中指定的元素: colors[0]

可以通过调用其 length 字段查出给定数组中有多少个元素: colors.length

7)访问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”}

8)访问 Map 类型的属性

读取一个 Map 类型的属性将以如下所示的格式返回它所有的键值对: 


若希望检索出某个 Map 的值, 需要使用如下格式: map[key]

可以使用 size 或 size() 得出某个给定的 Map 的键值对的个数

可以使用 isEmpty 或 isEmpty() 检查某给定 Map 是不是空.

可以使用如下语法来创建一个 Map: 

9)使用 EL 访问值栈中对象的属性

<s:property value=“fieldName”> 也可以通过 JSP EL 来达到目的: ${fieldName}

原理: Struts2 将包装 HttpServletRequest 对象后的 org.apache.struts2.dispatcher.StrutsRequestWrapper 对象传到页面上, 而这个类重写了 getAttribute() 方法.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值