java valid payload_Spring Validation最佳实践及其实现原理,参数校验没那么简单!

之前也写过一篇关于Spring Validation使用的文章,不过自我感觉还是浮于表面,本次打算彻底搞懂Spring Validation。本文会详细介绍Spring Validation各种场景下的最佳实践及其实现原理,死磕到底!

项目源码:spring-validation

简单使用

Java API规范(JSR303)定义了Bean校验的标准validation-api,但没有提供实现。hibernate validation是对这个规范的实现,并增加了校验注解如@Email、@Length等。Spring Validation是对hibernate validation的二次封装,用于支持spring mvc参数自动校验。接下来,我们以spring-boot项目为例,介绍Spring Validation的使用。

引入依赖

如果spring-boot版本小于2.3.x,spring-boot-starter-web会自动传入hibernate-validator依赖。如果spring-boot版本大于2.3.x,则需要手动引入依赖:

org.hibernate

hibernate-validator

6.0.1.Final

对于web服务来说,为防止非法参数对业务造成影响,在Controller层一定要做参数校验的!大部分情况下,请求参数分为如下两种形式:POST、PUT请求,使用requestBody传递参数;

GET请求,使用requestParam/PathVariable传递参数。

下面我们简单介绍下requestBody和requestParam/PathVariable的参数校验实战!

requestBody参数校验

POST、PUT请求一般会使用requestBody传递参数,这种情况下,后端使用DTO对象进行接收。只要给DTO对象加上@Validated注解就能实现自动参数校验。比如,有一个保存User的接口,要求userName长度是2-10,account和password字段长度是6-20。如果校验失败,会抛出MethodArgumentNotValidException异常,Spring默认会将其转为400(Bad Request)请求。DTO表示数据传输对象(Data Transfer Object),用于服务器和客户端之间交互传输使用的。在spring-web项目中可以表示用于接收请求参数的Bean对象。在DTO字段上声明约束注解@Data

public class UserDTO {

private Long userId;

@NotNull

@Length(min = 2, max = 10)

private String userName;

@NotNull

@Length(min = 6, max = 20)

private String account;

@NotNull

@Length(min = 6, max = 20)

private String password;

}在方法参数上声明校验注解@PostMapping("/save")

public Result saveUser(@RequestBody @Validated UserDTO userDTO) {

// 校验通过,才会执行业务逻辑处理

return Result.ok();

}这种情况下,使用@Valid和@Validated都可以。

requestParam/PathVariable参数校验

GET请求一般会使用requestParam/PathVariable传参。如果参数比较多(比如超过6个),还是推荐使用DTO对象接收。否则,推荐将一个个参数平铺到方法入参中。在这种情况下,必须在Controller类上标注@Validated注解,并在入参上声明约束注解(如@Min等)。如果校验失败,会抛出ConstraintViolationException异常。代码示例如下:@RequestMapping("/api/user")

@RestController

@Validated

public class UserController {

// 路径变量

@GetMapping("{userId}")

public Result detail(@PathVariable("userId") @Min(10000000000000000L) Long userId) {

// 校验通过,才会执行业务逻辑处理

UserDTO userDTO = new UserDTO();

userDTO.setUserId(userId);

userDTO.setAccount("11111111111111111");

userDTO.setUserName("xixi");

userDTO.setAccount("11111111111111111");

return Result.ok(userDTO);

}

// 查询参数

@GetMapping("getByAccount")

public Result getByAccount(@Length(min = 6, max = 20) @NotNull String account) {

// 校验通过,才会执行业务逻辑处理

UserDTO userDTO = new UserDTO();

userDTO.setUserId(10000000000000003L);

userDTO.setAccount(account);

userDTO.setUserName("xixi");

userDTO.setAccount("11111111111111111");

return Result.ok(userDTO);

}

}

统一异常处理

前面说过,如果校验失败,会抛出MethodArgumentNotValidExcep

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值