一、Struts2入门
1. 概念
什么是Struts2
Struts2 是一个用来开发 MVC应用程序的框架.
它提供了 Web 应用程序开发过程中的一些常见问题的解决方案:
对页面导航活动进行管理
对来自用户的输入数据进行合法性验证
统一的布局
可扩展性
国际化和本地化
支持 Ajax
表单的重复提交
Struts2 VS Struts1
Struts2与Struts1 相比,在体系结构方面更优秀,具体表现在类更少,更高效,扩展更容易等。
struts2 不是从 Struts1扩展而来的, 说它是一个换了品牌标签的 WebWork 更合适。
2. 程序
Struts2 核心就是一个Filter,该Filter会对所有的请求进行拦截(/*)
StrutsPrepareAndExecuteFilter
StrutsPrepareFilter + StrutsExecuteFilter
Struts2 将所有的请求拦截下来,具体去访问哪个java类的方法需要读取配置文件 struts.xml
struts.xml文件需位于工程的类路径下
实现一个 Struts 的 HelloWorld 程序
1) 将 %struts2-blank例子%\WEB-INF\lib目录下所有jar包拷贝至 webproject\WEB-INF\lib 中
2) 将%struts2-blank例子%\WEB-INF\web.xml中的配置
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
拷贝至webproject/WEB-INF/web.xml 中
3) %struts2-blank例子%\将WEB-INF\classes 下的struts.xml文件拷贝至工程src下
清空 <struts></ struts> 标签之间的内容
4) 新建Action 实例, HelloWorldAction.java
Action可以不必是实现任何接口,它是一个普通java类(pojo),从这点可以看出 Struts2 是非侵入式设计,Action可以不依赖struts和Servlet而独立存在
Action中至少需要定义一个方法,且方法的返回值类型必须为String
public String sayHello() {
return "success";
}
5) 在struts.xml对 Action进行配置
<struts>
<!—package 用户配置action的组织包名,用于对Action进行归类-->
<package name="first"namespace="/first" extends="struts-default">
<!—配置当前action访问路径,以及对应的action类和调用的方法 -->
<actionname="HelloWorld"
class="cn.itcast.action.HelloWorldAction"
method="sayHello">
<!—配置处理结果,继承struts-default包,默认结果处理类型为 dispatcher -->
<resultname="success">/WEB-INF/hello.jsp</result>
</action>
</package>
</struts>
6) 在WEB-INF 下新建jsp页面hello.jsp
hello
动手练习: 用 struts2 实现最简单的mvc
二、Struts2 细节
1. package 元素
配置action的组织包
name: 配置包名,用于被继承
namespace:配置访问路径
以 /a/b/c/action 为例 搜索action的顺序为/a/b/c -- /a/b -- /a -- /
extends:指定继承的包
2. action 元素
1) name属性
配置action的访问名称 后缀默认为 action和”” 可以通过常量进行配置
<constantname="struts.action.extension" value="do"></constant>
2) class属性
配置action对应的java类,必须为完整类名
如果继承struts-default 包,默认class 为ActionSupport,该类的execute方法默认返回 success
我们在写 Action 类时通常会选择继承ActionSupport,也就自动继承了 execute 方法,同时可以使用父类定义的常量 SUCCESS、ERROR 等
3) method属性
配置action的访问方法名,默认访问execute方法
4) 通配符映射
一个 Web 应用可能有成百上千个 action 声明. 可以利用struts 提供的通配符映射机制把多个彼此相似的映射关系简化为一个映射关系
通配符的映射规则
l 若找到多个匹配, 没有通配符的那个将胜出
l 若指定的Action不存在, Struts 将会尝试把这个URI与任何一个包含着通配符 * 的Action名及进行匹配
l 若 Struts 找到的带有通配符的匹配不止一个, 最后一个匹配将胜出
l 被通配符匹配到的 URI 字符串的子串可以用 {1}, {2} 来引用. {1} 匹配第一个子串, {2} 匹配第二个子串…
{0} 匹配整个URI
l * 可以匹配零个或多个字符, 但不包括 / 字符. 如果想把 / 字符包括在内, 需要使用 **. 如果需要对某个字符进行转义, 需要使用 \.
例:
<action name="*_add"class="cn.itcast.action.Girl"method="add"></action>
匹配路径 Boy_add.action Girl_add.action
<action name="Boy_*_*"class="cn.itcast.action.Boy" method="{1}">
<resultname="success">
<paramname="location">/WEB-INF/jsp/{2}.jsp</param>
</result>
</action>
Boy_add_delete会调用 Boy的add方法, 转发给 delete.jsp
5) 动态方法调用
通过 url 动态调用 Action 中的方法
<actionname="Boy" class="cn.itcast.action.Boy">
/strutsdemo/Boy!add.action会调用Boy类的add方法
默认情况下, Struts 的动态方法调用处于激活状态, 若想禁用该功能, 则可以在 struts.xml 文件中配置常量
3. Action 类
概念:
action: 应用程序可以完成的每一个操作(用户的一个动作) 例如: 显示一个登陆表单,保存商品信息
Action类:Struts2中的Action是pojo(Plain Old Java Objects一个普通的java类)的,可以定义属性和方法,但需要遵循一些规则:
l 属性的名字必须遵守与 JavaBeans 属性名相同的命名规则. 属性的类型可以是任意类型. 从字符串到非字符串(基本数据库类型)之间的数据转换可以自动发生
l 必须有一个不带参的构造器
l 至少有一个供 struts 在执行这个 action 时调用的方法,方法的返回值为String类型(即视图名称)
l 同一个 Action 类可以包含多个 action.
l Struts2 会为每一个 HTTP 请求创建一个新的 Action 实例
4. result 元素
配置 action 的执行结果
name: 配置result结果名称,根据action执行方法的返回值决定找那个 result
默认为 success
type:result 结果类型,默认为 dispatcher 类型
常用的result类型
l dispatcher
dispatcher结果类型是最常用的结果类型, 也是 struts 框架默认的结果类型
用于将控制权转发给web应用中的其他资源
默认参数:location 用于指定转发的资源路径,通常为一个jsp页面
l redirect
用于将响应重定向到另一个资源
参数:
location: 指定重定向的资源路径
parse : 指定是否将location的值视为一个 OGNL 表达式来解析 默认值为true
l redirectAction
用于将响应重定向给另一个Action
参数:
actionName: 指定目标action, 该属性为默认属性
namespace: 指定目标 action 所在的 package
l chain
用于构成一个 Action 链,前一个action将控制权转发给下一个action,并且前一个action的状态在后一个action中继续保持
参数:
actionName: 指定目标action, 该属性为默认属性
namespace: 指定目标 action 所在的 package
method :指定调用action的方法 , 默认调用 execute 方法
l httpheader
用于将把一个 HTTP 状态发送到浏览器
默认参数 status : 指定状态码
l plaintext
将转发的资源作为文本输出 , 不常用
。。。
自定义 result
1) 写一个类实现com.opensymphony.xwork2.Result 接口
2) 定义属性name
3) 实现execute方法,输出 name + welcome
ServletActionContext.getResponse().getWriter().print(this.name+ ", welcome!!");
5. 访问 web 资源
在 Action 中, 可以通过以下两种方式访问 web 的
HttpSession,HttpServletRequest, ServletContext 资源
第一种:与Servlet API 解耦的访问方式
在Action中通过调用ActionContext类的方法来访问
注入方式:
让Action类实现ApplicationAware、RequestAware、SessionAware接口
第二种: 与Servlet API 耦合的方式
调用 ServletActionContext 的方法来实现
动手练习:
实现简单的用户登陆 在线人数存在 application
用户登陆时将user存入session让在线人数加1
用户注销时将user从session中移除让在线人数减1
三、OGNL
1.访问Action的属性
Struts在访问一个Action时,会自动将请求参数封装到Action的属性中(拦截器实现)
在 mvc 中,我们通常需要在 jsp 页面取出 javabean 封装的值,此时应取出 Action 的属性
${name }可以取出name 的值
相当于 <%=request.getAttribute(“name”) %>
注意: 此时的 request 为Struts2写的包装类StrutsRequestWrapper
2. 理解值栈
值栈是struts中特定的一个存储对象的地方
使用 Struts2 可以将对象都存在哪?
requestScope sessionScope applicationScope ValueStack
值栈ValueStack 内部有两个逻辑部分:
ObjectStack:用list集合模拟的栈,Struts 把Action和相关对象压入 ObjectStack 中
ContextMap:Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中. 实际上就是对 ActionContext 的一个引用
Struts 会把下面这些映射压入 ContextMap 中
parameters:该 Map 中包含当前请求的请求参数
request:该 Map 中包含当前 request 域中的所有属性
session:该 Map 中包含当前 session 对域中的所有属性
application:该 Map中包含当前 application 域中的所有属性
attr: 该 Map按如下顺序来检索域对象中的属性: request, session, application
3. OGNL表达式
1) 定义
OGNL(Object-GraphNavigation Language: 对象-图导航语言)
在 JSP 页面上可以可以利用OGNL访问到值栈(ValueStack) 里的对象属性.
ognl表达式需要在 Struts 标签中使用,方法有两种:
方式1 : 直接写变量, struts 会拿着变量去 ObjectStack(对象栈) 中查找对象的属性
方式2 : 变量前面加#,struts 会拿着变量去ContextMap 中查找对象
标签可分为两种,一种是struts特有的标签比如property,value属性会对ognl 求值
一种是页面元素标签,就是html标签,比如 textfield ,value属性不会对 ognl 求值
在第一种情况为了显示原始的值(不解析 ognl) 加单引号
<s:propertyvalue="'zhangsan'"/>
第二种情况若想取出值栈的值做回显,就需要加上 %{} 强制进行ognl解析
<s:textfieldname="username" label="用户名"value="%{username}" ></s:textfield>
通用办法解决显示原始字符的问题
%{'zhangsan'}
2) Property 标签
Struts 的property 标签用来输出值栈中的一个属性值.
3) 访问 ObjectStack
若想访问 Object Stack 里的某个对象的属性,方式有三种
object.propertyName
object["propertyName"]
object['propertyName']
可以通过下标的方式来引用栈中的对象,栈顶位置为0
例 : [1].name 就是访问第二个对象的name属性
若在指定的对象中没有找到对应的属性,则继续去下一个对象中找
[n].name的意思就是从第n个对象开始向下搜索name属性,找到为止
也可以不指定下标,即从0位置开始查找, name 就是从栈顶对象开始向下搜索name属性,找到为止
4) 访问 ContextMap 中的对象
若想访问 ContextMap 里的某个对象的属性, 方式有三种
#object.propertyName
#object["propertyName"]
#object['propertyName']
例:
#session.code: 查找 session 域中的 code 属性
#request.customer.name: 查找 request 域中的 customer 属性的name 属性值:
#attr.lastAccessDate: 依次去 request、session、application中查找lastAccessDate值
5) 调用字段和方法
l OGNL表达式可以访问对象的字段和方法
访问任何一个java类的静态字段和方法
@fullyQualifiedClassName@fieldName
例如:@java.util.Calendar@DECEMBER
@fullyQualifiedClassName@methodName(argumentList)
例如:@java.lang.Math@random()
l 访问对象栈中对象的字段和方法
.object.fieldName
例如: [0].datePattern
.object.methodName(argumentList)
例如: [0].repeat(3, “Hello”);
6) 访问数组
直接输出数组
使用下标访问数组的元素 preferences[0]
通过length字段查看数组元素的个数:preferences.length
7) 访问 List 集合
直接输出 List
使用下标访问 List 中指定的元素: list[0]
通过 size 方法查出list长度 :list.size()
通过方法 isEmpty() 或关键字 isEmpty 判断list是否为空 : list.isEmpty或 map.isEmpty()
可以使用OGNL表达式 动态创建一个list集合,格式与声明一个数组类似
{"aa","bb","cc"}
8) 访问Map集合
直接输出map
通过指定的 key 访问 value : map[key]
通过 size 方法查出map长度 : map.size()
通过方法 isEmpty() 或关键字 isEmpty 判断map是否为空 : map.isEmpty 或 map.isEmpty()
可以使用OGNL表达式 动态创建一个map集合, 前面要加#号, 格式如下
#{key-1:value-1, key-2:value-2, …… key-n:value-n}
四、标签
通用标签
1. property标签
property标签用来输出一个值栈属性的值
访问 ObjectStack 的对象的name属性:<s:propertyvlaue="name"/>
访问 ContextMap 中 session域的属性 <s:property value="#session.userName"/>
2. url 标签
动态生成一个url 类似 c:url
3. param 标签
用于传参
Struts会默认对value进行ognl 求值
如果想传递一个 String 类型的字符串作为参数值, 必须把它用单引号括起来
可以把 value 属性的值写在开始标签和结束标签之间. 利用这种方式来传递一个 EL 表达式的值
4. set 标签
set 标签可用于将一个键值对添加至以下的map集合
ValueStack值栈的 ContextMap 值栈
Map 类型的session 对象
Map 类型的application 对象
Map 类型的request 对象
Map 类型的page 对象
5. push 标签
push 标签将把一个对象压入 ValueStack 而不是压入 ContextMap
注意:push 标签在标签起始时把一个对象压入栈, 标签结束时将对象弹出栈
s:debug 需要写在标签之间才能看到效果
6. if, else 和elseif 标签
这三个标签用来进行条件测试, 它们的用途和用法类似于 if, else 和elseif 关键字. 其中 if 和elseif 必须有 test 属性
7. iterator 标签
iterator标签用来遍历一个数组, Collection 或一个 Map, 并把这个可遍历对象里的每一个元素依次压入和弹出 ValueStack 栈
在开始执行时, iterator 标签会先把 IteratorStatus 类的一个实例压入 ContextMap, 并在每次遍历循环时更新它. 可以将一个指向 IteratorStatus 对象的变量赋给 status 属性.
iterator标签的 status 属性的属性值
8. sort标签
sort 标签用来对一个可遍历对象里的元素进行排序.
9. date标签
date 标签用来对 Date 对象进行排版
format 属性的值必须是 java.text.SimpleDateFormat 类里定义的日期/时间格式之一
10. a标签
a 标签将呈现为一个 HTML 连接. 这个标签可以接受 HTML 语言中的a 元素所能接受的所有属性
11. action 标签
action 标签用在页面上来执行一个 action
action 标签还会把当前 Action 对象压入 ValueStack 值栈的 ContextMap 子栈
12. bean标签
bean 标签将创建一个 JavaBean, 并把它压入 ValueStack 值栈的 ContextMap 子栈. 这个标签的功能与 JSP 中的 useBean 动作元素很相似
13. include 标签
include 标签用来把一个 Servlet 或 JSP 页面的输出包含到当前页面里来
14. append, merge 标签
append 标签用来合并可遍历对象.
merge 标签用来交替合并可遍历对象.
示例:
15. generator 标签
generator 标签用来生成一个可遍历对象并把它压入 ValueStack 栈
generator 标签结束标记将弹出遍历对象
如果在一个 generator 标签里给出了 converter 属性, 新生成的可遍历对象里的每一个元素都会传递到该属性所指定的方法进行必要的转换
示例:
16. subset 标签
subset 标签用来创建一个可遍历集合的子集
subset 标签通过decider 属性来创建一个可遍历集合的子集
示例:
表单标签
Struts2 提供一套标签标签用于在html 页面中呈现一个form表单
Struts 表单表单和传统标签相比,优势在于:
自定对表单进行页面排版(产生table元素)
自动表单回显(从栈顶对象中取值)
表单标签的共同属性
label和required属性只在没有使用 simple 主题时才可以使用
1. form标签
form标签用于在页面中呈现一个表单
默认情况下, form 标签将被呈现为一个表格形式的 HTML 表单. 嵌套在 form 标签里的输入字段将被呈现为一个表格行. 每个表格行由两个字段组成, 一个对应着行标, 一个对应着输入元素. 提交按钮将被呈现为一个横跨两列单元格的行
2. textfield, password, hidden 标签
textfield标签将被呈现为一个输入文本字段, password 标签将被呈现为一个口令字段, hidden 标签将被呈现为一个不可见字段
password标签扩展自 textfield 标签, 多了一个 showPassword 属性. 该属性时布尔型. 默认值为 false, 它决定着在表单回显时是否显示输入的密码
3. submit 标签
submit 标签将呈现为一个提交按钮. 根据其 type 属性的值. 这个标签可以提供 3 种呈现效果
input: <input type=“submim” …/>
button: <input type=“submit” …/>
image: <input type=“image” />
4. reset 标签
reset 标签将呈现为一个重置按钮. 根据其 type 属性的值. 这个标签可以提供 2 种呈现效果
input:<input type=“reset” …/>
button: <input type=“reset” …/>
5. label 标签
label 标签将呈现一个 HTML 行标元素
6. textarea 标签
textarea标签将呈现为一个 HTML 文本域元素
7. checkbox 标签
checkbox 标签将呈现为一个HTML 复选框元素
与其他 HTML 输入元素类似, 当包含着一个单选框的表单被提交时, 这个单选框按钮在 HTTP 请求里增加一个请求参数. 如果某个单选框被选中了, 它的值将为true, 但如果该单选框未被选中, 在请求中就不会增加一个请求参数. checkbox 标签解决了这个局限性, 它采取的办法是为单选框元素创建一个配对的不可见字段
checkbox标签有一个 fieldValue 属性, 该属性指定的值将在用户提交表单时作为被选中的单选框的实际值发送到服务器. 如果没有使用 fieldValue 属性, 单选框的值将为 true 或 false
示例:
list系列标签
1. 标签属性
radio、select、checklist这三个标签均为列表标签
重要属性 list、listKey、listValue
list 属性的值可以为String字符串、数组、Collection、Map、Enumeration、Iterator
为属性赋值
l 字符串形式创建集合
l 使用一个Map
l Collection: 把数组或 Collection 赋值给 list 属性, 把用来提供选项值的对象属性赋给 listKey 属性, 把用来提供选项行标的对象属性赋给 listValue 属性
2. radio标签
radio标签呈现一个单选按钮,单选按钮个数与list属性的元素个数一致
radio标签比较适合多选一的请求,对于真假判断我们可以使用 checkbox 实现
示例:
3. select标签
示例:
4. optiongroup 标签
optiongroup标签对 select 元素所提供的选项进行分组. 每个选项有它自己的来源
示例:
5. checkboxlist
checkbox 标签被映射到一个字符串数组或是一个基本类型的数组. 若它提供的多选框一个也没有被选中, 相应的属性将被赋值为一个空数组而不是空值
示例:
表单标签主题:
默认情况下, form 标签将呈现为一个 HTML form 元素和一个 table 元素
每一种输入标签都将呈现为一个带标号的输入元素, 而这个输入元素将被包含在一个 tr 元素和td 元素的内部
主题: 为了让所有的 UI 标签能够产生同样的视觉效果而归集到一起的一组模板.
风格相近的模板被打包为一个主题
- simple: 把 UI 标签翻译成最简单的 HTML 对应元素, 而且会忽视行标属性
- xhtml: xhtml 是默认的主题. 这个主题的模板通过使用一个布局表格提供了一种自动化的排版机制.
- css_xhtml: 这个主题里的模板与 xhtml 主题里的模板很相似, 但它们将使用 css 来进行布局和排版
- ajax: 这个主题里的模板以 xhtml 主题里德模板为基础, 但增加了一些 Ajax 功能.
修改主题:
- 通过 UI 标签的 theme 属性
- 在一个表单里, 若没有给出某个 UI 标签的theme 属性, 它将使用这个表单的主题
- 在 page, request, session 或 application 中添加一个 theme 属性
- 修改 struts.properties 文件中的 struts.ui.theme 属性.
动手练习:
实现添加员工注册,实现表单验证,验证成功跳转至 successAction(请求请定向)
五、类型转换
html表单提交的数据都是String类型,而Action中的属性可能为任意类型的数据,数据在进行封装时必定会产生类型转换问题(字符串到非字符串类型)
1. struts2 如何实现参数的封装
在 struts2 中, 把请求参数映射到 action 属性的工作由默认拦截器栈defaultStack 中的一个params拦截器来完成(com.opensymphony.xwork2.interceptor.ParametersInterceptor)
params拦截器可以自动完成字符串和基本数据类型之间转换
2. 定制错误消息
在默认的拦截器栈中有一个拦截器为conversionError,该拦截器起到两个作用
负责添加与类型转换有关的出错消息(前提:Action类必须实现ValidationAware 接口)
保存个请求参数的原始值(用于实现表单的回显)
若字段标签使用的不是 simple 主题, 有非法制的输入字段将导致一条有着以下格式的出错消息:
若想覆盖默认的出错信息,需要两个步骤
1 在对应的动作类所在的包中新建ClassName.properties 文件
3. 自定义类型转换器
2 在属性文件中添加如下键值对: invalid.fieldvalue.字段名=错误消息
自定义类型转换器必须实现ongl.TypeConverter 接口或对这个接口的某种具体实现做扩展
我们可以通过继承StrutsTypeConverter类来实现接口
配置:
1 为 Action 类配置类型转换器
在 Action 类所在的包下创建配置文件ActionClassName-conversion.properties
为属性配置转换器 属性名=转换器完整类名
2 配置全局类型转换器
在类路径下新建配置文件xwork-conversion.properties
添加配置 属性类型(完整类名)=转换器(完整类名)
动手练习:
实现自定义的时间类型转换器: 时间模式需要以 web 应用的初始化参数配置在 web.xml 中
六、输入验证
1. 概念
一个健壮的 web 应用程序必须确保用户输入是合法的
Struts2 提供了一些基于XWork Validation Framework 的内建验证程序, 它们可以大大简化输入验证工作. 使用这些验证程序不需要编程, 只要在一个 XML 文件里对验证程序应该如何工作作出声明就可以了. 需要声明的内容包括: 哪些字段需要进行验证, 在验证失败时应该把什么样的出错消息发送到浏览器端
• 验证程序可以分为两类:
– 字段验证: 与表单里的某个字段相关联, 其验证行为发生在把一个值赋给一个 Action 属性之前
– 非字段验证: 不与某个特定的字段相关联, 它们用来测试某种特定的条件是否得到了满足.
大部分情况下,Struts2可以帮助我们实现数据的验证,但也不排除一些特定的情况,我们需要编程进行数据验证
2. Struts 验证规则
默认拦截器栈中的validation 拦截器负责加载和执行已注册的验证程序
使用一个验证程序需要3个步骤:
1 确定哪些Action 的输入需要验证
2. 编写一个验证程序配置文件. 它的文件名必须是以下两种格式之一:
• 若一个 Action 类的多个 action 使用同样的验证规则: ActionClass-validation.xml
• 若一个 Action 类的多个 action 使用不同的验证规则: ActionClass-alias-validation.xml
例如 UserAction-add-validation.xml
配置文件举例
其中,
• validators: 根元素
• field: 待验证的表单字段, name 属性指定将被验证的表单字段的名字
• field-validator: 验证规则. type 指定验证规则; short-circuit 取值可以为 true|false(默认值), true 的含义是如果当前字段验证失败, 作用于同一个字段的下一个验证规则将不执行;param 子元素可以向验证程序传递参数; message 子元素定义验证程序的出错消息
• validator: 普通验证
3. Struts2自带验证程序
• required: 确保某给定字段的值不是空值 null
• requiredstring: 确保某给定字段的值既不是空值 null, 也不是空白.
– trim 参数. 默认为 true, 表示struts 在验证该字段值之前先剔除前后空格.
• stringlength: 验证一个非空的字段值是不是有足够的长度.
– minLength: 相关字段的最小长度. 若没有给出这个参数, 该字段将没有最小长度限制
– maxLength:相关字段的最大长度. 若没有给出这个参数, 该字段将没有最大长度限制
– trim: 在验证之前是否去除前后空格
• int: 检查给定字段的值是否可以被转换为一个整数
– min: 相关字段的最小值. 若没给出这个参数, 该字段将没有最小值限制
– max: 相关字段的最大值. 若没给出这个参数, 该字段将没有最大值限制
• date: 确保某给定日期字段的值落在一个给定的范围内
– max:相关字段的最大值. 若没给出这个参数, 该字段将没有最大值限制
– min:相关字段的最小值. 若没给出这个参数, 该字段将没有最小值限制
• email: 检查给定 String 值是否是一个合法的 email
• url: 检查给定 String 值是否是一个合法的 url
• regex: 检查某给定字段的值是否与一个给定的正则表达式模式相匹配.
– expresssion*: 用来匹配的正则表达式
– caseSensitive: 是否区分字母的大小写. 默认为 true
– trim: 是否去除前后空格. 默认为 true
• expression 和 fieldexpression: 用来验证给定字段是否满足一个 OGNL 表达式.
– 前者不是一个字段验证程序, 后者是一个字段验证程序.
– 前者在验证失败时将生成一个 action 错误, 而后者在验证失败时会抛出一个字段错误
– expression*: 用来进行验证的 OGNL 表达式
• conversion: 检查对给定动作属性进行的类型转换是否会导致一个转换错误. 该验证程序还可以在默认的类型转换消息的基础上添加一条自定义的消息
4. 自定义验证
自定义验证程序必须实现 Validator 接口
可以通过以下方式实现接口:
– 若需要普通的验证程序, 可以继承 ValidatorSupport 类
– 若需要字段验证程序, 可以继承 FieldValidatorSupport 类
注册验证程序:
自定义验证器需要在类路径里的某个 validators.xml 文件里注册
验证框架首先在类路径下找validators.xml文件,没找到validators.xml文件, 验证框架将调用默认的验证设置,即default.xml里面的配置信息
Action 类可以通过实现Validateable 接口,从而提供验证功能
ActionSupport 类已经实现了 Validateable 接口
七、文件上传和下载
文件上传
• 在 Struts 应用程序里, FileUpload 拦截器和Jakarta Commons FileUpload 组件可以完成文件的上传
• 实现步骤:
1. 在 Jsp 页面的文件上传表单里使用 file 标签. 如果需要一次上传多个文件, 就必须使用多个 file 标签, 但它们的name属性必须是相同的
2. 在 Action 中新添加3 个和文件上传相关的属性. 这 3 个属性的名字必须是以下格式
[inputname]
[inputname]FileName
[inputname]ContentType
– inputName 是 jsp 页面上的 file 标签的name属性.
– 如果是上传单个文件, [inputName]File 属性的类型就是 java.io.File, 它代表被上传的文件, 第二个和第三个属性的类型是 String, 它们分别代表上传文件的文件名和文件类型
– 如果上上传多个文件, 可以使用数组或 List
• FileUpload 拦截器负责处理文件的上传操作, 它是默认的 defaultStack 拦截器栈的一员.
• FileUpload 拦截器有 3 个属性可以设置.
– maximumSize: 上传文件的最大长度(以字节为单位), 默认值为 2 MB
– allowedTypes: 允许上传文件的类型, 各类型之间以逗号分隔
– allowedExtensions: 允许上传文件扩展名, 各扩展名之间以逗号分隔
– 可以在 struts.xml 文件中覆盖这 3 个属性
• 若用户上传的文件大小大于给定的最大长度或其内容类型没有被列在 allowedTypes, allowedExtensions 参数里, 将会显示一条出错消息. 与文件上传有关的出错消息在 struts-messages.properties 文件里预定义. 可以在文件上传 Action 相对应的资源文件中重新定义错误消息, 但需要在 struts.xml 文件中配置使用 action 的消息:
<constantname="struts.custom.i18n.resources"value="MessageResource"></constant>
文件下载
struts2 提供了一个结果集类型 streams 用于做文件下载
streams结果集可以使用的参数
八、防表单重复提交
在实际开发中,我通常需要限制用户重复提交一个form请求
实现思路: 在服务器端内存通过 session 保存一个token, 在客户端表单放一个隐藏字段 token,字段提交的值和session中保存的值保持一致,用户提交表单时,检查token是否匹配,匹配则同意提交,提交完毕将session中的token移除, 只有当用户再次刷新表单页面时,才能再次提交表单
• Struts 提供的 token 标签可以用来生成一个独一无二的标记. 这个标签必须嵌套在 form 标签的内部使用, 它将在表单里插入一个隐藏字段并把标记保存在HttpSession 对象里.
• Token 标签必须与 Token 或 TokenSession 拦截器配合使用, 这两个拦截器都能对标记进行处理.
• Token 拦截器在遇到重复提交情况时, 会返回 invalid.token 结果并加上一个动作错误. 这种错误默认的消息是:
• 若想覆盖这条消息,需要在资源文件中修改默认消息
九、自定义拦截器
自定义拦截器需要实现com.opensymphony.xwork2.interceptor.Interceptor 接口
方法说明:
– init: 该方法将在拦截器被创建后立即被调用, 它在拦截器的生命周期内只被调用一次. 可以在该方法中对相关资源进行必要的初始化
– interecept: 每拦截一个动作请求, 该方法就会被调用一次.
– destroy: 该方法将在拦截器被销毁之前被调用, 它在拦截器的生命周期内也只被调用一次.
拦截器配置
struts2 知识点:
1.struts2 基于web层mvc的框架
2.Action的概念 每次请求创建一个 Action\ ActionContext、ValueStack
3.struts.xml 映射细节
4. 值栈+OGNL表达式
5. 标签
6. 类型转换
7. 表单验证
8. 文件上传和下载
9. 防止表单重复提交
10. 自定义拦截器
11.ModelDriven Preparable