笔记:
struts2_03
今日内容:
1 值栈内容
2 ognl内容
技术分析:
ognl内容
ognl:它是一种功能强大的表达式语言
作用:
1 获取对象的方法(了解)
2 获取类的静态属性(了解)
3 获取类的静态方法(了解)
4 获取值栈中的数据(重点)
其实ognl是一个单独存在的表达式语言,struts把ognl这门语言整合到了自己的框架中,
所有:struts2的默认表达式语言就是--ognl
入门:
条件: ognl在页面没办法单独使用,要结合struts2的内置标签来使用。
===【引入标签库,prefix: s:前缀,uri:alter+/自动补全。】
<!-- ongl的入门操作 -->
<!-- 获取对象的方法(了解) <s:property value="ognl表达式了" /> -->
字符串hello的长度是: <s:property value="'hello'.length()" /><br/>
<!-- 获取类的静态属性(了解) 条件: @类的全限定名@静态属性 -->
π的值是: <s:property value="@java.lang.Math@PI" /><br/>
<!-- 获取类的静态方法(了解) 条件: 1 @类的全限定名@静态方法 2:要配置常量,允许获取类的静态方法 -->
获取随机数:<s:property value="@java.lang.Math@random()" /><br/>
////////////////////////////////////////////////////////////////////////////////////////////////////
值栈内容:
一: 什么是值栈?
值栈: ValueStack
①在web阶段我们是使用域对象当存储数据的中转站 数据---域对象---页面展示
存储数据的结构:map
②在struts2中提供了值栈可以也当存储数据的中转站 数据---值栈中---页面或则配置文件展示
存储数据的结构:很复杂
有2个区:
root区: 存储数据的结构是 list
context区: 存储数据的结构是 map
值栈用来存储数据的
①在浏览器发送请求访问action的时候,会被struts2的前端控制器(StrutsPrepareAndExecuteFilte)拦截
在过滤器中,会创建action对象,且会创建ValueStack对象(特点:访问一次,创建一次)
②创建完成后,会将整个actio对象放在ValueStack中,且还会将页面数据,request,session,servletContext用来存储数据的
map集合放在ValueStack中(ps:存放的是地址的引用)
③当请求的action执行完毕,action对象会被销毁,且ValueStack对象也会被销毁
下次再访问有是一个新的action对象,和ValueStack对象。
所以:### ValueStack和action的生命周期是同步的,ValueStack会伴随着action的一生
struts2提供了一个值栈的接口:ValueStack 实现类: OgnlValueStack
二: 值栈的内部结构?
域对象底层,用来存储数据的结构:map
代码断点查看:见图。
struts标签的方式查看。页面标签<s:debug />。存到 值栈 的对象的属性 必须有get set,这里才能看见。
三: ActionContext与值栈的关系? 【容易忘--理解:actionContext能够获取ValueStack】######
ActionContext为什么可以获取到ValueStack?
======看源码
结论: 【在过滤器中,会创建ActionContext对象,并且创建valueStack对象,
将valueStack对象的引用给了ActionContext对象。】######【牢记】
四: 值栈的获取方式?
2种方式
1 通过ActionContext对象获取(掌握)
ActionContext.getContext().getValueStack()
2 通过request对象获取(了解)
看源码 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
===<"struts.valueStack",ValueStack>
结论:
valuestack会往request域中放一份
五: 如何操作ValueStack? ######
①怎么往root区存取数据? ###
1 属性设置的方式
直接在action的成员位置上设置属性。===并提供get set?
因为整个action对象的引用就在root区中。######
2 ValueStack对象API的方式
set(String key, Object o)
底层会【自动创建一个map集合】,将set的key放在map的key中,将set的value放在map的value中
最后将封装好的map放在root区中(list)
push(Object o) 存放【单个对象】的数据
②怎么往context区存取数据? ??
-----------------------------------------------------------------------------------------------
el也可以获取到值栈中的数据(了解---看得懂别人代码。---工作自己不会用)
el ${属性名} 以前依次从 pageContext,request,session,application查找
###### 在struts中是以上没有找到,还会去root区和context区查找
底层:
之前的el的${username}
先调用pageContext.getAttribute(..)
获取到,立即返回
获取不到,继续调用
request.getAttribute(..)
------【会有一个现象:EL取request域对象值的方式,也可以取到值栈里put方法存的数据。】
------【解释:源码:找不到,会再去值栈去找(先Root区,再Context区---不深究):因为struts2封装增强了servlet request。】
获取到,立即返回
获取不到,继续调用
session.getAttribute(..)
获取到,立即返回
获取不到,继续调用
application.getAttribute(..)
获取到,立即返回
获取不到,返回""
在struts中的el的底层:装饰者模式
包装了request.=== 对request.getAttribute方法进行了增强.
先依次以以前的方式查询
若都没有查询到,调用了 valueStack.findValue(..)从值栈中查找
-----------------------------------------------------------------------------------------------
ognl中的3个特殊符号: # % $ =====###### 【常用,容易忘 容易错】
① #的作用:
1 获取context区域中的数据。===ok(页面取值用)【常用,容易忘 容易错】
2 可以手动构建一个集合 ===
<!-- 手动构建的list集合 -->
<s:iterator value="{'aa','bb','cc'}" var="aa">
<s:property value="#aa"/>
</s:iterator>
<!-- 手动构建的map集合 -->
<s:iterator value="#{'aa':'111','bb':'222','cc':'333'}" var="mm">
<s:property value="#mm.key"/>----><s:property value="#mm.value"/><br/>
</s:iterator>
<s:radio list="{'男','女'}" name="sex"></s:radio>
<s:radio list="#{'1':'男','2':'女'}" name="sex"></s:radio>
===struts2的页面标签。(暂时不深究)
② %的作用:
强制将标签内容转换成ognl表达式。=====【常用,容易忘 容易错】
<s:textfield value="%{#request.abcd}"></s:textfield>
③ $的作用:
可以在配置文件中获取值栈的数据。=====【常用,容易忘 容易错】
例如文件下载:
<a href='/crm/download.action?filename=1.jpg'>下载图片</a>
返回逻辑视图
在action中提供其中一个属性 filename。====提供get set吗?
配置文件中
<action name="download" class="..." method="">
<result type="stream">
<param name="content-disposition">filename=${filename}</param>
</result>
</action>
案例
list
代码(值栈实用知识点 总结):######
http://pan.baidu.com/s/1qYjvHl6