springboot参数校验

参数校验

基于PathVariable的正则匹配

通过PathVariable,在{}包裹的字段后加冒号:,在加上正则。
如果不匹配正则,则前端会报出404.

/**
 * 采用正则,在pathvarable中做参数校验
 * 如果不匹配正则,则返回404
 */
@RestController
@RequestMapping("pathVariable")
public class AppController {

    @GetMapping("/id/{id:\\d+}")
    public String getId(@PathVariable("id") Integer id) {
        return String.valueOf(id);
    }

    @GetMapping("char/{char:[a-zA-Z0-9_]+}")
    public String getChar(@PathVariable("char") String charVar) {
        return charVar;
    }

}

基于注解

添加maven依赖

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.1.Final</version>
        </dependency>

单个字段校验

1、在Controller上注解@Validated
2、在字段前加入相应注解


/**
 * 单个参数的校验
 * 在@Validated
 */
@RestController
@RequestMapping("valid1")
@Validated
public class App2Controller {

    @GetMapping
    public String get(@NotEmpty(message = "name不能为空") String name, @Min(value = 12) Integer age) {
        return name + ":" + age;
    }

}

javabean校验

1、在实体类上加上注解校验

@Data
public class User {

    @NotEmpty(message = "实体类name不能为空")
    private String name;

    @Max(value = 100)
    private Integer age;
}

2、在Controller出的方法入参处加上@Validated ,BindingResult可以收集错误

@RestController
@RequestMapping("user")
public class App3Controller {

    @PostMapping
    public String post(@Validated @RequestBody User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            for (ObjectError allError : bindingResult.getAllErrors()) {
                System.out.println(allError.getDefaultMessage());
                throw new RuntimeException(allError.getDefaultMessage());
            }
        }
        return user.getName();
    }
}

自定义注解校验

1、定义一个注解

@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AppValidator.class)//指定注解逻辑实现类
public @interface AppValidAnno {
    String message() default "";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

note

  • message,groups,payload三个字段必须要
  • 需要在注解上表明逻辑的实现类,这个是ConstraintValidator的实现类
    2、实现ConstraintValidator类
/**
 * 不需要@Component
 * 实现了ConstraintValidator接口,spring会自动将其视为一个组件
 */
//@Component
public class AppValidator implements ConstraintValidator<AppValidAnno, String> {

    //注入其他逻辑类
    @Autowired
    private AppComponent appComponent;

    @Override
    public void initialize(AppValidAnno constraintAnnotation) {
        System.out.println("方法初始化");
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        return appComponent.validStr(s);
    }
}

note

  • 可以在这个类注入其他spring组件
  • 不需要@Component,实现了ConstraintValidator接口,spring会自动将其视为一个组件
  • ConstraintValidator<AppValidAnno, String>两个范型,第一个是对应的注解,第二个是要处理的字段的类型
    3、和其他校验注解的使用方式相同
@Data
public class User {

    @NotEmpty(message = "实体类name不能为空")
    private String name;

    @Max(value = 100)
    private Integer age;

    @AppValidAnno(message = "必须以app-开头")
    private String code;

}

更优雅的方式

采用validation的方式校验参数的时候,当在参数前加上@valid注解,才会生效,但是在上文的方式中,我们还在代码中加入了BindingResult这个类来接收错误参数。

public String post(@Validated @RequestBody User user, BindingResult bindingResult) {

所以此方法可以简化这种使用方式,不用在每个方式中加入参数BindingResult。
我们可以采用RestControllerAdvice来统一处理和返回错误信息。

    @PostMapping("/o")
    public String post1(@Valid @RequestBody User user) {
        return user.getName();
    }

统一处理代码

@RestControllerAdvice
public class ExceptionControllerAdvice {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public String MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        // 从异常对象中拿到ObjectError对象
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        // 然后提取错误提示信息进行返回
        return objectError.getDefaultMessage();
    }
}

参考

https://zhuanlan.zhihu.com/p/208298120

git

https://github.com/lexiaoyao1995/validatordemo

posted @ 2020-09-20 19:51  刃牙  阅读(1055)  评论(0编辑  收藏  举报