SpringBoot精选

SpringBoot数据校验hibernate-validato

2018-12-05  本文已影响198人  AC编程

一、数据校验

在web开发时,对于请求参数,一般上都需要进行参数合法性校验的,原先的写法时一个个字段一个个去判断,这种方式太不通用了,所以java的JSR 303: Bean Validation 1.0 规范就是解决这个问题的。JSR 303只是个规范,并没有具体的实现,目前通常都是才有hibernate-validator进行统一参数校验。

二、Hibernate Validator 版本

Hibernate Validator是Hibernate团队最初的验证框架,现在被称为“Legacy Hibernate Validator”。Hibernate Validator 4.x是Bean Validation 1.0(JSR 303)的参考实现,而Hibernate Validator 5.x是Bean Validation 1.1(JSR 349)的参考实现,目前最新版的Hibernate Validator 6.x 是Bean Validation 2.0(JSR 380)的参考实现。

三、hibernate validator校验demo

spring-boot-starter-web包里面有hibernate-validator包,不需要引用hibernate validator依赖。

3.1 校验对象数据

给bean配置Validation Annotations

import javax.validation.constraints.*;  // 注:不是用org.hibernate.validator.constraints
public class DemoModel {

    @NotBlank(message="用户名不能为空")
    @Length(min = 1, max = 20, message = "用户名应为1~20个字符")
    private String userName;

    @NotBlank(message="年龄不能为空")
    @Pattern(regexp="^[0-9]{1,2}$",message="年龄不正确")
    @Min(value = 18, message = "用户年龄必须大于18岁")
    @Max(value = 150, message = "用户年龄必须小于150岁")
    private String age;

    @AssertFalse(message = "必须为false")
    private Boolean isFalse;

    //如果是空,则不校验,如果不为空,则校验
    @Pattern(regexp="^[0-9]{4}-[0-9]{2}-[0-9]{2}$",message="出生日期格式不正确")
    private String birthday;

    @NotEmpty
    @Email(message = "邮箱格式不正确")
    private String email;

    // get set 省略.....
}

POST接口验证,BindingResult是验证不通过的格式化后的结果集合(如果不写,会返回一堆英文信息)

import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;

@RestController
@RequestMapping(value = "/demo")
public class HibernateValidatorController {

    @PostMapping("/2")
    public void demo2(@RequestBody @Valid DemoModel demo, BindingResult result){
        //POST请求传入的参数:{"userName":"dd","age":160,"isFalse":true,"birthday":"21010-21-12","email":"alanchen@"}
        if(result.hasErrors()){
            for (ObjectError error : result.getAllErrors()) {
                System.out.println(error.getDefaultMessage());
            }
        }
    }
}

验证请求参数时,在@RequestBody DemoModel demo之间加注解 @Valid,然后后面加BindindResult即可;多个参数的,可以加多个@Valid和BindingResult

public void test()(@RequestBody @Valid DemoModel demo, BindingResult result)

public void test()(@RequestBody @Valid DemoModel demo, BindingResult result,@RequestBody @Valid DemoModel demo2, BindingResult result2)

3.2 GET参数校验(@RequestParam参数校验)

使用@Valid注解,对RequestParam对应的参数进行注解,是无效的,需要在方法所在的Controller上加注解@Validated

@Validated
@RestController
@RequestMapping(value = "/demo")
public class HibernateValidatorController {

    @GetMapping("/1")
    public String demo1(@Email @RequestParam(required = true) String email) {
        return "Hello SpringBoot "+email;
    }
}

3.3 hibernate的校验模式

Hibernate Validator有以下两种验证模式:

@Configuration
public class ValidatorConfiguration {
    @Bean
    public Validator validator(){
        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
                .configure()
                .addProperty( "hibernate.validator.fail_fast", "true" )
                .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();

        return validator;
    }
}

3.4返回验证信息提示

验证不通过时,抛出了ConstraintViolationException异常,使用同一捕获异常处理

@ControllerAdvice
@Component
public class GlobalExceptionHandler {

    @ExceptionHandler
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public String handle(ValidationException exception) {
        if(exception instanceof ConstraintViolationException){
            ConstraintViolationException exs = (ConstraintViolationException) exception;

            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            for (ConstraintViolation<?> item : violations) {
          /**打印验证不通过的信息*/
                System.out.println(item.getMessage());
            }
        }
        return "bad request, " ;
    }
}

3.5 使用的是JSR annotations

所有的注解,应该使用JSR注解,即javax.validation.constraints,而不是org.hibernate.validator.constraints

四、关于前后端双层校验

项目中一般是前后端对数据进行双层验证,为什么不用一种就够了?前后端都写验证,会不会重复且浪费开发资源?简单来说

参考文章

上一篇 下一篇

猜你喜欢

热点阅读