使用注解校验字段(JSR303数据校验)
我们用一个类接收前端传来的数据时,有些字段是必须的。相信很多人都是通过if else来进行判断的,但是现在我们可以通过注解的方式来进行判断,这样代码可以更简洁。步骤如下:
1.引入maven依赖(必要)
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.0.Alpha3</version>
</dependency>
2.在接收数据的类上添加注解(必要)
@Data
public class User{
@Null
private Integer id;
//如果我们要求name属性不能为空,那么就在该属性上面添加@NotBlank注解
@NotBlank(message = "用户名不能为空")
private String name;
private String password;
private String email;
}
3.在新增用户的接口上面添加@Valid注解(必要)
/**
* 保存
* @Valid注解如果不添加的话,校验规则就不会起作用
*/
@RequestMapping("/save")
public R save(@Valid @RequestBody User user){
userService.save(user);
return R.ok();
}
4.自定义返回结果BindingResult(此步骤可省略)
/**
* 就是在第三步的基础上包装一下返回结果,在参数的最后边添加BindingResult
*/
@RequestMapping("/save")
public R save(@Valid @RequestBody User user, BindingResult result){
if(result.hasErrors()){
Map<String,String> map = new HashMap<>();
//1.获取校验的错误结果
result.getFieldErrors().forEach(item ->{
//获取错误的提示信息(如果自定义了message,那么就是自定义的错误信息)
String errorMessage = item.getDefaultMessage();
//获取是哪个属性有错
String field = item.getField();
map.put(field,errorMessage);
});
return R.error(400,"提交的数据不合法").put("data",map);
}else {
userService.save(user);
return R.ok();
}
}
5.提取步骤4中的异常进行统一处理(此步骤可省略)
@RequestMapping("/save")
public R save(@Valid @RequestBody User user){
//之前Controller中的方法可简化为这样
userService.save(user);
return R.ok();
}
把之前的异常处理抽取到一个类里面
/**
* 统一异常处理
*/
@Slf4j
//@ResponseBody
//@ControllerAdvice(basePackages = "com.xxxx.yyyy.product.controller")
//@RestControllerAdvice注解里面已经包含@ResponseBody和@ControllerAdvice
//basePackages 的作用是指明可处理哪些Controller的异常
@RestControllerAdvice(basePackages = "com.xxxx.yyy.product.controller")
public class GulimallExceptionControllerAdvice {
/**
* 专门用于处理校验数据出现的异常
*/
// @ResponseBody
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleValidException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
Map<String, String> map = new HashMap<>();
//1.获取校验的错误结果
bindingResult.getFieldErrors().forEach(item -> {
//获取错误的提示信息(如果自定义了message,那么就是自定义的错误信息)
String errorMessage = item.getDefaultMessage();
//获取是哪个属性有错
String field = item.getField();
map.put(field, errorMessage);
});
return R.error(400, "数据校验出现问题").put("data", map);
}
/**
* 除了校验数据之外,也可处理其他异常
*/
@ExceptionHandler(value = Throwable.class)
public R handleException (Throwable e){
return R.error(400,e.getMessage());
}
}
6.拓展:分组校验
新增一个用户的时候,我们使用User进行接收,此时id必须为空。但是在修改用户信息的时候,我们还是用User来进行接收,此时id就不能为空了。这个时候就引出了分组校验。使用步骤如下:
1)新建两个接口
public interface AddGroup {
//里面不需要写东西
}
public interface UpdateGroup{
}
2)修改User类
@Data
public class User{
@NotNull(message = "修改必须指定用户id", groups ={UpdateGroup.class})
@Null(message = "新增不能指定id", groups = {AddGroup.class})
private Integer id;
@NotBlank(message = "用户名不能为空")
private String name;
private String password;
private String email;
}
注意:这个时候如果name属性上面的@NotBlank注解不指定分组,那么@NotBlank注解此时就会失效,如果想要添加和修改时name属性都不为空,则需要修改为@NotBlank(message = "用户名不能为空",groups = {AddGroup.class, UpdateGroup.class})
。
3)修改新增用户的接口
//新增用户
@RequestMapping("/save")
public R save(@Validated({AddGroup.class}) @RequestBody User user){
//之前Controller中的方法可简化为这样
userService.save(user);
return R.ok();
}
//修改用户信息
@RequestMapping("/update")
public R update(@Validated({UpdateGroup.class}) @RequestBody User user) {
userService.updateById(user);
return R.ok();
}
注意: @Valid已经替换为@Validated
另外记录一些其他常用注解
注解名称 | 解释说明 |
---|---|
被注释的元素必须是电子邮件地址 | |
@NotEmpty | 被注释的字符串必须非空 |
@Null | 被注释的元素必须为null |
@NotNull | 被注释的元素不能为null |
@AssertTrue | 被注释的元素必须为true |
@AssertFalse | 被注释的元素必须为false |
@Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
同时每个注解都有一个属性messgae,用来定义错误信息,例如:@NotBlank(message = “用户名不能为空”)
@Email(message=“邮箱格式不正确”)