propertyvalue="something"/>
6.body>
7.html>
==============================
Action的实例,总是放到valuestack中。
因为Action放在stack中,而stack是root(根对象),所以对Action中的属性的访问就可以省略#标记。
但是,要访问ActionContext中其它对象的属性,就必须要带上#标记,以便让OGNL知道,不是从根对象,而是从其它对象中去寻找。
Struts2中OGNL,valueStack,stackContext的学习
学习Struts2,一直不明白表单中的值是怎么传给Action的,上网查了些资料,基本了解了!
下面基本是从几个人的BOLG转载过来,以后记不清了再来看~
[color=red]先看看我做的实验jsp页面
Java代码
formaction="hello/converter.action"method="post">
textfieldname="point"label="点">
textfield>
textfieldname="point2"label="2">
textfield>
textfieldname="point3"label="3">
textfield>
textfieldname="age"label="年龄">
textfield>
textfieldname="date"label="日期">
textfield>
submitname="提交">
submit>
form>
结果图(是通过debug>
debug>得到的)
valuestack:
Stackcontext:
通过图中我们可以看到
valuestack中包括我传递的值(point,point2,point3,age,date)
stackcontext中包括了requestapplicationOgnlValueStack(root)sessionparameters等属性
值栈(ValueStack)
Struts2将OGNL上下文设置为Struts2中的ActionContext(内部使用的仍然是OgnlContext),并将值栈设为OGNL的根对象。
我们知道,OGNL上下文中的根对象可以直接访问,不需要使用任何特殊的“标记”,而引用上下文中的其他对象则需要使用“#”来标记。
由于值栈是上下文中的根对象,因此可以直接访问。
那么对于值栈中的对象该如何访问呢?
Struts2提供了一个特殊的OGNLPropertyAccessor,它可以自动查找栈内的所有对象(从栈顶到栈底),直接找到一个具有你所查找的属性的对象。
也就是说,对于值栈中的任何对象都可以直接访问,而不需要使用“#”。
假设值栈中有两个对象:
student和employee,两个对象都有name属性,student有学号属性number,而employee有薪水属性salary。
employee先入栈,student后入栈,位于栈顶,那么对于表达式name,访问的就是student的name属性,因为student对象位于栈顶;表达式salary,访问的就是employee的salary属性。
正如你所见,访问值栈中的对象属性或方法,无须指明对象,也不用“#”,就好像值栈中的对象都是OGNL上下文中的根对象一样。
这就是Struts2在OGNL基础上做出的改进。
值栈中的Action实例
Struts2框架总是把Action实例放在栈顶。
因为Action在值栈中,而值栈又是OGNL中的根,所以引用Action的属性可以省略“#”标记,这也是为什么我们在结果页面中可以直接访问Action的属性的原因。
Struts2中的命名对象
Struts2还提供了一些命名对象,这些对象没有保存在值栈中,而是保存在ActionContext中,因此访问这些对象需要使用“#”标记。
这些命名对象都是Map类型。
parameters
用于访问请求参数。
如:
#parameters['id']或#parameters.id,相当于调用了HttpServletRequest对象的getParameter()方法。
注意,parameters本质上是一个使用HttpServletRequest对象中的请求参数构造的Map对象,一量对象被创建(在调用Action实例之前就已经创建好了),它和HttpServletRequest对象就没有了任何关系。
request
用于访问请求属性。
如:
#request['user']或#request.user,相当于调用了HttpServletRequest对象的getAttribute()方法。
session
用于访问session属性。
如:
#session['user']或#session.user,相当于调用了HttpSession对象的getAttribute()方法。
application
用于访问application属性。
如:
#application['user']或#application.user,相当于调用了ServletContext的getAttribute()方法。
attr
如果PageContext可用,则访问PageContext,否则依次搜索request、session和application对象。
以下是转过来的:
先分清楚下ActionContext、ValueStack、StackContext三者
ActionContext
一次Action调用都会创建一个ActionContext
调用:
ActionContextcontext=ActionContext.getContext()
ValueStack
由OGNL框架实现
可以把它简单的看作一个栈(List)。
StackObject:
放入stack中的对象,一般是action。
StackContext(map):
stack上下文,它包含一系列对象,包括request/session/attr/applicationmap等。
EL:
存取对象的任意属性,调用对象的方法,遍历整个对象结…
ActionContext是Action上下文,可以得到requestsessionapplication
ValueStack是值栈存放表单中的值
StackContext栈上下文也是用来存值的
struts2对OGNL上下文的概念又做了进一步扩充,在struts2中,OGNL上下文通常如下所示:
|--request
|
|--application
|
contextmap---|--OgnlValueStack(root)[user,action,OgnlUtil,...]
|
|--session
|
|--attr
|
|--parameters
在Struts2中,采用标准命名的上下文(Context)来处理OGNL表达式。
处理OGNL的顶级对象是一个Map(也叫contextmap),而OGNL在这个context中就是一个顶级对象(root)。
在用法上,顶级对象的属性访问,是不需要任何标记前缀的。
而其它非顶级的对象访问,需要使用#标记。
Struts2框架把OGNLContext设置为我们的ActionContext。
并且ValueStack作为OGNL的根对象。
除valuestack之外,Struts2框架还把代表application、session、request这些对象的Map对象也放到ActionContext中去。
(这也就是Struts2建议在Action类中不要直接访问ServletAPI的原因,他可以通过ActionContext对象来部分代替这些(ServletAPI)功能,以方便对Action类进行测试!
)
Action的实例,总是放到valuestack中。
因为Action放在stack中,而stack是root(根对象),所以对Action中的属性的访问就可以省略#标记。
但是,要访问ActionContext中其它对象的属性,就必须要带上#标记,以便让OGNL知道,不是从根对象,而是从其它对象中去寻找。
那么访问Action中的属性的代码就可以这样写
propertyvalue="postalCode"/>
其它ActionContext中的非根对象属性的访问要像下面这样写:
propertyvalue="#session.mySessionPropKey"/>or
propertyvalue="#session['mySessionPropKey']"/>or
propertyvalue="#request['myRequestPropKey']"/>
对Collection的处理,内容就很简单。
selectlabel="label"name="name"list="{'name1','name2','name3'}"value="%{'name2'}"/>
这是处理List。
这个代码在页面上建立一个下拉选项,内容是list中的内容,默认值是name2.
处理map
selectlabel="label"name="name"list="#{'foo':
'foovalue','bar':
'barvalue'}"/>
需要注意的是,判断一个值是否在collection中。
我们要使用in或者notin来处理。
iftest="'foo'in{'foo','bar'}">
muhahaha
if>
else>
boo
else>
另外,可以使用通配符来选择collection对象的子集。
?
——所有匹配选择逻辑的元素
^——只提取符合选择逻辑的第一个元素
$——只提取符合选择逻辑的最后一个元素
person.relatives.{?
#this.gender=='male'}
`````````````````````````````````````````````````````````````````````````````````
以下为补充摘录的一些问题:
提问:
在Struts2中,如何使用自身的Tag读取Action中的变量?
Struts2自身的Tag会根据value中的OGNL表达式,在ValueStack中寻找相应的对象。
因为action在ValueStack的顶部,所以默认情况下,Struts2的Tag中的OGNL表达式将查找action中的变量。
请注意,value中的内容直接是OGNL表达式,无需任何el的标签包装。
例如:
propertyvalue="user.name"/>
提问:
在Struts2中,如何使用自身的Tag读取HttpServletRequest,HttpSession中的变量?
在上面的知识中,我们知道,Struts2中OGNL的上下文环境中,包含request,session,application等servlet对象的Map封装。
既然这些对象都在OGNL的上下文中,那么根据OGNL的基本知识,我们可以通过在表达式前面加上#符号来对这些变量的值进行访问。
例如:
propertyvalue="%{#application.myApplicationAttribute}"/>
propertyvalue="%{#session.mySessionAttribute}"/>
propertyvalue="%{#request.myRequestAttribute}"/>
propertyvalue="%{#parameters.myParameter}"/>
提问:
在Struts2中,如何使用JSTL来读取Action中的变量?
这是一个历史悠久的问题。
因为事实上,很多朋友(包括我在内)是不使用Struts2自身的标签库,而是使用JSTL的,可能因为JSTL标签库比较少,简单易用的原因吧。
我们知道,JSTL默认是从page,request,session,application这四个Scope逐次查找相应的EL表达式所对应的对象的值。
那么如果要使用JSTL来读取Action中的变量,就需要把Action中的变量,放到request域中才行。
所以,早在Webwork2.1.X的年代,我们会编写一个拦截器来做这个事情的。
大致的原理是:
在Action执行完返回之前,依次读取Action中的所有的变量,并依次调用reque