springboot学习(七) springboot 各种方式的校验

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学习 下一篇 自定义监听

猜你喜欢

转载自blog.csdn.net/u011943534/article/details/80955069