SpringMVC编程式验证器Validator

JAVA herman 843浏览 0评论
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

数据校验在web系统中非常常见,也非常常用。本文将借助SpringMVC的编程式验证器来学习一下Validator。

数据不合法

  1. 比如用户名长度必须在5-20之间,而且必须以字母开头,可包含字母、数字、下划线;
  2. 比如注册用户时 用户名已经存在或邮箱已经存在等;
  3. 比如去一些论坛经常会发现,您发的帖子中包含×××屏蔽关键字等。

还有很多数据不合法的场景,在此就不罗列了,对于数据不合法,Spring Web MVC提供了两种验证方式:

  • 编程式验证器验证
  • 声明式验证

编程式验证器

package org.springframework.validation;  
	public interface Validator {  
	boolean supports(Class<?> clazz);  
	void validate(Object target, Errors errors);  
}
  • Validator接口:验证器,编程实现数据验证的接口;
  • supports方法:当前验证器是否支持指定的clazz验证,如果支持返回true即可;
  • validate方法:验证的具体方法,target参数表示要验证的目标对象(如命令对象),errors表示验证出错后存放错误信息的错误对象。

验证器实现

package com.xttblog.chapter4.web.controller.support.validator;  
//省略import  
public class UserModelValidator implements Validator {  
    private static final Pattern USERNAME_PATTERN = Pattern.compile("[a-zA-Z]\\w{4,19}");  
    private static final Pattern PASSWORD_PATTERN = Pattern.compile("[a-zA-Z0-9]{5,20}");  
    private static final Set<String> FORBINDDDEN_WORD_SET = new HashSet<String>();  
    static {  
       FORBINDDDEN_WORD_SET.add("fuc k"); //删掉空格  
       FORBINDDDEN_WORD_SET.add("admin");  
    }    
    @Override  
    public boolean supports(Class<?> clazz) {  
       return UserModel.class == clazz;//表示只对UserModel类型的目标对象实施验证  
    }  
    @Override  
    public void validate(Object target, Errors errors) {  
       //这个表示如果目标对象的username属性为空,则表示错误(简化我们手工判断是否为空)  
       ValidationUtils.rejectIfEmpty(errors, "username", "username.not.empty");  
       UserModel user = (UserModel) target;  
       if(!USERNAME_PATTERN.matcher(user.getUsername()).matches()) {  
           errors.rejectValue("username", "username.not.illegal");//如果用户名不合法  
       }  
       for(String forbiddenWord : FORBINDDDEN_WORD_SET) {  
           if(user.getUsername().contains(forbiddenWord)) {  
              errors.rejectValue("username", "username.forbidden", 
			  new Object[]{forbiddenWord}, "您的用户名包含非法关键词");//用户名包含屏蔽关键字  
              break;  
           }  
       }  
       if(!PASSWORD_PATTERN.matcher(user.getPassword()).matches()) {  
           errors.rejectValue("password","password.not.illegal", "密码不合法");//密码不合法  
       }    
    }  
}
  • supports方法:表示只对UserModel类型的对象验证;
  • validate方法:数据验证的具体方法,有如下几个验证:

用户名不合法(长度5-20,以字母开头,随后可以是字母、数字、下划线)

USERNAME_PATTERN.matcher(user.getUsername()).matches() //使用正则表达式验证
errors.rejectValue("username", "username.not.illegal");//验证失败为username字段添加错误码

屏蔽关键词:即用户名中含有不合法的数据(如admin)

user.getUsername().contains(forbiddenWord) //用contains来判断我们的用户名中是否含有非法关键词
errors.rejectValue("username", "username.forbidden", new Object[]{forbiddenWord}, "您的用户名包含非法关键词");
//验证失败为username字段添加错误码(参数为当前屏蔽关键词)(默认消息为"您的用户名包含非法关键词")

密码不合法,例如密码不能低于6位数等。

ValidationUtils

ValidationUtils.rejectIfEmpty(errors, "username", "username.not.empty");
表示如果目标对象的username属性数据为空,则添加它的错误码;
内部通过(value == null || !StringUtils.hasLength(value.toString()))实现判断value是否为空,从而简化代码。

spring配置文件chapter4-servlet.xml

<bean id="userModelValidator"  
class="com.xttblog.chapter4.web.controller.support.validator.UserModelValidator"/>  
<bean name="/validator"  
class="com.xttblog.chapter4.web.controller.RegisterSimpleFormController">  
    <property name="formView" value="registerAndValidator"/>  
    <property name="successView" value="redirect:/success"/>  
    <property name="validator" ref="userModelValidator"/>  
</bean>  

错误码配置(messages.properties),需要执行NativeToAscii

username.not.empty=用户名不能为空  
username.not.illegal=用户名错误,必须以字母开头,只能出现字母、数字、下划线,并且长度在5-20之间  
username.forbidden=用户名中包含非法关键词【{0}】  
password.not.illegal=密码长度必须在5-20之间  

视图页面(/WEB-INF/jsp/registerAndValidator.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>  
<form:form commandName="user">  
<form:errors path="*" cssStyle="color:red"></form:errors><br/>  
username:<form:input path="username"/>  
<form:errors path="username" cssStyle="color:red"></form:errors>  
<br/>  
password:<form:password path="password"/>  
<form:errors path="password" cssStyle="color:red"></form:errors>  
<br/>  
<input type="submit" value="注册"/>  
</form:form>  

form:errors path="username":表示只显示username字段的错误信息;

输入地址:http://localhost:9080/springmvc-chapter4/validator进行测试。

当我们输入错误的数据后,会报错(form:errors path="*"显示所有错误信息,而form:errors path="username"只显示该字段相关的)。

如MultiActionController控制器相关方法没有提供给我们errors对象(Errors),我们应该怎么进行错误处理呢?
此处给大家一个思路,errors本质就是一个Errors接口实现,而且在页面要读取相关的错误对象,该错误对象应该存放在模型对象里边,因此我们可以自己创建个errors对象并将其添加到模型对象中即可。

BindException errors = new BindException(user, getCommandName(user));  
//如果用户名为空  
if(!StringUtils.hasLength(user.getUsername())) {  
    errors.rejectValue("username", "username.not.empty");  
}  
if(errors.hasErrors()) {  
    return new ModelAndView(getCreateView()).addAllObjects(errors.getModel());  
} 
  • new BindException(user, getCommandName(user)):使用当前的命令对象,和命令对象的名字创建了一个BindException作为errors;
  • StringUtils.hasLength(user.getUsername()):如果用户名为空就是用errors.rejectValue("username", "username.not.empty");注入错误码;
  • errors.hasErrors():表示如果有错误就返回到新增页面并显示错误消息;
  • ModelAndView(getCreateView()).addAllObjects(errors.getModel()):此处一定把errors对象的模型数据放在当前的ModelAndView中,作为当前请求的模型数据返回。

在浏览器地址栏输入:http://localhost:9080/springmvc-chapter4/userAndValidator/create 到新增页面

用户名什么都不输入,提交后又返回到新增页面 而且显示了错误消息说明我们的想法是正确的。本文示例源码下载链接:http://pan.baidu.com/s/1bpvohZp 密码:wgde

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » SpringMVC编程式验证器Validator