一、contextMap中的数据操作
![](https://yqfile.alicdn.com/img_1b663290031040f2394484f1fe6350ab.png?x-oss-process=image/resize,w_1400/format,webp)
1、存数据:
需要熟悉 ActionContext类
和 ValueStack接口
的 API
。框架为我们存数据。
1.1、利用 ActionContext 存数据
我们先看看 ActionContext.class 的源码:
![](https://yqfile.alicdn.com/img_45fb5540d477d2ef8412e57a1effb48f.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_ef4d3155fc2d25119e34b8ebbf7ac43c.png?x-oss-process=image/resize,w_1400/format,webp)
1.2、利用 ValueStack 存数据
a、如何获取ValueStack呢?
![](https://yqfile.alicdn.com/img_8b6c9aa975083b34b386d3d816f6adff.png?x-oss-process=image/resize,w_1400/format,webp)
b、ValueStack中的getRoot()方法。
![](https://yqfile.alicdn.com/img_d3f8267f855232a4d574465c69b8d83b.png?x-oss-process=image/resize,w_1400/format,webp)
c、CompoundRoot是什么?
![](https://yqfile.alicdn.com/img_4baa794a75f0643ad24b6de2c73e184b.png?x-oss-process=image/resize,w_1400/format,webp)
d、栈操作。
动作类中相应的代码为:
![](https://yqfile.alicdn.com/img_7b646a77cd0640b3fa866030a146a2a8.png?x-oss-process=image/resize,w_1400/format,webp)
学生实体类代码:
![](https://yqfile.alicdn.com/img_76241a82450b0caab30a7fd63bbed0db.png?x-oss-process=image/resize,w_1400/format,webp)
Struts Debug页面查看数据:
![](https://yqfile.alicdn.com/img_d7086454cc3884276316ef5ed844b9bc.png?x-oss-process=image/resize,w_1400/format,webp)
2、取数据:用Struts2的标签(OGNL表达式)在JSP上(用的最多)
使用OGNL表达式来去,struts2的OGNL表达式必须写在struts2标签中。
2.1、使用s:property取数据
a、取contextMap中的数据,需使用 #key
。
![](https://yqfile.alicdn.com/img_08985a7642209fe1e84e4b83debf29cf.png?x-oss-process=image/resize,w_1400/format,webp)
b、取contextMap里面ValueStack中对象的属性:直接写属性名
![](https://yqfile.alicdn.com/img_0074c91e050221fd2aea1ea6179e266b.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_51ea2d780437a6237dad1a2c444e1c69.png?x-oss-process=image/resize,w_1400/format,webp)
如果遇有对象的属性的名称相同(属性名同名),可以通过OGNL表达式,选择查找的起始位置。它会从指定起始位置逐个对象查找指定的属性名称,只要找到了,就不再继续查找了。
![](https://yqfile.alicdn.com/img_cb7857c6150dca47b3e46238da9f16c1.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_9f59bc3ab3dc0e50549fa6b3214221dd.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_99a607fd2e460008dce2ae2d6cb6658b.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_3c7d39dd18fd09858b8978f07fa8c114.png?x-oss-process=image/resize,w_1400/format,webp)
特殊说明:当s:property不给定value属性时,默认取栈顶对象。
![](https://yqfile.alicdn.com/img_93a1624b7bd2a9eeb6d56f303ad69378.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_5824c17a0a0162ab18f833622d088e43.png?x-oss-process=image/resize,w_1400/format,webp)
OGNL的使用总结:
1.取根(root)中对象的属性,不使用#。
2.取contextMap中key的值,要使用#。
2.2、ValueStack的其他方法
a、setValue方法
![](https://yqfile.alicdn.com/img_b638ed92d419706dad41c8eb881e2700.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_dd72fa85293fa2b5a6762665d09d6668.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_2e337c0bdf0a0902f352444aab47ab5b.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_48ab678149506e2df42a1a491171b09a.png?x-oss-process=image/resize,w_1400/format,webp)
b、set方法
![](https://yqfile.alicdn.com/img_35dd1765af8b1d684a97c15851bf2102.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_a7048ae6d41151fc8dee342a26b33dbc.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_6f2c8bab59be864df0117e9a3b806c61.png?x-oss-process=image/resize,w_1400/format,webp)
c、findValue方法:我们在jsp上调用的其实都是findValue
![](https://yqfile.alicdn.com/img_1361021986516c7d7f248885022d2fbe.png?x-oss-process=image/resize,w_1400/format,webp)
二、Struts2对EL的改变
1、Struts2中使用EL的问题
前提:
我们应该知道,如果我们在动作类中没有往 值栈(根) 中放入数据的话,那么我们的动作类对象默认是在值栈的栈顶。
![](https://yqfile.alicdn.com/img_f0bae7db77a22d5618fd970b7cde3641.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_ac155928f5114188ada7de5dd0f17fbe.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_466d83a0111d29e82551c1a63377b922.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_ee3a6355126b8bb6dad3e35dbea839cb.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_0bcf77f9616f7acee3f0ccf2ddc66201.png?x-oss-process=image/resize,w_1400/format,webp)
问题:
我们放到动作类中的属性和请求域中的属性,使用EL表达式取出来了。但是放到应用域中的属性,使用EL表达式没取出来。
2、关于EL问题的分析
分析:
我们知道EL表达式是从四大域对象中依次查找属性。搜索范围是由小到大。
查找顺序:pageScope --> requestScope --> sessionScope --> applicationScope
但是通过测试发现,程序搜索放到应用域中的name属性,搜索完request范围后就没有继续搜索了,原因是:在请求域中没有找到的情况下,去ValueStack中查找了,返回了ValueStack中栈顶对象name属性的值。
问题出现在这个request的包装类上了,该包装类对getAttribute方法进行了改写,如下图所示:
![](https://yqfile.alicdn.com/img_5eee1e101469e8d96121feefebd62697.png?x-oss-process=image/resize,w_1400/format,webp)
我们来看看这个包装类的源码:
![](https://yqfile.alicdn.com/img_71df58f92c88fc48d641e5e3ca509f4d.png?x-oss-process=image/resize,w_1400/format,webp)
3、Struts2中EL查找顺序改变总结
EL表达式的查找顺序:pageScope --> requestScope --> sessionScope --> applicationScope
Struts2对EL表达式查找顺序的改变:pageScope --> requestScope --> valueStack(根中)
--> 剩余的contextMap(小Map)
--> sessionScope --> applicationScope
4、OGNL的特殊说明
![](https://yqfile.alicdn.com/img_e054ae762b84f36c03b19bdfcc11f970.png?x-oss-process=image/resize,w_1400/format,webp)
当我们不写#号时,OGNL表达式会从值栈的栈顶开始找对应的属性,如果没有该属性,再去contextMap中把value的值作为key去查找对应的值。
这个知道就行,我们开发中一般不这么写!
![](https://yqfile.alicdn.com/img_110dc6994bbca60dd404af94d802f8bc.png?x-oss-process=image/resize,w_1400/format,webp)
三、OGNL配合通用标签的其他使用
1、iterator标签(很重要)
![](https://yqfile.alicdn.com/img_7e0605c7edb515992f63b1ff3566a758.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_818ceb752c0f3f853c62b8e9489933af.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_e35e869185c604e17c08db309a0a9bd9.png?x-oss-process=image/resize,w_1400/format,webp)
2、OGNL投影(了解)
2.1、使用过滤条件投影
2.2、投影指定属性
如下图所示:
![](https://yqfile.alicdn.com/img_50a1258a09e7b3c6e486e4ea337c8cb6.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_41e5c702810274f5c524c3f7f146fbe1.png?x-oss-process=image/resize,w_1400/format,webp)
3、Struts2中 `#,$,%` 符号的使用(重要)
3.1、#
a、取contextMap中键key对应的值value时使用,例如:<s:property value="#name"/>
b、OGNL中创建Map对象时使用,例如:<s:radio list="#{'male':'男', 'female':'女'}"/>
3.2、$
a、在JSP中使用EL表达式时使用,例如:${name}
b、在xml配置文件中,编写OGNL表达式时使用,例如:文件下载时,文件名编码:
struts.xml --> ${@java.net.URLEncoder.encode(filename)}
3.3、%
在struts2中,有些标签的value属性取值就是一个OGNL表达式,例如:<s:property value="OGNL Expression"/>
还有一部分标签,value属性的取值就是普通字符串,例如:<s:textfield value="username"/>
,
如果想把一个普通的字符串强制看成是OGNL表达式,就需要使用 %{}
把字符串套起来。例如:<s:textfield value="%{username}"/>
。
当然在 <s:property value="%{OGNL Expression}"/>
也可以使用,但一般不会这么用,因为你两次告诉我你是OGNL表达式,不是有病吗!
4、Struts2中其他标签的使用
4.1、set标签
![](https://yqfile.alicdn.com/img_710c5f4fac777ff586e6fef0f86aee3c.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_b5ff93f7dfcad5fdf166687519548739.png?x-oss-process=image/resize,w_1400/format,webp)
4.2、action标签
![](https://yqfile.alicdn.com/img_ddc63a83acef4a40a129f1b69dd308e1.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_2cf72a832eaad00d5834ad060d8bf942.png?x-oss-process=image/resize,w_1400/format,webp)
4.3、if标签,elseif标签 else标签
![](https://yqfile.alicdn.com/img_1b0ade6c2ff63e8b6cb4ccd2248a33ff.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_92b801f7465fffebf8e1874315313a77.png?x-oss-process=image/resize,w_1400/format,webp)
4.4、url和a标签(很有用)
![](https://yqfile.alicdn.com/img_fe26d7a8571957f23040acb92256f654.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_c2481160cd19476558550b433a31aec8.png?x-oss-process=image/resize,w_1400/format,webp)
修改动作名称的扩展名
![](https://yqfile.alicdn.com/img_1be381a29ae6b7f753b1c9a980e04c38.png?x-oss-process=image/resize,w_1400/format,webp)
四、Struts2的UI标签和主题
1、Struts2中UI标签的优势
自动的数据回显和错误提示功能
自带的简单样式和排版
2、表单标签的通用属性
说明:UI标签中value的取值一般都是字符串。
2.1、UI标签的通用属性
![](https://yqfile.alicdn.com/img_d5652f9b9cccbe34ca2ccf19fc401359.png?x-oss-process=image/resize,w_1400/format,webp)
2.2、关于标签checkboxlist的使用
![](https://yqfile.alicdn.com/img_62907a924599fee509f54837589a280f.png?x-oss-process=image/resize,w_1400/format,webp)
2.3、UI标签的小案例以及模型驱动的分析
![](https://yqfile.alicdn.com/img_956f2bea6d674d835229f333aa52ac04.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_9ef1a94bd2f4489fc081537cf248891b.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_20d7ae5365892dd245a576baa016b3b2.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_a31f8c542e3b7fb1b895ce5c42240603.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_28de8c9a04226766b3dcd96b6b62be28.png?x-oss-process=image/resize,w_1400/format,webp)
3、UI标签的模板(主题)
3.1、struts2中默认主题
默认主题的名称是XHTML,都是在struts的默认属性文件中定义着,该文件是:default.properties,
文件位置:\struts-2.3.15.3-all\struts-2.3.15.3\apps\struts2-blank\WEB-INF\lib\struts2-core-2.3.15.3\org\apache\struts2\default.properties
![](https://yqfile.alicdn.com/img_97d603fc511a1dcbd66f8b5269d9da8b.png?x-oss-process=image/resize,w_1400/format,webp)
3.2、更改默认主题
a、更改表单某个元素的默认主题:使用的是表单元素的theme属性。
b、更改表单所有主题:使用的是form标签的theme属性。
c、更改全站所有表单主题:是在struts.xml配置文件中,覆盖原有主题的设置。
如下图所示:
![](https://yqfile.alicdn.com/img_964ed9b595c18691534b82ce417a17ca.png?x-oss-process=image/resize,w_1400/format,webp)
注意:当我们使用了simple主题后,我们需要
自己添加文本信息
。原来我们在jsp中怎么写,现在还怎么写。
例如:
<s:textfield name="name" label="用户名" />
改写为:
用户名:<s:textfield name="name" />
![](https://yqfile.alicdn.com/img_d1a1d9b7b548753d2f153b9a10b55a67.png?x-oss-process=image/resize,w_1400/format,webp)
五、防止表单重复提交(使用拦截器)
1、回顾之前的解决办法:
![](https://yqfile.alicdn.com/img_af7e4f8485d42f1b941c02eb0f153af1.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_7ba0e82f7a6eec65f46ca66e16f3696e.png?x-oss-process=image/resize,w_1400/format,webp)
2、Struts2中的解决办法:
2.1、使用重定向
![](https://yqfile.alicdn.com/img_2f257c16747591fefdff1126907f0a33.png?x-oss-process=image/resize,w_1400/format,webp)
遗留的问题:刷新页面,再提交没有问题,但是防不住后退,再提交。
2.2、表单上使用
<s:token/>
生成令牌,再配合
token拦截器
,在struts.xml中进行相关的配置
![](https://yqfile.alicdn.com/img_b8b9308ae75f0cafb5b62c648e588fb7.png?x-oss-process=image/resize,w_1400/format,webp)
![](https://yqfile.alicdn.com/img_0d56cf6d284340316b683b2275f4ea70.png?x-oss-process=image/resize,w_1400/format,webp)
点击后退再提交时,会提示:没有一个invalid.token的结果视图,如下图所示:
![](https://yqfile.alicdn.com/img_e6de623843d91e9b19ab2c45f3396564.png?x-oss-process=image/resize,w_1400/format,webp)
那我们就配置一下这个invalid.token的结果视图:
![](https://yqfile.alicdn.com/img_9adcdd7fb35a8fa823e10ddfbbcd0d17.png?x-oss-process=image/resize,w_1400/format,webp)
遗留的问题:此种解决方式,是产生了错误之后再去告知用户,你错了。
2.3、表单上使用
<s:token/>
生成令牌,再配合
tokenSession拦截器
,在struts.xml中进行相关的配置
![](https://yqfile.alicdn.com/img_989c6617d2e6b1e5b40859a2886e0854.png?x-oss-process=image/resize,w_1400/format,webp)
我的博客园地址: http://www.cnblogs.com/chenmingjun
我的蚂蚁笔记博客地址: http://blog.leanote.com/chenmingjun
Copyright ©2018 黑泽明军
【转载文章务必保留出处和署名,谢谢!】