spring validation的使用与自定义校验注解
前言
前端录入数据,在后台进行校验工作是必不可少的。例如:为空校验,邮箱格式校验,手机号校验等。
后端校验的目的是避免用户绕过浏览器,使用http工具直接向后端请求一些违法数据,服务端的数据校验也是必要的,可以防止脏数据落到数据库中,如果数据库中出现一个非法的邮箱格式,也会让运维人员头疼不已。
下面介绍spring 框架中的自动校验机制。
框架提供的校验注解
| 注解 | 说明 |
| @NotNull | 值不能为空 |
| @Null | 值必须为空 |
| @Pattern(regexp=) | 字符串必须匹配正则表达式 |
| @Size(min=,max=) | 集合的元素数量必须在min和max之间 |
| @CreditCardNumber(ignoreNonDigitCharacters) | 字符串必须是信用卡号(按美国标准校验) |
| 字符串必须是Email邮箱 | |
| @Length(min=,max=) | 检查字符串的长度 |
| @NotBlank | 字符串必须有字符 |
| @NotEmpty | 字符串不为null,集合有元素 |
| @Range(min=,max=) | 数字必须大于等于min,小于等于max |
| @SafeHtml | 字符串是安全的html |
| @URL | 字符串是合法的URL |
| @AssertFalse | 值必须是false |
| @AssertTrue | 值必须是true |
| @DecimalMax(value=,inclusive=) | 值必须小于等于(inclusive=true)/小于(inclusive=false) value属性指定的值,可以注解在字符串类型的属性上 |
| @DecimalMin(value=,inclusive=) | 值必须大于等于(inclusive=true)/大于(inclusive=false) value属性指定的值,可以注解在字符串类型的属性上 |
| @Digits(integer=,fraction=) | 数字格式检查,integer指定整数部分的最大长度,fraction指定小数部分的最大长度 |
| @Future | 值必须是未来的日期 |
| @Past | 值必须是过去的日期 |
| @Max(value=) | 值必须小于等于value指定的值,不能注解在字符串类型的属性上 |
| @Min(value=) | 值必须大于等于value指定的值,不能注解在字符串类型的属性上 |
引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.1.6.RELEASE</version></dependency><!--用lombok ,让代码更简洁--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.8</version></dependency>
实体类
public class User implements Serializable {private static final long serialVersionUID = -8441401775719174836L;private Integer id;private String userName;(message = "密码不能为空")private String password;(message = "生日必须是过去的时间")private Date birthDay;}
控制层
import javax.validation.Valid;import org.springframework.validation.BindingResult;/*** 说明:* 添加 BindingResult参数后,就算验证不通过,也能继续执行方法体* BindingResult的参数的作用:* 方便记录日志(如果不想继续向下执行,可以直接再抛异常)* @param user* @param errors* @return*/public Object create( User user, BindingResult result){// 判断BindingResult是否保存错误的验证信息,如果有,则直接returnif (errors.hasErrors()) {Map<String, String> errors = Maps.newHashMap();result.getFieldErrors().stream().forEach(f -> errors.put(f.getField(), f.getDefaultMessage()));return errors;}//对 user的处理,然后返回return user;}
自定义校验注解
自定义注解用途:校验字段的在数据库里的唯一性等
定义注解类
*** 自定义校验注解* 类似与** 指明这是一个校验的注解* validatedBy = MyConstraintValidator.class 指定由MyConstraintValidator类去校验** 必须定义三个成员 message,groups,payload**/public MyConstraint {String message() default "{javax.validation.constraints.NotEmpty.message}";Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };}
定义校验类
/*** 不用添加 @Component注解* spring会扫描实现了ConstraintValidator 接口的类后,然后自动管理** ConstraintValidator<MyConstraint, String>:* 泛型参数说明:* 第一个参数 指定校验MyConstraint注解的字段* 第二参数 注解修改字段的类型* @author chennan* @date 2019.7.22 22:19*/public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {/*** 可以注入任何spring管理的服务*/private HelloService helloService;public boolean isValid(String value, ConstraintValidatorContext context) {System.out.println("------------MyConstraintValidator---------");System.out.println(value);System.out.println(helloService.greeting("tom"));System.out.println("------------MyConstraintValidator---------");//true-校验通过 false-校验不通过return false;}public void initialize(MyConstraint constraintAnnotation) {System.out.println("my validator init");}}
使用自定义校验注解
public class User implements Serializable{private static final long serialVersionUID = -8441401775719174836L;(message = "测试自定义注解")private String userName;}
