前言

数据的校验是交互式网站一个不可或缺的功能,前端的js校验可以涵盖大部分的校验职责,如用户名唯一性,生日格式,邮箱格式校验等等常用的校验。但是为了避免用户绕过浏览器,使用http工具直接向后端请求一些违法数据,服务端的数据校验也是必要的,可以防止脏数据落到数据库中,如果数据库中出现一个非法的邮箱格式,也会让运维人员头疼不已。在一般的应用,可以使用validation来对数据进行校验。

校验思路:

  1. 页面提交请求的参数,请求到controller方法中,使用validation进行校验。
  2. 如果校验出错,将错误信息展示到页面。

配置数据校验步骤

  1. 导入校验jar文件
    hibernate的校验框架validation所需要jar包
  2. 配置校验器
    在SpringMVC配置文件中配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- 采用注解开发 mvc:annotation-driven这个配置替代了两个的bean的配置:处理映射器, 处理适配器 -->
	<!-- 校验器注入到处理器适配器中validator="validator" -->
	<mvc:annotation-driven conversion-service="conversionService" validator="validator"></mvc:annotation-driven>

	<!-- 开启全包扫描,把我们自己写的controller注册进容器 -->
	<context:component-scan base-package="net.neuedu.springmvc"></context:component-scan>
	
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
	<!-- 配置数据校验bean -->
	<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
		<!-- hibernate校验器 -->
		<property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property>
		<!-- 指定校验使用的资源文件,在文件中配置校验错误信息 -->
		<property name="validationMessageSource" ref="messageSource"></property>
	</bean>
	<!-- 校验错误信息配置文件 -->
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<!-- 资源文件名 -->
		<property name="basenames">
			<list><value>classpath:resourceMessage</value></list>
		</property>
		<!-- 资源文件编码格式 -->
		<property name="fileEncodings" value="utf-8"></property>
		<!--对资源文件缓存时间,单位秒 -->
		<property name="cacheSeconds" value="120"></property>
	</bean>
</beans>
  1. pojo中添加校验规则
public class Product {
	//不能为空,在小6个字符,最大20个字符
	@NotEmpty(message = "{productNameNotNullMessage}")
    @Size(max = 20,min = 6,message = "{productNameErrorMessage}")	
	private String productName;  //名字
	
	//double型的数据,最大10000.00,最小0.01
	@DecimalMax(value = "10000.00",message = "{productPriceMaxErro}")
	@DecimalMin(value = "0.01",message = "{productPriceMinErro}")
	private Double productPrice;//价格
	
	//非空
	@NotNull(message="{productDateIsNullError}")
	private Date productDate;//日期
	
	//非空
	@NotBlank(message="{productDescIsNullError}")
	private String desc;//描述
	
	//非空,邮箱校验使用到正则表达式
	@NotEmpty(message = "{emailNameNotNullMessage}")
	@Pattern(regexp = "^\\w+@\\w+/.\\w+$",message = "{emailNameErrorMessage}")
	private String email;
//get和set方法这里省略不写
}
  1. 错误信息文件
  • 在 .properties配置校验错误信息
  • 把配置文件放到类路径中
  1. 捕获错误信息
  • 在controller方法中捕获
  • 添加@Validated表示在对items参数绑定时进行校验,校验信息写入BindingResult中,在要校验的pojo后边添加BingdingResult, 一个BindingResult对应一个pojo,且BingdingResult放在pojo的后边。
@RequestMapping("addProduct.do")
	public ModelAndView addProduct(@Validated(value = {AddGroup.class}) Product product,BindingResult bindingResult)
	{
		//需求:如果product的各个字段有哪个字段为空值,那么程序会报错,去往错误信息显示页面,提示用户输入数据
		List<ObjectError> errors = null;
		if(bindingResult.hasErrors())
		{
			errors=bindingResult.getAllErrors();
			for (ObjectError o:errors) {
				System.out.println(o.getDefaultMessage());
			}
		}else
		{
			System.out.println("product:"+product);
		}
		ModelAndView mav = new ModelAndView();
		mav.setViewName("add_product");
		mav.addObject("errors",errors); //向页面传错误信息
		return mav;
	}

配置分组校验

背景:

在pojo中定义校验规则,而pojo是被多个 controller所共用,当不同的controller方法对同一个pojo进行校验,但是每个controller方法需要不同的校验。

解决方法:

定义多个校验分组(其实是一个java接口),分组中定义有哪些规则
每个controller方法使用不同的校验分组

1.定义校验分组
分组就是一个标识,在实体类的包中定义一个接口,接口中不需要定义任何方法,如下:
定义一个AddGroup接口,表示这是在增加产品时使用到校验分组

package net.neuedu.springmvc.domain;

public interface AddGroup {
	
}

再定义一个UpdateGroup接口,表示修改产品是使用到的校验分组

package net.neuedu.springmvc.domain;

public interface UpdateGroup {

}

pojo代码修改如下:
其中 groups = {AddGroup.class}属性表示这个属于增加产品是的校验组;
groups = {AddGroup.class,UpdateGroup.class} 表示增加和修改同时需要的校验组;
即是,分组需要校验什么属性,就在这个属性上增加 接口.class(AddGroup.class})

@NotEmpty(message = "{productNameNotNullMessage}",groups = {AddGroup.class})
    @Size(max = 20,min = 6,message = "{productNameErrorMessage}",groups = {AddGroup.class})	
	private String productName;  //名字
	
	//double型的数据,最大10000.00,最小0.01
	@DecimalMax(value = "10000.00",message = "{productPriceMaxErro}",groups = {AddGroup.class,UpdateGroup.class})
	@DecimalMin(value = "0.01",message = "{productPriceMinErro}",groups = {AddGroup.class,UpdateGroup.class})
	private Double productPrice;//价格
	
	//非空
	@NotNull(message="{productDateIsNullError}",groups = {AddGroup.class})
	private Date productDate;//日期
	
	//非空
	@NotBlank(message="{productDescIsNullError}",groups = {AddGroup.class})
	private String desc;//描述
	
	//非空,邮箱校验使用到正则表达式
	@NotEmpty(message = "{emailNameNotNullMessage}",groups = {AddGroup.class})
	@Pattern(regexp = "^\\w+@\\w+/.\\w+$",message = "{emailNameErrorMessage}",groups = {AddGroup.class})
	private String email;

Controller:
在接收参数的前面加上@Validated(value = {AddGroup.class})属性即可。

public ModelAndView addProduct(@Validated(value = {AddGroup.class}) Product product,BindingResult bindingResult)