springboot中使用validation校验参数

目录

一、validation的简单使用

二、validation的几个常用注解 

三、 异常捕获的两种处理方式

四、分组校验

五、@Valid嵌套校验


一、validation的简单使用

1、pom文件引入validation

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.5.4</version>
        </dependency>

2、post请求,@RequestBody参数校验,只需要在前面加@Validated即可

    @PostMapping("/test1")
    public void validatedTest1(@Validated @RequestBody OrderTest orderTest) {
        log.info("request={}",orderTest);
    }

3、get请求,@RequestParam 参数校验使用,在类上加@Validated,参数前加对应注解,@NotBlank、@NotNull等

@Slf4j
@RestController
@RequestMapping("/validated")
@Validated
public class ValidatedTestController {
    @GetMapping("/test2")
    public void validatedTest2(@NotBlank @RequestParam String name) {
        log.info("name={}",name);
    }
}

二、validation的几个常用注解 

@Data
public class OrderTest {

    /**
     * 常用于String类型不为空
     */
    @NotBlank
    public String orderNo;

    /**
     * NotNull可用于所有类型,不能为null
     * Min最小值包含该值
     * Max最大值包含该值
     * 注意一般结合NotNull使用,如果没有NotNull,可以不传该值,为null时不校验最大最小值
     */
    @NotNull
    @Min(1)
    @Max(100)
    public Integer quantity;

    @NotNull
    @DecimalMin("0.01")
    @DecimalMax("200")
    public BigDecimal price;

    @NotNull(message = "订单日期不能为空")
    public LocalDate orderDate;
}

三、 异常捕获的两种处理方式

1、validation异常捕获配置,抛异常全局捕获处理,返回前端显示只返回message即可,不然太长不太友好,ExceptionHandler的配置如下,可参考修改

  1. @Validated @RequestBody中参数校验抛出异常类型为BindException.class
  2. @NotBlank @RequestParam中参数校验异常类型ValidationException.class
//注意修改basePackages = "com.xxx.xxx" 改为自己项目路径
@ControllerAdvice(basePackages = "com.xxx.xxx")
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public HttpResponse handlerException(HttpServletRequest request, Exception e) {
        log.info("exception err",e);
        return HttpResponse.error(e.getMessage());
    }

    @ExceptionHandler(BindException.class)
    public HttpResponse handlerBindException(HttpServletRequest request, BindException e) {
        log.info("argumentException err",e);
        StringBuilder errMessage = new StringBuilder();
        BindingResult bindingResult = e.getBindingResult();
        if (bindingResult.hasErrors()) {
            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                errMessage.append(fieldError.getField()).append(fieldError.getDefaultMessage()).append(";");
            }
        } else {
            errMessage.append(e.getMessage());
        }
        return HttpResponse.error(errMessage.toString());
    }

    @ExceptionHandler(ValidationException.class)
    public HttpResponse handlerValidationException(HttpServletRequest request, ValidationException ex) {
        log.error("validation error",ex);
        return HttpResponse.error(ex.getMessage());
    }
}

2、结合BindingResult 主动判断,此种方式不会抛出异常,需要判断hasErrors进行业务处理,是继续还是中断等

@PostMapping("/test1")
    public void validatedTest1(@Validated @RequestBody OrderTest orderTest, BindingResult result) {
        if (result.hasErrors()) {
            log.info("errors={}",result.getAllErrors());
        }
        log.info("request={}",orderTest);
    }

四、分组校验

1、@Validated的group分组校验

例如OrderTest中orderNo我在新插入时不要求必填,更新时要求必填如果校验呢,当然呢可以分别建两个对象进行分别验证,也可以通过group来进行分组验证

(1)、接收对象OrderTest如下加入分组,Insert.class和Update.class为两个空interface,名字自行定义修改

public interface Insert {
}
@Data
public class OrderTest {

    @NotBlank(groups = Update.class)
    public String orderNo;

    @NotBlank(groups = {Update.class,Insert.class})
    public String customerId;

    @NotNull(groups = Insert.class)
    @Min(1)
    @Max(100)
    public Integer quantity;

    @NotNull
    @DecimalMin("0.01")
    @DecimalMax("200")
    public BigDecimal price;

    @NotNull(message = "订单日期不能为空")
    public LocalDate orderDate;
}

(2)@Validated使用时只需要加入分组即可

@Slf4j
@RestController
@RequestMapping("/validated")
@Validated
public class ValidatedTestController {

    @PostMapping("/test1")
    public void validatedInsertTest1(@Validated(Insert.class) @RequestBody OrderTest orderTest) {
        log.info("request={}",orderTest);
    }

    @PostMapping("/test1/update")
    public void validatedUpdateTest1(@Validated(Update.class) @RequestBody OrderTest orderTest) {
        log.info("request={}",orderTest);
    }

    @GetMapping("/test2")
    public void validatedTest2(@NotBlank @RequestParam String name) {
        log.info("name={}",name);
    }
}

如果@Validated加入了分组,那么只校验对应分组的判断,结果截图如下@Validated(Update.class)只校验orderNo、customerId

@Validated(Insert.class)只校验customerId、quantity

 

五、@Valid嵌套校验

嵌套对象属性上加@valid即可,如果是list则在List<@Valid OrderTestDetail>,新建一个OrderTest和OrderTestDetail

@Data
public class OrderTest {

    @NotBlank
    public String orderNo;

    @NotBlank
    public String customerId;

    @Valid
    public OrderTestDetail orderTestDetail;

    @NotNull
    public List<@Valid OrderTestDetail> orderTest2List;
}

@Data
public class OrderTestDetail {
    @NotBlank
    private String orderNo;

    @NotBlank
    private String name;
}

结果验证如图

 中间小插曲Cannot deserialize value of type `java.util.ArrayListccom.ssh.mydmx.dto.OrderTestDetail` from Object value (token `JsonToken.START_OBJECT`)

这个因为我是用idea中restful插件orderTest2List的传参,它默认没有加中括号[]导致

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值