前言
数据的校验是交互式网站一个不可或缺的功能,前端的js校验可以涵盖大部分的校验职责,如用户名唯一性,生日格式,邮箱格式校验等等常用的校验。但是为了避免用户绕过浏览器,使用http工具直接向后端请求一些违法数据,服务端的数据校验也是必要的,可以防止脏数据落到数据库中,如果数据库中出现一个非法的邮箱格式,也会让运维人员头疼不已。在一般的应用,可以使用validation来对数据进行校验。
校验思路:
- 页面提交请求的参数,请求到controller方法中,使用validation进行校验。
- 如果校验出错,将错误信息展示到页面。
配置数据校验步骤
- 导入校验jar文件
hibernate的校验框架validation所需要jar包 - 配置校验器
在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>
- 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方法这里省略不写
}
- 错误信息文件
- 在 .properties配置校验错误信息
- 把配置文件放到类路径中
- 捕获错误信息
- 在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)