springboot 各种方式的校验
springboot 有各种方式进行校验,下面一一进行介绍
1 Java断言的方式
Java1.4引入断言。可以使用这种方式做参数的校验。下面是一段做校验的例子。assert表达式为false的时候会抛出一个异常。
@PutMapping("/assert")
public Employee put2(@RequestBody Employee employee){
assert employee.getName() != null && !"".equals(employee.getName());
return employee;
}
2 Spring Assert方式
同样,使用spring Assert也可以做校验,方式与assert类似,下面是一段例子。name不能为空,否则会抛出一个异常,异常的message就是 “名称不能为空”,这种方式更好用一些,能够自定义错误消息
@PutMapping("/spring/assert")
public Employee put1(@RequestBody Employee employee){
Assert.hasText(employee.getName(), "名称不能为空");
return employee;
}
3 参数校验方式
通过javax.validation.constraints.xxx的注解对参数修饰。Controller上修饰@org.springframework.validation.annotation.Validated,如下面的例子。
@GetMapping("/param")
public Employee get1(@Size(min=3, max=5) String name, @Min(3) @Max(5) int id ){
return new Employee(id, name);
}
如果不满足条件会抛出MethodArgumentNotValidException异常,通过ControllerAdivisor可以抓取异常,向前台返回异常信息,具体返回异常情况可根据自己项目。ControllerAdivisor抓取异常方式可见上一篇,下面是例子。
@ExceptionHandler(value = ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String to400(ConstraintViolationException e){
StringBuilder result = new StringBuilder();
result.append("error 400 :");
Set<ConstraintViolation<?>> cvs = e.getConstraintViolations();
if(cvs != null){
for (ConstraintViolation cv: cvs) {
Path path = cv.getPropertyPath();
String msg = cv.getMessage();
result.append(path).append(",").append(msg).append(";");
//TODO 这里可以使用path 和msg 组合成返回的内容,这里就是做一个拼接
}
}
return result.toString();
}
4 Bean校验方式
校验Bean的方式可以使用spring的 validation。
引入validation依赖
compile('org.springframework.boot:spring-boot-starter-validation')
bean的参数上添加注解
package com.zqw.springboot.learn.boot.validate.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
@Data
@Slf4j
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
@Max(value=5,message = "最大5")
@Min(value = 3, message = "最小3")
private Integer id;
@Size(min=3,max=5, message = "介于3到5")
private String name;
}
Controller 注入bean时添加@Valid注解
@PutMapping("/bean")
public Employee put3(@Valid @RequestBody Employee employee){
return employee;
}
校验失败时会抛出一个MethodArgumentNotValidException 异常,可以在controlleradvisor抓取异常做处理返回前台
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String to400(MethodArgumentNotValidException e){
StringBuilder result = new StringBuilder();
result.append("error 400 :");
BindingResult bindingResult = e.getBindingResult();
List<FieldError> errors = bindingResult.getFieldErrors();
if(errors != null){
for (FieldError error: errors) {
String field = error.getField();
String msg = error.getDefaultMessage();
//TODO 这里可以使用field 和msg 组合成返回的内容,这里就是做一个拼接
result.append(field).append(",").append(msg).append(";");
}
}
return result.toString();
}
5 自定义校验
假设要校验身份证号,不能为空,必须为数字(暂且这么认为),必须为18位。
编写注解类,message为校验失败的默认输出,可以采用国际化的方式定义
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR,
ElementType.ANNOTATION_TYPE,ElementType.PARAMETER})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {CarNoValidator.class})
public @interface CarNoConstraint {
String message() default "{carNo.constraint.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
编写Constraint类implements ConstraintValidator
public class CarNoValidator implements ConstraintValidator<CarNoConstraint, String> {
public void initialize(SexConstraint constraintAnnotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(StringUtils.isBlank(value)) return false;
if(value.length() != 18) return false;
if(!StringUtils.isNumeric(value)) return false;//身份证号可能最后为X,先不管他,暂时认为都是数字
return true;
}
}
在使用此注解的bean上添加注解,这里还自定义了一个枚举的校验,详情可参考本文最后的github源码
@Data
@Slf4j
public class Employee {
@Max(value=5,message = "最大5")
@Min(value = 3, message = "最小3")
private Integer id;
@Size(min=3,max=5, message = "介于3到5")
private String name;
@SexConstraint
private Sex sex;
@CarNoConstraint
private String carNo;
public Employee( Integer id, String name) {
this.id = id;
this.name = name;
}
public Employee() {
}
}
国际化配置在resource下面定义ValidatorMessages.properties 和ValidatorMessages_zh_CN.properties
sex.constraint.message=the sex is ont valid
carNo.constraint.message=the carNo must be number, the length must be 18
sex.constraint.message=\u6027\u522b\u975e\u6cd5
carNo.constraint.message=\u8eab\u4efd\u8bc1\u4e0d\u80fd\u4e3a\u7a7a\uff0c\u5fc5\u987b\u4e3a\u6570\u5b57\uff0c\u5fc5\u987b\u4e3a18\u4f4d
校验不通过时会抛出MethodArgumentNotValidException异常,异常抓取方式可参见bean校验处。
当然校验的注解也可以直接作用在参数上,参见第3中参数的校验。这里的校验如下:
@GetMapping("/carNo/param")
public String get1(@CarNoConstraint String carNo ){
return carNo;
}
github 源码
springboot学习 上一篇 springboot异常处理
springboot学习 下一篇 自定义监听