Struts2利用验证框架实现数据验证(十一)

勿以恶小而为之,勿以善小而不为--------------------------刘备

劝诸君,多行善事积福报,莫作恶

上一章简单介绍了Struts2实现单文件上传,多文件上传与下载(十),如果没有看过,请观看上一章

数据验证,分为前端验证和后端验证。

前端验证主要是通过JavaScript和jQuery来实现,目的是: 减少客户等待的时间,减轻服务器端的压力,用户输入的错误数据,直接提示。

后端验证的目的是: 防止“绕过”客户端,提交非法数据。 在服务器端处理数据之前,确认数据的正确性。

这里只讲后端的验证。

在验证的时候,需要将提示信息展示给前端, Struts2框架提供了两种方式,进行提示信息。 addFieldError() 方法和 addActionError() 方法。

一. addFieldError() 方法和addActionError()方法

一.一 简单小提示

addFiledError(String name,String message) 添加字段范围内的具体的错误。

addActionError(String message) 在Action中添加具体的错误。

在Servlet开发阶段时,返回错误信息 通常用的是 request.setAttribute("message","具体的错误信息"),

现在可以用addFieldError()来进行处理。

对于类中的错误,用addActionError()进行处理。

两者所反映的级别是不一样的. field为字段级别的,action为Action级别的。

一.二 提示错误小例子

一.二.一 编写验证 UserAction

package com.yjl.web.action;
import com.opensymphony.xwork2.ActionSupport;
/**
* @author 两个蝴蝶飞
* @version 创建时间:Aug 30, 2018 8:21:09 PM
* User的验证类
*/
public class UserAction extends ActionSupport{
	private static final long serialVersionUID = 1L;
	/**
	 * 用addFiledError()方法处理
	 * 也是用key--value的形式进行展示的.
	 */
	public String field(){
		this.addFieldError("nameErr","姓名只能是中文");
		this.addFieldError("sexErr","性别只能选择男或者女");
		this.addFieldError("passwordErr","密码错误");
		return SUCCESS;
	}
	/**
	 *用 addActionError()方法处理。
	 */
	public String action(){
		//通常只写一个错误提示 
		this.addActionError("第一个类中大错误");
		return SUCCESS;
	}
}

一.二.二 配置struts.xml文件




		
		
				/WEB-INF/content/message.jsp
		
		
		
			/WEB-INF/content/{1}.jsp
		

一.二.三 编写 /content/message.jsp


显示Field错误

显示单个错误

nameErr

显示Action错误

一.二.四 重启服务器,运行

输入网址: http://localhost:8080/Struts_Validate/User_field, 显示field 域错误:

Struts2利用验证框架实现数据验证(十一)_第1张图片

输入网址: http://localhost:8080/Struts_Validate/User_action, 显示action 域错误

Struts2利用验证框架实现数据验证(十一)_第2张图片

显示字段错误时,如用户名 name是否填写错误,密码 password是否填写错误,手机号 phone是否填写错误,通常会显示全部的错误信息。

故一般常用:



来直接显示所有字段的错误。

一.二.五 hasFieldErrors() 和 hasActionErrors() 进行判断显示

访问 filed 错误时,没有action 错误,但却将Action的提示语都显示出来了,

访问action 错误时,没有filed 错误,但却将 Field的提示语都 显示出来了。

常常需要在 显示错误之前,进行一下判断, 如果有错误,才显示,如果没有错误的话,就不显示 。

用 hasFieldErrors() 用于验证是否有 field 级别的错误。

用 hasActionErrors() 用于验证是否有 action 级别的错误。

一.二.六 重写 /content/message.jsp 页面, 添加判断




	

显示Field错误

显示单个错误

nameErr

显示Action错误

再次进行测试:

输入网址: http://localhost:8080/Struts_Validate/User_field, 显示field 域错误:

Struts2利用验证框架实现数据验证(十一)_第3张图片

输入网址: http://localhost:8080/Struts_Validate/User_action, 显示action 域错误

Struts2利用验证框架实现数据验证(十一)_第4张图片

二 业务方法中验证

我们希望用户在前端表单填写数据,进行提交,如果错误了,就返回相应的错误信息,如果没有任何错误,就通过。

业务方法验证可以分为三个部分。

二.一 开发者自己手动验证

如用户登录时的验证:

