(2)Web资源对应的Map对象
Key | Value |
com.opensymphony.xwork2.ActionContext.application | 封装Application域数据的Map对象 |
application | 封装Application域数据的Map对象 |
|
|
request | 封装请求域数据的Map对象 |
|
|
com.opensymphony.xwork2.ActionContext.parameters | 封装请求参数数据的Map对象 |
parameters | 封装请求参数数据的Map对象 |
|
|
com.opensymphony.xwork2.ActionContext.session | 封装Session域数据的Map对象 |
session | 封装Session域数据的Map对象 |
|
|
attr | 可以按范围从小到大顺序在所有域对象中查询数据的特殊Map对象 |
补充说明:
[1]除了request的Map对象,其他几个域对象都有两个键指向,一个键较长,一个键较短,嗯,放心吧,他们指向的是同一个对象。
[2]关于attr这个Map,它能够按照范围由小到大的顺序在各个域对象中查询数据,看源码就知道——它的实现类是org.apache.struts2.util.AttributeMap
public Object get(Object key) { PageContext pc = getPageContext();
if (pc == null) { Map request = (Map) context.get("request"); Map session = (Map) context.get("session"); Map application = (Map) context.get("application");
if ((request != null) && (request.get(key) != null)) { return request.get(key); } else if ((session != null) && (session.get(key) != null)) { return session.get(key); } else if ((application != null) && (application.get(key) != null)) { return application.get(key); } } else { try{ return pc.findAttribute(key.toString()); }catch (NullPointerException npe){ return null; } }
return null; } |
(3)ValueStack对象
Key | Value |
com.opensymphony.xwork2.util.ValueStack.ValueStack | 值栈对象 |
补充说明:看到这个你会不会困惑呢?是的,你没有看错,Struts2确实是把ValueStack值栈对象放入了context这个Map当中,上面显示的key指向的是ValueStack对象的引用。ActionContext对象就是通过这种方式获取ValueStack对象的。其实Struts2还将ValueStack对象的引用又复制了一份放到了请求域中——是不是有点狡兔三窟的感觉?通过很多方式都能够得到ValueStack对象的引用,之所以这样无非是为了在不同情况下方便的获取值栈。稍后我们会盘点获取值栈对象的所有方法。
(4)与Action类运行相关的环境信息
Key | Value |
com.opensymphony.xwork2.ActionContext.name | 当前action的name属性值 |
action | 当前Action类的实例对象 |
com.opensymphony.xwork2.ActionContext.conversionErrors | {}空Map |
com.opensymphony.xwork2.ActionContext.locale | en_US或zh_CN等 |
last.property.accessed | null |
last.bean.accessed | null |
xwork.NullHandler.createNullObjects | false |
current.property.path | null |
com.opensymphony.xwork2.ActionContext.container | com.opensymphony.xwork2.inject.ContainerImpl对象 |
com.opensymphony.xwork2.ActionContext.actionInvocation | com.opensymphony.xwork2.DefaultActionInvocation对象 |
xwork.MethodAccessor.denyMethodExecution | false |
report.conversion.errors | false |
struts.actionMapping | ActionMapping Map对象 |
⑤总结
ValueStack对象与其他对象的关系可以概括为下面这个图
获取ValueStack对象的途经
通过上面对ValueStack对象数据结构的分析我们很容易得出获取ValueStack对象的两个较为直接的途经:
①通过ActionContext对象获取
ValueStack valueStack = ActionContext.getContext().getValueStack(); |
②通过读取请求域获取
ValueStack valueStack = (ValueStack) requestMap.get("struts.valueStack"); |
ValueStack对象和请求的关系
在Action类中打印ValueStack对象发现每一个ValueStack对象的HashCode值都不同,证明Struts2为每一个请求创建一个新的ValueStack对象。这就保证了读写值栈中数据的时候不会有线程安全的问题。
三、OGNL
1.OGNL概述
①OGNL是Apache Commons下的一个子项目,同在Commons下的子项目还有我们用过的FileUpload、IO、BeanUtils、DbUtils、Logging等。
②OGNL并不依赖Struts2存在,创建一个Java工程就能够对OGNL进行测试,此时需要导入两个JAR包
javassist-3.11.0.GA.jar
ognl-3.0.6.jar
[这两个JAR包可以在Struts2提供的blank例子工程的lib目录下找到]
2.OGNL:对象图导航语言
①对象图:Java对象可连续访问的级联属性形成的图形结构
例如:department.getEmpList().get(3).getAddress().getCity();
当对象嵌套层次较深时,按照对象自身的属性进行访问往往过于冗长。
②导航语言:以表达式的形式快速定位到对象图中的某个属性
类似:jQuery选择器、xPath表达式等
③OGNL表达式语法
[1]Ognl.getValue()方法未指定上下文对象:从根对象中读取数据
(1)读取普通对象的属性:"对象.属性名"或"对象[属性名]"
(2)读取List/数组对象的元素:"List/数组对象[下标]"
(3)读取Map对象中键对应的值:"Map对象['键']"或"Map对象.键"
[2]Ognl.getValue()方法指定了上下文对象
(1)OGNL表达式中没有使用#号,表示在根对象中查找数据
(2)OGNL表达式中以#key的形式表示在上下文对象中以key为键查找对应的值
④其他语法
[1]调用对象非静态方法
"对象.方法名()"或"对象.方法名('字符串或基本数据类型参数')"
[2]调用对象静态方法:
"@全类名@方法名()"或"@全类名@方法名('字符或基本数据串类型参数')"
[3]访问对象静态属性:"@全类名@属性名"
3.ValueStack中的OGNL
①对应关系
[1]CompoundRoot对象对应OGNL中的根对象
[2]context对象对应OGNL中的上下文环境对象
源码:com.opensymphony.xwork2.ognl.OgnlUtil.getValue(String, Map<String, Object>, Object)
②重要区别
在OGNL语法中,访问List或数组类型的根对象时必须使用“[]”指定下标,但如果根对象是CompoundRoot对象,则可以省略下标。
如果省略了下标,仅指定了对象的属性名时,将从栈顶元素向下开始查找包含这个属性名的对象,直到为止。
即使指定了下标,也不是仅从下标指向的对象开始查找,而是从指向的对象开始向下查找直到找到为止。
③访问静态资源
默认情况下Struts2不允许通过OGNL表达式访问静态资源,必须加入如下设置
<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant> |
④通过ValueStack对象调用public abstract Object findValue(String expr);方法即可执行OGNL表达式
本教程由尚硅谷教育大数据研究院出品,如需转载请注明来源。