1.Struts2提供了验证框架,功能强大而且简单易用,帮助用户做了很多事情,使得用户不必从头开发。那么一个好的验证框架需要考虑哪些因素呢?
(1)验证功能的复用性
比如都是对一个int数据类型的验证,验证的是它的数据范围,如果验证功能抽象的好,就可以复用同样的验证功能,省去重复开发的麻烦。
(2)验证功能的可扩展性
是不是可以自己扩展验证功能,并保证扩展功能和原有的框架功能一样使用。
(3)验证与业务逻辑分离
在业务开发时,可能需要在业务逻辑不变的情况下修改验证逻辑,比如某个网站要求大于18周岁的公民才能注册,随着业务的开展,要修改为大于15岁的公民才能注册,很显然,这个时候,注册逻辑本身没有改变,但是验证逻辑发生了变化,那么,分离的验证逻辑可以保证在修改验证逻辑的时候,不会为业务逻辑带来麻烦。
2.使用Struts2的验证框架
2.1使用代码实现 验证功能
2.1.1重写validate()方法
也就是把校验条件写在validate()方法。这样可以减少execute()或是自定义的action方法的代码.struts2在调用execte()方法时,会先执行validate()方法.如果没通过validate则会抛出fieldError,并返回name="input"中定义的视图.否则继续执行execute()方法.下面来看一个实例。
登陆界面login.jsp 代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!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>Struts2验证框架</title>
</head>
<body>
<s:form action="login" method="post">
<s:textfield name="user.account" label="账号" />
<s:textfield name="user.name" label="姓名" />
<s:textfield name="user.age" label="年龄" />
<s:submit value="注册" />
</s:form>
</body>
</html>
LoginAction的代码如下
package com.action;
import com.bean.UserModel;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private UserModel user=new UserModel();
public UserModel getUser() {
return user;
}
public void setUser(UserModel user) {
this.user = user;
}
public String execute() throws Exception {
System.out.println(SUCCESS);
return SUCCESS;
}
public void validate() {
if (user.getName().equalsIgnoreCase("hello")) {
System.out.println(INPUT);
this.addFieldError("msg.hello", "必须输入hello!");
this.addActionError("处理动作失败!");
} else {
this.addActionMessage("提交成功");
}
}
}
最后来看一个下Struts2.xml配置文件:
<action name="login" class="com.action.LoginAction">
<result name="success">/welcome.jsp</result>
<result name="input">/login.jsp</result>
</action>
2.1.2重写validateXXX()方法
如果输入校验只想校验某个处理逻辑,也就是仅仅校验某个处理方法,则重写validate方法显然不够,validate()方法无法知道需要校验哪个处理逻辑。实际上,如果重写了Action的validate方法,则该方法会校验所有的处理逻辑。
为了实现校验指定处理逻辑的功能,struts2的Action提供了一个validateXXX方法。XXX即是Action对应的处理逻辑方法。来看一下在Action中是怎样操作的
对应的action类中的片段:
public String test(){//action操作的方法
//..此处省略
return "";
}
public void validateTest()
//这是我们自定义的validate方法 (validateTest) 这便是方法名
{ //一定要记住大写test的首字母
//..此处省略
}
@override
Public String execute()//这是重写ActionSupport的方法
{
//..此处省略
return "";
}
@override
public void validate()//这是重写ActionSupport的方法 如果我们需要有
//execute方法并且还要对它接收的数据信息进行验证
{
//那么我们可以将方法名改成 valiateExecute()便可以了
//..此处省略
}
分析发现:使用validate方法来验证客户端提交的数据,但如果使用validate方法就会将验证代码和正常的逻辑代码混在一起,但这样做不利于代码维护,而且也很难将过些代码用于其他程序的验证。在Struts2中为我们提供了一个Validation框架,这个框架和Struts1.x提供的Validation框架类似,也是通过XML文件进行配置。
2.2 struts2框架实现数据校验
来看一个简单的示例:
验证需求:用户注册时只需要填写自己的账号、姓名、年龄,其中,账号和姓名必须填写,年龄要求必填而且在18岁以上。
登陆界面register.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!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>Struts2验证框架</title>
</head>
<body>
<s:form action="login" method="post">
<s:textfield name="user.account" label="账号" />
<s:textfield name="user.name" label="姓名" />
<s:textfield name="user.age" label="年龄" />
<s:submit value="注册" />
</s:form>
</body>
</html>
界面如下:
RegisterAction类的代码如下:
package com.action;
import com.bean.UserModel;
import com.opensymphony.xwork2.ActionSupport;
public class RegisterAction extends ActionSupport {
private UserModel user=new UserModel();
public UserModel getUser() {
return user;
}
public void setUser(UserModel user) {
this.user = user;
}
public String execute() throws Exception{
System.out.println("传入的数据为:"+user.toString());
return SUCCESS;
}
}
其中UserModel类实现代码如下:
package com.bean;
public class UserModel {
private String account;
private String name;
private int age;
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
struts.xml的内容如下:
<action name="register" class="com.action.RegisterAction">
<result name="success">/welcome.jsp</result>
<!-- 校验错误直接返回"input"字符串,所以要定义"input"对应的视图资源 -->
<result name="input">/register.jsp</result>
</action>
验证框架的配置文件RegisterAction-validation.xml(格式[Action的类名-validation.xml])
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="user.account">
<field-validator type="requiredstring">
<message>请输入账号</message>
</field-validator>
</field>
<field name="user.name">
<field-validator type="requiredstring">
<message>请输入姓名</message>
</field-validator>
</field>
<field name="user.age">
<field-validator type="int">
<param name="min">18</param>
<message>年龄必须在18岁以上</message>
</field-validator>
</field>
</validators>
测试:
当在登录界面中年龄属性输入小于18的数时,会出现下面的视图:
验证执行时机:验证发生在execute方法运行之前,在Struts2的params拦截器已经把请求的参数反射的设置到Action的属性之后,所以,验证框架实际上验证的是值栈里面的内容。
验证的结果:如果用户输入的参数完全满足验证条件,则会继续执行execute方法,如果用户输入的参数不满足验证条件,注意:3个验证条件只要有一个验证通不过,就会跳转到这个Action所配置的名为input的Result,所以在struts.xml里最好配置一个名为input的result
3.验证框架的运行原理
下面来看一下验证器框架的运行顺序图:
参考: Struts2之验证框架