//第一种情况: 在登录方法中直接进行验证
public String login(){
	//1. 接收到各个数据,如用户名,密码,邮箱等.
	String userName="两个蝴蝶飞";
	String password="yjl";
	String email="[email protected]";
	//2. 判断用户名是否错误,如果出现了错误,就this.addFieldError("userName","用户名错误");
	if(!"两个蝴蝶飞".equals(userName)){
		this.addFieldError("userName","用户名错误");
	}
	//3. 判断密码是否错误,如果出现了错误,就this.addFieldError("password","密码错误");
	if(!"yjl".equals(password)){
		this.addFieldError("password","密码错误");
	}
	//4. 判断邮箱是否错误,如果出现了错误,就this.addFieldError("email","邮箱错误");
	if(!"[email protected]".equals(email)){
		this.addFieldError("email","邮箱错误");
	}
	//5. 判断在这个action中是否出现了错误,如果有错误,将其添加到Action中,返回输入的界面
	if(this.hasErrors()){ 
	 //也有hasFieldErrors()和hasActionErrors(), hasErrors()包括field错误和action错误
		this.addActionError("登录的输入数据不对");
		return "loginUI";
	}
	//6.现在才是进行正常的逻辑操作,上面都是数据的检测(第一步获取数据除外)
	//判断是否登录成功,如果成功返回到成功界面, 如果不成功,返回到登录的界面,
	//... 登录业务
	return SUCCESS;
}

需要我们自己写验证代码,且不具有通过性,每一个方法,如注册方法register() 也需要进行验证。

二.二 重写 validate() 方法

二.二.一 Validateable 接口定义

ActionSupport 的类定义如下:

public class ActionSupport
implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable{
	
}

里面实现了一个验证接口 Validateable 该接口 Validateable 里面有一个validate()方法

public interface Validateable {

    /**
     * Performs validation.
     */
    void validate();

}

UserAction 继承了ActionSupport类,故继承了validate()方法,开发者 需要重写validate()方法即可。

数据验证,写在了 validate() 方法里面,正常的登录代码写在了 login() 方法里面,

数据验证与业务逻辑进行了分离。

那么此时,登录的逻辑判断就可以写成:

二.二.二 重写 validate() 方法进行验证

//第二种方式,重写validate()方法进行验证
public String login(){
	//1. 接收到各个数据,如用户名,密码,邮箱等.
	String userName="两个蝴蝶飞";
	String password="yjl";
	String email="[email protected]";
	
	//5. 判断在这个action中是否出现了错误,如果有错误,将其添加到Action中,返回输入的界面
	if(this.hasErrors()){ //也有hasFieldErrors()和hasActionErrors(), 这是两个方法的错误相加
		this.addActionError("登录的输入数据不对");
		return "loginUI";
	}
	//直接判断型业务逻辑,不用管数据验证。(当然前面有一个检测的操作)
	//判断是否登录成功,如果成功返回到成功界面, 如果不成功,返回到登录的界面,
	//用addFieldError或者addActionError添加错误信息
	return SUCCESS;
}
@Override
public void validate() {
	//只关注数据的验证
	//1. 接收到各个数据,如用户名,密码,邮箱等.
	String userName="两个蝴蝶飞";
	String password="yjl";
	String email="[email protected]";
	//2. 判断用户名是否错误,如果出现了错误,就this.addFieldError("userName","用户名错误");
	if(!"两个蝴蝶飞".equals(userName)){
		this.addFieldError("userName","用户名错误");
	}
	//3. 判断密码是否错误,如果出现了错误,就this.addFieldError("password","密码错误");
	if(!"yjl".equals(password)){
		this.addFieldError("password","密码错误");
	}
	//4. 判断邮箱是否错误,如果出现了错误,就this.addFieldError("email","邮箱错误");
	if(!"[email protected]".equals(email)){
		this.addFieldError("email","邮箱错误");
	}
}

二.二.三 流程处理

在进入login()方法之前,首先会调用validate()方法,进行数据验证。

相比较第一种方式,这个时候便处理上简单了一些。

但还是有一些特别严重的问题。 那就是在访问UserAction时,在进入每一个方法之前,都会先调用validate()方法。

如: UserAction 中 还存在 toLogin 和 register() 方法:

    public String toLogin(){
		//先调用validate()方法
		return "login";
	}
	public String register(){
		//先调用validate()方法
		return "register";
	}

然而,实际生活中, 登录时的验证与注册时的验证,验证数据的多少是不一样的,如注册时验证性别不为空,居住地不为空, 在登录时是不需要验证的,还有确认密码登录时是没有的。 更有的情况,登录和注册时对同一数据的验证规则是不一样的(根据具体业务情况分析), 如注册时需要验证用户名是否存在,登录时不需要验证用户名是否存在。 这个时候,需要在validate()方法中进行大量的判断,如果方法名login,走哪个验证,是register(),起哪个验证,是toLogin()的话,不走验证。

二.三 针对单个方法分别进行验证

需要注意,这个时候,验证数据的方法名称必须符合validateXxx()的形式。

如果是对login() 方法进行验证,那么验证login数据是否正确的方法名称必须是 validateLogin(),

如果是对register() 方法进行验证,那么验证reigster 数据是否正确的方法名称必须是 validateRegister().

对login()和register()方法分别进行验证:

