对于Web服务器来说,为防止非法参数对业务造成影响,需要在Controller层做参数校验,通常将请求参数分为两种形式:
- POST、PUT请求,使用RequestBody传递参数;
- GET请求,使用RequestParam或PathVariable传递参数。
RequestBody参数校验
POST、PUT请求一般使用RequestBody传递参数,这种情况下,后端使用DTO对象进行接收。只要给DTO对象加上@Validated注解就能实现自动参数校验(需在DTO字段上声明约束注解)。
RequestParma或PathVariable参数校验
GET请求一般会使用RequestParma/PathVariable传参。如果参数参数比较多,还是推荐使用DTO对象接收。否则,推荐将一个个参数平铺到方法入参中,在这种情况下,必须在controller类上标注@Validated注解,并在入参上声明约束注解,如校验失败,会抛出ConstraintViolationException异常。
分组校验
在实际开发中,可能有多个方法使用同一个DTO类来接收参数,而不同的方法校验规则可能不一样,这时,简单的在DTO类的字段上加约束注解无法解决这个问题,因此,spring-validation支持分组校验功能,专门用来解决此类问题。
//保存时UserId可为空,更新是userId的值必须>=10000L
@Data
public class UserDTO {
@Min(value = 10000L, groups = Update.class)
private Long userId;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 2, max = 10, groups = {Save.class, Update.class})
private String userName;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 6, max = 20, groups = {Save.class, Update.class})
private String account;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 6, max = 20, groups = {Save.class, Update.class})
private String password;
/**
* 保存的时候校验分组
*/
public interface Save {
}
/**
* 更新的时候校验分组
*/
public interface Update {
}
}
@Validated注解指定校验分组
@PostMapping("/save")
public Result saveUser(@RequestBody @Validated(UserDTO.Save.class) UserDTO userDTO) {
// 校验通过,才会执行业务逻辑处理
return Result.ok();
}
@PostMapping("/update")
public Result updateUser(@RequestBody @Validated(UserDTO.Update.class) UserDTO userDTO) {
// 校验通过,才会执行业务逻辑处理
return Result.ok();
}
嵌套校验
DTO类里面的字段都是基本数据类型和String类型。但是实际场景中,有可能某个字段也是一个对象,这种情况先,可以使用嵌套校验。
保存User信息的时候同时还带有Job信息。需要注意的是,此时DTO类的对应字段必须标记@Valid注解。
@Data
public class UserDTO {
@Min(value = 10000000000000000L, groups = Update.class)
private Long userId;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 2, max = 10, groups = {Save.class, Update.class})
private String userName;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 6, max = 20, groups = {Save.class, Update.class})
private String account;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 6, max = 20, groups = {Save.class, Update.class})
private String password;
@NotNull(groups = {Save.class, Update.class})
@Valid
private Job job;
@Data
public static class Job {
@Min(value = 1, groups = Update.class)
private Long jobId;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 2, max = 10, groups = {Save.class, Update.class})
private String jobName;
@NotNull(groups = {Save.class, Update.class})
@Length(min = 2, max = 10, groups = {Save.class, Update.class})
private String position;
}
/**
* 保存的时候校验分组
*/
public interface Save {
}
/**
* 更新的时候校验分组
*/
public interface Update {
}
}
嵌套校验可以结合分组校验一起使用,而且嵌套集合校验会对集合里面的每一项都进行校验。