SpringBoot 参数校验

背景

参考地址:https://mp.weixin.qq.com/s/lcXIl2ifr3OmiSOPdaXLnw
通过注解实现参数校验。

单个参数校验

/**
     * controller 上必须加 @Validated ,同时NotNull和 RequestParam本身的非空冲突
	 * 加 @Validated之后,并不意味着其他类型参数校验可以不用@Validated
     * @param id
     * @throws Exception
     */
    @ApiOperation("单个参数校验")
    @GetMapping("/singleParam")
    public void login(@ApiParam(value= "主键id") @Min(1) @RequestParam Integer id) throws Exception{
        ResponseFactory.success();
    }

一般DTO使用

DTO 定义:

public class UserDTO {
	/**
	 * 用户名
	 */
	@NotNull(message = "用户名不能为空")
	private String userName;

	/**
	 * 密码
	 */
	@NotNull(message = "密码不能为空")
	private String passWord;
}

controller层:

@PostMapping("/login")
public ResponseVo<User> login(@Valid @RequestBody UserDTO userDTO)throws Exception{

	return ResponseFactory.success(userService.login(userDTO));
}
@PostMapping("/login2")
public ResponseVo<User> login2(@Validated @RequestBody UserDTO userDTO)throws Exception{

	return ResponseFactory.success(userService.login(userDTO));
}

总结:这时候使用 @Valid 或 @Validated 效果一致

分组校验

起因:在实际项目中,可能多个方法需要使用同一个DTO类来接收参数,而不同方法的校验规则很可能是不一样的。
比如保存User的时候,UserId是可空的,但是更新User的时候,UserId的必须有值。
解决方案:约束注解上声明适用的分组信息groups
DTO定义:

@Data
@ApiModel("分组校验dto1")
public class UserGloupValidDTO1 {

	public interface Add {
	}
	public interface Update {
	}

	/**
	 * 用户名
	 */
	@NotNull(message = "id不能为空", groups = UserGloupValidDTO1.Add.class)
	@ApiModelProperty(value = "id")
	private Integer id; //用int的话,@NotNull校验不行,因为它校验的是对象
	/**
	 * 用户名
	 */
	@NotNull(message = "用户名不能为空", groups = {UserGloupValidDTO1.Add.class, UserGloupValidDTO1.Update.class} )
	@ApiModelProperty(value = "用户名")
	private String userName;

	/**
	 * 密码
	 */
	@NotNull(message = "密码不能为空", groups = {UserGloupValidDTO1.Add.class, UserGloupValidDTO1.Update.class})
	@ApiModelProperty(value = "密码")
	private String passWord;

}

controller定义:

@ApiOperation("分组校验1")
@PostMapping("/valid3")
public void login3(@Validated(UserGloupValidDTO1.Add.class) @RequestBody UserGloupValidDTO1 reqDTO)throws Exception{
}

注:DTO中定义接口类标识分组类别,接口类除了名字,没有别的内容。与controller 层中@Validated(UserGloupValidDTO1.Add.class) 对应。说明这个只是起到一个标识的作用。因为一个项目有多个dto,如果每个都自己定义分组的话,就太多了。
定义公共校验分组 :

public class ValidGroups {
	public interface Add {
	}
	public interface Delete {
	}
	public interface Query {
	}
	public interface Update {
	}
}

DTO和controller 中分别使用这个标记{

@NotNull(message = "id不能为空", groups = ValidGroups.Update.class)
		
@Validated(ValidGroups.Update.class)

ps:分组校验不能用@Valid ,编译就失败了

嵌套校验

前面的示例中,DTO类里面的字段都是基本数据类型和String类型。
但是实际场景中,有可能某个字段也是一个对象,这种情况先,可以使用嵌套校验。
比如,上面保存User信息的时候同时还带有Job信息。
需要注意的是,此时DTO类的对应字段必须标记@Valid注解。
NestValidDTO.java:

@NotNull(message = "用户名不能为空", groups = {ValidGroups.Add.class, ValidGroups.Update.class})
private String userName;

@Valid //DTO类的对应字段必须标记@Valid注解
private JobDTO jobDTO;

注:当NestValidDTO.java 只剩下 jobDTO ,同时将它修改为List ,也就实现了集合校验

集合校验

参考的文章中使用的是
定义一个validList{

public class ValidationList<E> implements List<E> {
	@Delegate // @Delegate是lombok注解
	@Valid // 一定要加@Valid注解
	public List<E> list = new ArrayList<>();

	// 一定要记得重写toString方法
	@Override
	public String toString() {
		return list.toString();
	}
}

}
controller {

/**
 * 多个错误只能抛出一个,同时错误为“java.lang.IllegalStateException: JSR-303 ”
 * 无法被参数异常捕获
 * @param userList
 * @return
 */
@ApiOperation("集合-分组校验(文章示例)")
@PostMapping("/saveList6")
public ResponseVo saveList(@RequestBody @Validated(ValidGroups.Update.class) ValidationList<UserGloupValidDTO2> userList) {
	// 校验通过,才会执行业务逻辑处理
	return ResponseFactory.success();
}

}
总结:这种方式不行,使用嵌套校验“注”中提到的方式。

编程式校验

@Autowired
private javax.validation.Validator globalValidator;
/**
 * 编程式校验
 * @param userDTO
 * @return
 */
@ApiOperation("编程式校验")
@PostMapping("/saveList7")
public ResponseVo saveWithCodingValidate(@RequestBody UserGloupValidDTO2 userDTO) {
    Set<ConstraintViolation<UserGloupValidDTO2>> validate = globalValidator.validate(userDTO, ValidGroups.Update.class);
    // 如果校验通过,validate为空;否则,validate包含未校验通过项
    if (validate.isEmpty()) {
        // 校验通过,才会执行业务逻辑处理

    } else {
        for (ConstraintViolation<UserGloupValidDTO2> userDTOConstraintViolation : validate) {
            // 校验失败,做其它逻辑
            System.out.println(userDTOConstraintViolation);
        }
    }
    return ResponseFactory.success();
}
	

当我们并不是参数失败就退出时,需要这种方式

自定义参数校验注解

参考我的一篇注解文章

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值