服务端数据校验
为什么需要服务端校验?
最早的校验,就是服务端校验。早期的网站,用户输入一个邮箱地址,校验邮箱地址需要将地址发送到服务端,服务端进行校验,校验成功后,给前端一个响应。有了JavaScript,校验工作可以放在前端去执行。那么为什么还需要服务端校验呢?
因为前端传来的数据不可信。前端很容易获取都后端的数据接口,如果有人绕过页面,就会出现非法数据,所以服务端也要数据校验,总的来说:
- 前端校验要做,目的是为了提高用户体验
- 后端校验也要做,目的是为了数据安全
一、普通校验
1、Spring MVC 中不支持服务端的数据校验,需要添加Hibernate相关校验依赖,Hibernate的校验框架和ORM没有关系。
2、创建错误配置信息properties文件
book.name.null=\u4E66\u540D\u4E0D\u80FD\u4E3A\u7A7A\uFF01
book.name.length=\u4E66\u540D\u4E0D\u80FD\u5C0F\u4E8E3\uFF01
book.author.null=\u4F5C\u8005\u4E0D\u80FD\u4E3A\u7A7A\uFF01
3、在Spring MVC 的配置文件中配置如下:
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource">
<property name="basenames">
<list>
<!-- bookError 是自定义错误信息properties配置文件名 -->
<value>classpath:bookError</value>
</list>
</property>
</bean>
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" id="validatorFactory">
<property name="validationMessageSource" ref="messageSource"/>
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
</bean>
<mvc:annotation-driven validator="validatorFactory"/>
4、在需要校验的类上添加注解:
@NotNull(message = "书籍编号不能为空!")
private Integer id;
//书名长度必须大于3
@Length(min = 3,message = "{book.name.length}")
@NotNull(message = "{book.name.null}")
private String name;
//作者不能为空
@NotNull(message = "{book.author.null}")
private String author;
5、在Controller中,指明数据校验:
/**
* 数据校验
* @param book
* @param bindingResult
*/
@RequestMapping("/book")
@ResponseBody
public void addBook(@Validated Book book, BindingResult bindingResult ) {
if (bindingResult.hasErrors()) {
List<ObjectError> allErrors = bindingResult.getAllErrors();
for (ObjectError error : allErrors) {
System.out.println(error.getDefaultMessage());
}
}
System.out.println(book);
}
二、分组校验
1、定义分组
定义分组,实际上就是两个空的接口:
/**
* 分组一
* @author 叶小陌
*
*/
public interface Group1 {
}
/**
* 分组二
* @author 叶小陌
*
*/
public interface Group2 {
}
2、在校验上指定分组
@NotNull(message = "书籍编号不能为空!",groups = {Group1.class})
private Integer id;
//书名长度必须大于3
@Length(min = 3,message = "{book.name.length}",groups = {Group1.class,Group2.class})
@NotNull(message = "{book.name.null}",groups = {Group1.class,Group2.class})
private String name;
//作者不能为空
@NotNull(message = "{book.author.null}",groups = {Group1.class,Group2.class})
private String author;
3、在Controller中指定分组
/**
* 数据校验
* @param book
* @param bindingResult
*/
@RequestMapping("/book")
@ResponseBody
public void addBook(@Validated(value = Group2.class) Book book, BindingResult bindingResult ) {
if (bindingResult.hasErrors()) {
List<ObjectError> allErrors = bindingResult.getAllErrors();
for (ObjectError error : allErrors) {
System.out.println(error.getDefaultMessage());
}
}
System.out.println(book);
}
三、其他一些常见的校验注解如下:
注解 | 说明 |
---|---|
@Null | 被注解的元素必须为 null |
@NotNull | 被注解的元素必须不为 null |
@AssertTrue | 被注解的元素必须为 true |
@AssertFalse | 被注解的元素必须为 false |
@Min(value) | 被注解的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注解的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注解的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value) | 被注解的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Size(max=, min=) | 被注解的元素的大小必须在指定的范围内 |
@Digits (integer, fraction) | 被注解的元素必须是一个数字,其值必须在可接受的范围内 |
@Past | 被注解的元素必须是一个过去的日期 |
@Future | 被注解的元素必须是一个将来的日期 |
@Pattern(regex=,flag=) | 被注解的元素必须符合指定的正则表达式 |
@NotBlank(message =) | 验证字符串非null,且长度必须大于0 |
被注解的元素必须是电子邮箱地址 | |
@Length(min=,max=) | 被注解的字符串的大小必须在指定的范围内 |
@NotEmpty | 被注解的字符串的必须非空 |
@Range(min=,max=,message=) | 被注解的元素必须在合适的范围内 |