下面是关于如何优雅地进行字段校验的 Spring Boot 攻略。
1. 配置实体类字段校验
首先,在实体类中使用 JSR303 验证为我们提供了强大的约束形式,可通过添加适当的注释来轻松验证诸如是否为空或字符串长度是否满足要求等逻辑。
例如,下面的实体类注释了一个用户名字段,这个字段不能为空,并且长度在 6 到 16 个字符之间:
@Data
public class UserDTO {
@NotBlank(message = "用户名不能为空!")
@Length(min = 6, max = 16, message = "用户名长度必须在 {min} 到 {max} 个字符之间!")
private String userName;
...
}
在控制器的方法中,可以通过添加 @Valid 注释来执行此实体类的验证:
@RestController
public class UserController {
@PostMapping("/user")
public String addUser(@Valid @RequestBody UserDTO userDTO) {
// 验证通过
return "success";
}
}
这样就可以通过 Spring Boot 自带的 Validator 实现实体类字段校验了,而我们只需添加注释即可。
2. 自定义全局异常处理
当字段校验不通过时,常规的处理方式是返回带有错误信息的 HTTP 响应。但是,Spring Boot 提供了全局异常处理机制,使我们能够更简洁地组织和捕获异常,并将异常信息转换为我们需要的格式并返回给客户端。以下是实现自定义全局异常处理的步骤:
2.1 实现自定义异常
首先,需要创建一个自定义异常类,该类应继承 RuntimeException。例如:
public class GlobalException extends RuntimeException {
private String message;
public GlobalException(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
2.2 实现 ControllerAdvice
创建一个 @ControllerAdvice 注释的类 FooExceptionHandler,并实现以下方法:
@ControllerAdvice
public class FooExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<?> handleConstraintViolationException(ConstraintViolationException e) {
List<String> msgList = new ArrayList<>();
e.getConstraintViolations().forEach(item -> {
msgList.add(item.getMessage());
});
String msg = StringUtils.join(msgList.toArray(), ",");
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(msg);
}
@ExceptionHandler(GlobalException.class)
public ResponseEntity<?> handleGlobalException(GlobalException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
}
其中,handleConstraintViolationException 方法捕获 JSR303 验证异常并将错误信息合并为一个消息返回给客户端。handleGlobalException 方法则用来捕获 GlobalException 异常并返回异常信息给客户端。
2.3 测试
编写测试方法进行测试,例如:
@RestController
public class FooController {
@RequestMapping("/foo")
public String foo(@RequestParam("bar") String bar) {
if (StringUtils.isBlank(bar)) {
throw new GlobalException("参数 bar 不可为空!");
}
return "success";
}
}
使用 Postman 等接口测试工具调用 /foo 接口,当bar参数为空时,会返回异常信息 Parameter 'bar' must not be empty。
示例
示例一
下面以创建一个添加用户的 API 接口为例进行演示。首先,我们通过给 UserDTO 实体类的 userName 字段添加注释来进行字段校验:
@Data
public class UserDTO {
@NotBlank(message = "用户名不能为空!")
@Length(min = 6, max = 16, message = "用户名长度必须在 {min} 到 {max} 个字符之间!")
private String userName;
...
}
然后,在创建用户的 Controller 方法 addUser 中添加 @Valid 注释,调用此方法时,Spring Boot 将自动执行 UserDTO 的验证:
@RestController
public class UserController {
@PostMapping("/user")
public String addUser(@Valid @RequestBody UserDTO userDTO) {
// 验证通过
return "success";
}
}
示例二
第二个示例将通过自定义全局异常处理来演示优雅的异常处理。
在演示中,将创建一个 /foo 请求,其参数 bar 必须存在,否则将会抛出 GlobalException 异常,然后 GlobalExceptionHandler 将捕获此异常并返回给客户端。以下是实现代码:
@ControllerAdvice
public class FooExceptionHandler {
@ExceptionHandler(GlobalException.class)
public ResponseEntity<?> handleGlobalException(GlobalException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
}
@RestController
public class FooController {
@RequestMapping("/foo")
public String foo(@RequestParam("bar") String bar) {
if (StringUtils.isBlank(bar)) {
throw new GlobalException("参数 bar 不可为空!");
}
return "success";
}
}
public class GlobalException extends RuntimeException {
private String message;
public GlobalException(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
}
在以上代码中,我们创建了一个 GlobalException 异常类,并在 FooController 的 foo 方法中抛出此异常。最后,我们使用 @ControllerAdvice 注释的全局异常处理器 FooExceptionHandler 捕获此异常并返回给客户端。
以上就是 Spring Boot 中优雅字段校验和异常处理的攻略,他们能够节省大量的代码处理时间,提高代码的可读性和可维护性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Springboot如何优雅地进行字段校验 - Python技术站