1、数据验证的概述
1.1、数据验证的重要性
数据验证是非常必要的,不但和我们的常识性理解有关系,还有可能涉及到一些非法输入等问题,所以我们需要进行必要的数据验证,以保证我们在数据输入的时候都是正确且合法的。
1.2、数据验证的分类
数据验证的一般分类有两种:
一种就是在客户端验证,数据在提交到服务器端之前进行验证,这样做的特点就是减少客户等待、减轻服务器端压力,我们可以用javaScript或者是JQuery来实现;
一种是服务器端验证,就是在数据提交到服务器端之后在进行数据验证。防止有效防止“绕过”客户端验证提交的非法数据,可以在服务器端处理数据前确保数据的合法性;
1.3、Strsuts2实现数据验证的两种方式
- 继承ActionSupport类实现验证
- 使用Struts2验证框架实现验证
2、基于继承ActionSupport类实现数据验证
2.1、 在Action类的业务方法中直接验证
这是一种直观的验证方法,直接在实现了ActionSupport的XxxAxtion类里边利用代码直接进行数据的验证。如下的代码就是一小段在XxxAxtion类中直接实现数据验证的。
String ageStr="^\\d{1,3}$";
Pattern ageReg=Pattern.compile(ageStr);
Matcher ageMatcher=ageReg.matcher(user.getAge()+"");
if(!ageMatcher.matches()){
this.addFieldError("user.age", "年龄只能是数字,并只能为1-200之间!");
}
if(null==user.getAge()){
this.addFieldError("user.age", "年龄不能为空!");
}
2.2、重写Validate()方法进行验证
我们知道,ActionSupprot类里边有一个方法是Validate()方法,我们可以通过重写Validate()方法的方式实现数据验证功能。和直接在Action类的业务方法中直接验证的方法不通点就是我们把实现验证的那部分代码写进Validate()方法中就可以了。这样做的优点就是将数据验证和业务处理进行分离,但是添加和显示错误信息的方法还是不变的。注意:如果Action中有validate()方法,会先执行验证,验证后才执行业务方法,不通过不执行业务方法
@Override
public void validate() {
if(null==user.getUsername() || "".equals(user.getUsername())){
this.addFieldError("user.username", "用户名不能为空!");
}
if(null==user.getPassword() || "".equals(user.getPassword())){
this.addFieldError("user.password", "密码不能为空!");
}
String ageStr="^\\d{1,3}$";
Pattern ageReg=Pattern.compile(ageStr);
Matcher ageMatcher=ageReg.matcher(user.getAge()+"");
if(!ageMatcher.matches()){
this.addFieldError("user.age", "年龄只能是数字,并只能为1-200之间!");
}
if(null==user.getAge() || "".equals(user.getAge())){
this.addFieldError("user.age", "年龄不能为空!");
}else{
if(0>user.getAge() || 200<user.getAge()){
this.addFieldError("user.age", "年龄1-200之间!!");
}
} String emaString="^\\w+@\\w+(.\\w{2,3}){1,2}$";
Pattern emailReg=Pattern.compile(emaString);
Matcher emailMatcher=emailReg.matcher(user.getEmail());
if(!emailMatcher.matches()){
this.addFieldError("user.email", "邮箱格式不正确");
}
super.validate(); }
2.3、使用validateXxx()方法
struts2支持使用ValidateXxx()方法进行数据验证,使用validateXxx()方法实现针对Xxx()方法的数据验证;validate()方法和validateXxx()方法同时存在时都会起作用;ValidateXxx()
方法的调用要先于validate()方法。
这种数据验证的方法比直接使用重写Validate()方法要好一些,因为我们知道,每一次请求都会创建一个对应的action对象,但例如注册的时候可能我们需验证邮箱的格式,但这
只是在注册的时候才使用,平时的时候我们是不使用的啊。所以使用validateXxx()方法能有效的分离注册是数据验证和访问请求时的数据验证。比较好!
public String register() throws Exception {
System.out.println("=========完成注册信息======");
if(this.hasErrors()){
return INPUT;
}
return SUCCESS;
} @Override
public void validate() {
System.out.println("====执行validate方法验证====");
if(null==user.getUsername() || "".equals(user.getUsername())){
this.addFieldError("user.username", "用户名不能为空!");
}
if(null==user.getPassword() || "".equals(user.getPassword())){
this.addFieldError("user.password", "密码不能为空!");
} } public void validateRegister(){
System.out.println("====执行validateRegister方法验证====");
String ageStr="^\\d{1,3}$";
Pattern ageReg=Pattern.compile(ageStr);
Matcher ageMatcher=ageReg.matcher(user.getAge()+"");
if(!ageMatcher.matches()){
this.addFieldError("user.age", "年龄只能是数字,并只能为1-200之间!");
}
if(null==user.getAge() || "".equals(user.getAge())){
this.addFieldError("user.age", "年龄不能为空!");
}else{
if(0>user.getAge() || 200<user.getAge()){
this.addFieldError("user.age", "年龄1-200之间!!");
}
} String emaString="^\\w+@\\w+(.\\w{2,3}){1,2}$";
Pattern emailReg=Pattern.compile(emaString);
Matcher emailMatcher=emailReg.matcher(user.getEmail());
if(!emailMatcher.matches()){
this.addFieldError("user.email", "邮箱格式不正确");
}
}
3、基于继承ActionSupport类实现数据验证时添加错误信息的方法
addFieldError(String fieldName,String errorMessage),添加字段的错误信息
addActionError(String anErrorMessage),添加与Action所处理业务相关的错误信息
4、基于继承ActionSupport类实现数据验证时在页面输出验证结果
<s:fielderror/>输出一个或者所胡字段的错误信息
<s:actionerror/>输出所有Action的错误信息
5、基于继承ActionSupport类实现数据验证时的struts.xml文件的配置方法
<result name="input">xxx.jsp</result>
总结:
在Action类中添加错误信息,以便于在展示界面输出错误信息;总的来说就是这三种方法实现数据验证的位置不一样罢了。
6、基于Struts2验证框架实现数据验证
6.1、框架验证的一般过程:
- 编写jsp界面以便于输入数据
- 编写Action类和想匹配的配置文件
- 在Action类同一个目录下编写验证文件ActionName-validation.xml(这个验证文件的命名规则是固定的)
- 在新创建的验证文件中按照规范写验证规则
代码实现:
编写Action类:
package com.java1234.action; import com.java1234.model.User;
import com.opensymphony.xwork2.ActionSupport; public class RegisterAction extends ActionSupport{ /**
*
*/
private static final long serialVersionUID = 1L; private User user; public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
} @Override
public String execute() throws Exception {
System.out.println("传入的用户:"+user);
return SUCCESS;
} }
同一个目录下编写验证文件:
<?xml version="1.0" encoding="UTF-8"?>
<!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="user.userName">
<field-validator type="requiredstring">
<message>请输入用户名</message>
</field-validator>
<field-validator type="stringlength">
<param name="minLength">6</param>
<param name="maxLength">10</param>
<message>用户名必须在${minLength}和${maxLength}之间</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>
<field name="user.email">
<field-validator type="requiredstring">
<message>请输入邮件</message>
</field-validator>
<field-validator type="email">
<message>邮件格式不对</message>
</field-validator>
</field>
<field name="user.homePage">
<field-validator type="requiredstring">
<message>请输入主页</message>
</field-validator>
<field-validator type="url">
<message>主页格式不对</message>
</field-validator>
</field> <validator type="expression">
<param name="expression"><![CDATA[!user.name.equals(user.userName)]]></param>
<message>用户名和真实姓名不能相同</message>
</validator>
</validators>
struts.xml配置文件:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="manager" extends="struts-default"> <action name="registerAction" class="com.java1234.action.RegisterAction">
<result name="input">/register.jsp</result>
<result name="success">/success.jsp</result>
</action> </package> </struts>
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>Insert title here</title>
</head>
<body>
<s:actionerror/>
用户注册
<s:form action="/registerAction" method="post">
<s:textfield name="user.userName" label="用户名"></s:textfield>
<s:textfield name="user.name" label="真实姓名"></s:textfield>
<s:textfield name="user.age" label="年龄"></s:textfield>
<s:textfield name="user.email" label="邮件"></s:textfield>
<s:textfield name="user.homePage" label="主页"></s:textfield>
<s:submit value="注册"></s:submit>
</s:form>
</body>
</html>
访问地址:http://localost:8080/HeadFirstChap01/register.jsp
6.2、如何针对某一个业务配置验证规则
根据实际情况我们可能有这样的需求:指对某一个方法进行数据验证。我们的处理办法一般有两种,一种就是把这个方法单独写进一个Action类中,然后对这个Action类进行单独编写验证文件然后在struts.xml文件中只需要使用method属性指明一下就可以了;还有一种方法就是不单独分出来一个Action,而是在编写验证文件的时候创建一个:ActionName-alias-validation.xml的文件(中间的名称要与action的name属性名字相同)。
6.3、使用验证框架时的执行流程
ActionName-Validation.xml文件可以对整个Action类的业务方法使用;ActionName-alias-validation.xml文件指对Action类中的某一个业务方法起作用;如果两个文件都存在的情况下,两个文件都会起作用。
验证的顺序一般是:ActionName-Validation.xml(父类)、ActionName-alias-validation.xml(父类)、ActionName-Validation.xml、ActionName-alias-validation.xml。