@liayun
2016-10-03T10:03:18.000000Z
字数 13516
阅读 1634
Struts2框架学习
这是Struts2框架进阶三。废话不多说,直接进入正文。
在Struts2中,我们可以实现对action的所有方法进行校验或者对action的指定方法进行校验。
对于输入校验,Struts2提供了两种实现方法:
通过重写validate()或validateXxx()方法实现,validate()方法会校验action中所有与execute方法签名相同的方法。validateXxx()只会校验action中方法名为Xxx的方法。其中Xxx的第一个字母要大写。当某个数据校验失败时,我们应该调用addFieldError()方法往系统的fieldErrors添加校验失败信息(为了使用addFieldError()方法,action可以继承ActionSupport ),如果系统的fieldErrors包含失败信息,Struts2会将请求转发到名为input的result,在input视图中可以通过<s:fielderror/>
显示失败信息。
首先我们编写struts.xml配置文件的内容为:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<package name="person" namespace="/person" extends="struts-default">
<action name="manage_*" class="cn.itcast.action.PersonAction" method="{1}">
<result name="input">/index.jsp</result>
<result name="message">/WEB-INF/page/message.jsp</result>
</action>
</package>
</struts>
接着我们在WebRoot根目录下创建出一个jsp页面——index.jsp,用于收集用户填写的信息。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>输入校验</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/person/manage_save.action" method="post">
用户名:<input type="text" name="username">不能为空<br/>
手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
我们还要在WEB-INF/page/目录下创建出一个全局消息显示页面——message.jsp。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>结果</title>
</head>
<body>
${message }
</body>
</html>
最后我们在cn.itcast.action包下创建一个Action——PersonAction.java。
public class PersonAction extends ActionSupport {
private String username;
private String mobile;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
}
以上准备工作做好之后,开始对PersonAction.java中的所有方法进行输入校验。我们只须在PersonAction类中添加如下方法即可:
@Override
public void validate() { // 会对action中的所有方法进行校验
if (this.username==null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空"); // 输出校验错误信息
}
if (this.mobile==null || "".equals(this.mobile.trim())) {
this.addFieldError("mobile", "手机号不能为空");
} else {
if (!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()) {
this.addFieldError("mobile", "手机号格式不正确");
}
}
}
如果验证失败后,请求将转发至input视图:
<result name="input">/index.jsp</result>
在index.jsp页面中还要使用Struts2标签<s:fielderror/>
显示校验失败信息。注意,还要在页面头部添加:
<%@ taglib="/struts-tags" prefix="s" %>
这样,index.jsp页面的内容就为:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>输入校验</title>
</head>
<body>
<s:fielderror />
<form action="${pageContext.request.contextPath }/person/manage_save.action" method="post">
用户名:<input type="text" name="username">不能为空<br/>
手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
这样,我们就实现了对action中的所有方法进行输入校验。大家亦可自行测试。
若是要对PersonAction.java中的update()方法进行输入校验,只须在PersonAction类中添加如下方法即可:
public void validateUpdate() { // 会对action中的update()方法进行校验
if (this.username==null || "".equals(this.username.trim())) {
this.addFieldError("username", "用户名不能为空"); // 输出校验错误信息
}
if (this.mobile==null || "".equals(this.mobile.trim())) {
this.addFieldError("mobile", "手机号不能为空");
} else {
if (!Pattern.compile("^1[358]\\d{9}$").matcher(this.mobile).matches()) {
this.addFieldError("mobile", "手机号格式不正确");
}
}
}
这样,我们就实现了对action中的指定方法进行输入校验。大家亦可自行测试。
第2步说明了进入input视图有两种情况:
如果validate()方法中没有一行代码,但是还会进入input视图,原因就应该是类型转换失败了。我们举例来说明这一点。
我们首先修改index.jsp的页面内容为:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>输入校验</title>
</head>
<body>
<s:fielderror />
<form action="${pageContext.request.contextPath }/person/manage_update.action" method="post">
用户名:<input type="text" name="username">不能为空<br/>
生日:<input type="text" name="birthday"><br/>
手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
接着修改PersonAction类的代码为:
public class PersonAction extends ActionSupport {
private String username;
private String mobile;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
public void validateUpdate() { // 会对action中的update()方法进行校验
}
}
测试如下:
记得要插入.GIF的图片
验证了这一点。
若要基于XML配置方式实现输入校验,则Action类需要继承ActionSupport,然后还得提供校验文件,如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
</validators>
初学者可能不知道以上的校验文件怎么写,但没关系,Struts2框架给开发人员提供了一些案例,我们可以拷贝其中的校验文件到我们的项目中,然后修修改改。如我们可以在诸如...\struts-2.3.24\apps\struts2-blank\WEB-INF\classes\example目录下找到这样的校验文件——Login-validation.xml,打开:
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<message key="requiredstring"/>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<message key="requiredstring"/>
</field-validator>
</field>
</validators>
发现该校验文件使用的是XWork Validator 1.0.2版本,该版本对有些输入校验不友好,所以就不要选用这个版本了,最好是选用1.0.3版本。总之,不要使用XWork Validator 1.0.2这个版本。
好了,我们还是回到一开始的校验文件。在这个校验文件中,对action中字符串类型的username属性进行验证,首先要求调用trim()方法去掉空格,然后判断用户名是否为空。该文件需要和action类放在同一个包下,文件的取名应遵守ActionClassName-validation.xml规则,其中ActionClassName为action的简单类名,-validation为固定写法。如果Action类为cn.itcast.action.UserAction,那么该文件的取名应为:UserAction-validation.xml。
我们把注意力集中在这段代码上面:
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
<field>
指定action中要校验的属性。<field-validator>
指定校验器。<message>
为校验失败后的提示信息,如果需要国际化,可以为message指定key属性,key的值为属性文件中的key。上面指定的校验器requiredstring是由系统提供的,系统提供了能满足大部分验证需求的校验器,这些校验器的定义可以在xwork-core-2.x.x.jar中的com.opensymphony.xwork2.validator.validators下的default.xml中找到。
下面我们就来详细说明系统提供的校验器。
系统提供的校验器如下:
required(必填校验器,要求field的值不能为null),如:
<field-validator type="required">
<message>性别不能为空!</message>
</field-validator>
requiredstring(必填字符串校验器,要求field的值不能为null,并且长度大于0,默认情况下会对字符串去前后空格),如:
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
stringlength(字符串长度校验器,要求field的值必须在指定的范围内,否则校验失败,minLength参数指定最小长度,maxLength参数指定最大长度,trim参数指定校验field之前是否去除字符串前后的空格),如:
<field-validator type="stringlength">
<param name="maxLength">10</param>
<param name="minLength">2</param>
<param name="trim">true</param>
<message><![CDATA[产品名称应在1-10个字符之间]]></message>
</field-validator>
regex(正则表达式校验器,检查被校验的field是否匹配一个正则表达式。expression参数指定正则表达式,caseSensitive参数指定进行正则表达式匹配时,是否区分大小写,默认值为true),如:
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
int(整数校验器,要求field的整数值必须在指定范围内,min指定最小值,max指定最大值),如:
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>年龄必须在1-150之间</message>
</field-validator>
fieldexpression(字段OGNL表达式校验器,要求field满足一个OGNL表达式,expression参数指定ognl表达式,该逻辑表达式基于ValueStack进行求值,返回true时校验通过,否则不通过),如:
<field name="imagefile">
<field-validator type="fieldexpression">
<param name="expression"><![CDATA[imagefile.length() > 0]]></param>
<message>文件不能为空</message>
</field-validator>
</field>
email(邮件地址校验器,要求如果field的值非空,则必须是合法的邮件地址),如:
<field-validator type="email">
<message>电子邮件地址无效</message>
</field-validator>
弄清楚上面的知识点之后,我们就基于XML配置方式实现对action的所有方法进行校验。
首先我们将PersonAction类的代码修改为:
public class PersonAction extends ActionSupport {
private String username;
private String mobile;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String update() {
ActionContext.getContext().put("message", "更新成功");
return "message";
}
public String save() {
ActionContext.getContext().put("message", "保存成功");
return "message";
}
}
接着我们还要修改index.jsp页面的内容为:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>输入校验</title>
</head>
<body>
<s:fielderror />
<form action="${pageContext.request.contextPath }/person/manage_save.action" method="post">
用户名:<input type="text" name="username">不能为空<br/>
手机号:<input type="text" name="mobile">不能为空,并且要符合手机好的格式:1,3/5/8,后面是9个数字<br/>
<input type="submit" value="提交">
</form>
</body>
</html>
最后我们就要在cn.itcast.action包下提供校验文件了,文件名必须为PersonAction-validation.xml。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
<field name="mobile">
<field-validator type="requiredstring">
<message>手机号不能为空!</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
</field>
</validators>
测试,发现正则表达式校验器不起作用,原因不知为何?
当校验文件的取名为ActionClassName-validation.xml时,会对action中的所有处理方法实施输入验证。如果你只需要对action中的某个处理方法实施验证,那么,校验文件的取名应为:ActionClassName-ActionName-validation.xml,其中ActionName为struts.xml中为action配置的名称。例如:在实际应用中,常有以下配置:
<action name="user_*" class="cn.itcast.action.UserAction" method="{1}">
<result name="success">/WEB-INF/page/message.jsp</result>
<result name="input">/WEB-INF/page/addUser.jsp</result>
</action>
UserAction中有以下两个处理方法:
public String add() throws Exception{
....
}
public String update() throws Exception{
....
}
如果我们要访问UserAction类中的add()方法,那极有可能在浏览器中输入这样的URL地址:.../person/user_add.action,这时我们有必要知道Struts2框架是如何解析这样的URL地址的。
Struts2框架在寻找action的时候,先解析出:namespace=/person,然后再解析出:ActionName=user_add,也即是说,ActionName是路径中的,而不是<action>
标签中的name。所以,
现在我们基于XML配置方式只实现对PersonAction的update()方法进行输入校验。我们只须在cn.itcast.action包下提供校验文件即可,校验文件必须得为PersonAction-manage_update-validation.xml。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="username">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>用户名不能为空!</message>
</field-validator>
</field>
<field name="mobile">
<field-validator type="requiredstring">
<message>手机号不能为空!</message>
</field-validator>
<field-validator type="regex">
<param name="expression"><![CDATA[^1[358]\d{9}$]]></param>
<message>手机号格式不正确!</message>
</field-validator>
</field>
</validators>
测试,发现正则表达式校验器不起作用,原因不知为何?
当为某个action提供了ActionClassName-validation.xml和ActionClassName-ActionName-validation.xml两种规则的校验文件时,系统按下面顺序寻找校验文件:
系统寻找到第一个校验文件时还会继续搜索后面的校验文件,当搜索到所有校验文件时,会把校验文件里的所有校验规则汇总,然后全部应用于处理方法的校验。如果两个校验文件中指定的校验规则冲突,则只使用后面文件中的校验规则。
当action继承了另一个action,父类action的校验文件会先被搜索到。假设UserAction继承BaseAction, UserAction在struts.xml中的配置如下:
<action name="user" class="cn.itcast.action.UserAction" method="{1}">
.....
</action>
访问上面名为user的action,系统先搜索到BaseAction-validation.xml, BaseAction-user-validation.xml,接着搜索到UserAction-validation.xml, UserAction-user-validation.xml。校验规则是这四个文件的总和。