public String login(){
	if(this.hasErrors()){
		this.addActionError("登录的输入数据不对");
		return "loginUI";
	}
	return "login";
}
public String register(){
	if(this.hasErrors()){
		this.addActionError("注册的输入数据不对");
		return "loginUI";
	}
	return "register";
}
public void validateLogin(){
	//对登录表单中的数据进行验证
}
public void validateRegister(){
	//对注册表单中的数据进行验证
}

有人会问,在注册时出现了错误,已经将数据放入到Action中了,即hasErrors()为true了,那么进入login()方法,取出的数据不就是true吗? 这是一个误区。 Strtus2是多实例的,在进入register()方法时,会重新实例化对象,所有的数据都会清空(静态属性和代码块除外),包括错误信息。 在进入login()时,也会重新实例化一下,会清空的。 需要设置 scope="prototype"。

这种方式相对于第二种来说,可读性大大增强,但每一个方法都要验证数据,都需要写一个validateXxx()方法,会导致验证方法过多。

注意,当Action既有 validate()方法,也有validateLogin()方法时,如果执行的是login操作时, 那么会先执行validateLogin()方法, 再执行validate()方法,有一个先后的顺序,但是两者均起作用的。

(图片摘自森林森前辈的Struts2(十二),本章图片均来自于此,谢谢。 源址为:https://www.cnblogs.com/liunanjava/p/4383237.html)

Struts2利用验证框架实现数据验证(十一)_第5张图片

常常用 Validate 框架进行验证。

三. validate框架验证数据

使用验证框架的好处, 1.验证实现的部分方便复用和扩展,2.验证的实现和业务处理分离。

验证里的配置需要在 xml文件中进行相应的配置。

这里验证一些常见的属性,用User类进行相应的包装。

三.一 未使用框架验证之前

三.一.一 编写 User.java

/**
* @author 两个蝴蝶飞
* @version 创建时间:Sep 8, 2018 2:46:59 PM
* 用于包装框架数据的实体类,没有实际意义
*/
public class User {
	/**
	 * @param id 编号id
	 * @param userName 用户名
	 * @param password 密码
	 * @param name 真实姓名
	 * @param sex 性别
	 * @param age 年龄
	 */
	private Integer id;
	private String userName;
	private String password;
	private String name;
	private String sex;
	private int age;
}

属性需要实现setter和getter方法,也添加一个 toString() 方法。

三.一.二 编写 RegisterAction 类

里面定义跳转到注册和注册的两个方法:

/**
* @author 两个蝴蝶飞
* @version 创建时间:Aug 30, 2018 8:21:09 PM
* User的相关验证
*/
public class RegisterAction extends ActionSupport{
	private static final long serialVersionUID = 1L;
	private static Logger logger=Logger.getLogger(UserAction.class);
	private User user;
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	public String toRegister(){
		logger.info("跳转到注册页面");
		return "registerUI";
	}
	public String register(){
		logger.info("执行注册的功能");
		logger.info("用户名是:"+user.getUserName()+",密码是:"+user.getPassword());
		return "register";
	}
}

三.一.三 配置 struts.xml


			/WEB-INF/content/register.jsp
			/WEB-INF/content/success.jsp
			
			/WEB-INF/content/register.jsp

三.一.四 编写 /content/register.jsp


	

这是一个注册框架的页面

/content/success.jsp 的内容显示 注册成功


	注册成功

三.一.五 重启服务器,进行验证

网址是: http://localhost:8080/Struts_Validate/Register_toRegister

Struts2利用验证框架实现数据验证(十一)_第6张图片

点击提交,页面正常跳转


在这里插入图片描述

日志打印输出:
在这里插入图片描述


这个时候,环境已经搭建成功了。

现在并没有进行相应的验证操作。

接下来就是具体的验证。

三.二 validate验证框架的具体详细使用

三.二.一 创建 Xxx.xml 验证文件

在action包下,创建 .xml 配置文件,该配置文件的文件名称 action名-validation.xml。

如UserAction的验证配置文件是UserAction-validation.xml,注意连接符是-,并不是下划线_

该例子用的是 RegisterAction, 那么创建的配置文件名称就是 RegisterAction-validation.xml

Struts2利用验证框架实现数据验证(十一)_第7张图片

三.二.二 配置约束

在UserAction-validation.xml中引入相关的约束




	


三.二.三 添加id 的约束


 
		
		 
			
			必须存在id 
		

三.二.四 重启服务器,验证

重启服务器,发现出错了。

再次输入网址: http://localhost:8080/Struts_Validate/Register_toRegister

Struts2利用验证框架实现数据验证(十一)_第8张图片

提示,必须输入id的值。

当我们在前端 get 方式传入id的值后, (注意,传入的是user.id的值)

Struts2利用验证框架实现数据验证(十一)_第9张图片

没有提示任何错误,可以正确的进行跳转到注册的页面了。

当我们输入一些值,但不输入编号时:

Struts2利用验证框架实现数据验证(十一)_第10张图片

点击提交按钮后,

Struts2利用验证框架实现数据验证(十一)_第11张图片

说明,验证框架起作用了,验证了 id不能为空。

三.二.五 验证 user.name的类型

配置user.userName 必须是字符串类型,且不能为空

在RegisterAction-validation.xml 中配置user.userName的验证


	 
		
			用户名不能为空,且必须是字母类型
		

重启服务器,进行测试,验证框架也同样起作用(这儿就不贴图了)

三.二.六 验证user.password

必须是字符串类型,且有长度限制。

在RegisterAction-validation.xml 中配置user.password 的验证

    
		
			密码不能为空
		
		
		
			
			true
			
			6
			15
			
			密码的长度应该在${minLength}~${maxLength}之间
		
	

可以在一个字段中,添加多个验证。 注意参数trim,maxLength,minLength的写法。

验证长度用type="stringlength" 这里是小写。

三.二.七 配置确认密码与user.password密码值一样

常用于字段表达式

前端jsp 设置:

 
 

在RegisterAction-validation.xml 中配置repassword 的验证


		
			true
			
			确认密码必须与原先密码相同
		

这个时候,才算是达到了要达到的效果。

三.二.八 配置真实姓名的中文验证

必须是2~4个中文,用regex类型,演示正则表达式


		
			
			
			必须是两个汉字~四个汉字
		
	

三.二.九 对age的int类型配置

需要指定其最大和最小值 用int


	 	
	 		
	 		18
	 		58
	 		注册年龄必须在${min}~${max}岁之间
	 	
	

三.二.十 对money的double类型配置

用double类型


	 	
	 		金钱必须是小数
	 	
	

输入整数或者浮点数是可以通过,但是输入字母是出错的。 另

外,输入1.2d,或者1.2f是正确的。

如果出错,显示的信息是:

在这里插入图片描述

三.三 验证文件所在的位置

在UserAction-validator.xml验证文件中,那些type="int",type="required",并不是随便写的,而是已经定义好的。它在

Struts2下载目录\Struts2\src\apps\portlet\src\main\resources目录下

Struts2利用验证框架实现数据验证(十一)_第12张图片

该文件,其中内容主要是:

validators.xml文件:




    
    
    
    
    
    
    
    
    
    
    
    

可以点击进入查看源代码,其中中就是那些属性。

Struts2利用验证框架实现数据验证(十一)_第13张图片

四. 为每一个方法写单独验证,

上面t每一个Action写了一个xml验证文件,这个是相对于整个Action来说的。

即这个Action中的每一个方法,都会进行这些统一的验证。

做一个简单的小例子。

在UserAction中添加一个转到登录的方法,在Action 写入方法,

public String toLogin(){
		logger.info("跳转到登录的页面");
		return "toLogin";
	}

其相应的 struts.xml 配置文件 :

/login.jsp

访问toLogin方法时: http://localhost:8090/Struts_validate/User_toLogin.action

会跳转到注册的页面,(跳转到注册页面是因为出错了,配置了result 中name="input")

日志也没有输出

在这里插入图片描述

在执行toLogin()方法之前,也对user.id,user.name 等属性 进行了相应的验证。

四.一 创建业务性验证

在与要验证的Action同级目录下,创建一个验证文件,命名方式必须是: ActionName-要验证方法名-validation.xml。

故新建一个UserAction-register-validation.xml文件,添加上面的一些验证,原先的UserAction-validation.xml文件保留,但去除验证配置。 在这里插入图片描述

重启服务器,进入http://localhost:8090/Struts_validate/User_toLogin.action,发现可以正常进入,会跳转到相应的login.jsp页面,而且日志也可以打印输出。

Struts2利用验证框架实现数据验证(十一)_第14张图片

这样就完成了单个业务验证的处理。

有时候,一个Action中有很多方法,特别是toXXX页面的方法,这个时候就不建议对整个Action进行验证了,而是对每一个方法即业务进行单独的验证。但可能会造成一个Action中的验证文件过多的情况。根据业务需求进行相应的取舍。

即如果是多个方法,可以:

Struts2利用验证框架实现数据验证(十一)_第15张图片

对add,login,register 三个方法进行单独的验证。

五. 验证框架的图像总结

验证顺序:

Struts2利用验证框架实现数据验证(十一)_第16张图片

验证知识点总结

Struts2利用验证框架实现数据验证(十一)_第17张图片

本章节代码链接为:

链接:https://pan.baidu.com/s/1_8Uo0YgGt9DLh1GRum0_uw 
提取码:yi71 

谢谢您的观看!!!

你可能感兴趣的:(Struts2利用验证框架实现数据验证(十一))