前言:下午着手开发毕设的后端,写到注册接口时,需要校验表单字段。form类写了各字段校验规则,校验却没有生效。
错误实践
// controller类
@PostMapping("register")
public Result<String> register(@RequestBody @Validated UserForm form) {
UserDTO dto = UserDTO.toDTO(form);
userService.register(dto);
return ResultUtil.success("注册成功");
}
// form类
@Data
public class UserForm {
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 6, message = "用户名不得少于两位或多于六位")
private String username;
@NotEmpty(message = "密码不得为空")
@Size(min = 2, max = 6, message = "密码不得少于两位或多于六位")
private String password;
private String realName;
private String avatar;
private Integer gender;
@Email
private String email;
@Pattern(regexp = "^1[3-9]\d{9}$", message = "手机号码格式不正确")
private String phone;
}
implementation 'org.springframework.boot:spring-boot-starter-validation'
核心原因为没有添加捕获校验失败的异常方法
在UserController类中加入捕获方法即可正常抛出错误校验
// controller类
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<String> handleValidationException(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
List<FieldError> errors = bindingResult.getFieldErrors();
StringBuilder errorMessage = new StringBuilder();
for (FieldError error : errors) {
errorMessage.append(error.getDefaultMessage()).append("; ");
}
return ResultUtil.error(errorMessage.toString());
}
这时大坑来了,每个控制器类写一段肯定不现实,要抽出来当全局方法,我在controller的同级下新建exception目录,写入GlobalExceptionHandler类
// exception目录下的全局方法
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<String> handleValidationException(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
List<FieldError> errors = bindingResult.getFieldErrors();
StringBuilder errorMessage = new StringBuilder();
for (FieldError error : errors) {
errorMessage.append(error.getDefaultMessage()).append("; ");
}
return ResultUtil.error(errorMessage.toString());
}
}
这样写后捕获异常就无法生效了,痛苦了许久,东找西找,最后在换注解的时候,发现是注解的问题,需要与controller上的注解相对应
我的UserController注解为@RestController,而捕获类的注解为@ControllerAdvice,导致了无法生效,改为@RestControllerAdvice注解即可
问题核心&&最佳实践
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<String> handleValidationException(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
List<FieldError> errors = bindingResult.getFieldErrors();
StringBuilder errorMessage = new StringBuilder();
for (FieldError error : errors) {
errorMessage.append(error.getDefaultMessage()).append("; ");
}
return ResultUtil.error(errorMessage.toString());
}
}
一壶茶,一包烟,一个异常修一天