Spring MVC 中的 @Valid 注解可以用来验证提交的数据是否满足指定的规则和条件,但是如果数据不符,则需要抛出异常给前端。
下面是使用 @Valid 注解实现异常拦截的步骤:
-
在 Controller 的方法参数中添加注解 @Valid 和 BindingResult 对象。
-
编写数据验证规则,通常是在数据实体类中使用注解编写。
-
在 Controller 方法调用时,Spring MVC 会自动对提交的数据进行验证,如果不符配置要求,则会自动将错误信息封装成 BindingResult 对象,并将其作为参数传入 Controller 方法中。
-
在 Controller 方法中判断 BindingResult 对象中是否包含错误信息,如果包含,则可以将错误信息通过异常抛出给前端。
下面是使用 @Valid 注解抛出异常的示例:
- 新建一个数据实体类 User.java,其中包含用户名和密码两个属性。在类上加上注解 @Validated。
@Validated
public class User {
@NotEmpty(message = "用户名不能为空")
private String username;
@NotNull(message = "密码不能为空")
private String password;
// getter and setter
}
- 在 Controller 中添加一个方法来接收前端传来的 User 对象,验证是否符合规则。如果不符合,抛出异常。
@PostMapping("/")
@ResponseBody
public ResponseData createUser(@RequestBody @Valid User user, BindingResult result){
if(result.hasErrors()){
List<String> msgs = result.getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
throw new ApiException(ResponseCode.PARAMETER_ERROR, String.join(";", msgs));
}
// 保存用户数据
return new ResponseData();
}
在这个方法中,我们处理了参数 "user",并将其与注解 @Valid 一起使用,Spring MVC 会在处理该方法之前自动执行验证。然后通过 BindingResult 捕获验证结果,并判断是否有错误。如果有,则将错误返回给前端。
- 添加一个全局异常处理器来捕获抛出的异常并返回错误信息。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ApiException.class)
public ResponseData handleApiException(ApiException e) {
//将异常信息封装到 ResponseData 对象中,返回给前端
return new ResponseData(e.getCode(), e.getMessage());
}
@ExceptionHandler(Exception.class)
public ResponseData handleException(Exception e) {
//将异常信息封装到 ResponseData 对象中,返回给前端
return new ResponseData(ResponseCode.SERVER_ERROR);
}
}
在这个全局异常处理器中,我们使用 @RestControllerAdvice 注解来标注这是一个全局异常处理器,然后使用 @ExceptionHandler 注解来指定当某个类型的异常抛出时,应该调用处理它的方法。
下面是一个完整的示例代码:
@RestController
@RequestMapping("/user")
@Validated
public class UserController {
@PostMapping("/")
public void createUser(@RequestBody @Valid User user, BindingResult result) {
if (result.hasErrors()) {
List<String> msgs = result.getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
throw new ApiException(ResponseCode.PARAMETER_ERROR, String.join(";", msgs));
}
// 保存用户数据
}
}
@ControllerAdvice
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ApiException.class)
public ResponseData handleApiException(ApiException e) {
return new ResponseData(e.getCode(), e.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseData handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
List<String> msgs = e.getBindingResult().getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
return new ResponseData(ResponseCode.PARAMETER_ERROR, String.join(";", msgs));
}
@ExceptionHandler(Exception.class)
public ResponseData handleException(Exception e) {
return new ResponseData(ResponseCode.SERVER_ERROR);
}
}
@Data
public class User {
@NotBlank
private String username;
@NotNull
private String password;
}
@Data
public class ResponseData {
private int code;
private String message;
public ResponseData() {
code = ResponseCode.SUCCESS;
message = "成功";
}
public ResponseData(int code, String message) {
this.code = code;
this.message = message;
}
}
public class ApiException extends RuntimeException {
private int code;
public ApiException(int code, String message) {
super(message);
this.code = code;
}
public int getCode() {
return code;
}
}
public class ResponseCode {
public static final int SUCCESS = 0;
public static final int PARAMETER_ERROR = 1001;
public static final int SERVER_ERROR = 5001;
}
其中,用户实体类 User.java 包含了两个字段 username、password,并使用了 NotBlank、NotNull 等注解来限制它们的输入规则。Controller 中的 createUser() 方法使用了 @Valid 和 BindingResult 来实现验证和异常抛出。GlobalExceptionHandler 类中对不同类型的异常进行了处理,以及定义了异常代码。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringMvc @Valid如何抛出拦截异常 - Python技术站