返回
SpringBoot:轻松搞定全局异常处理+错误码枚举+JSR303校验
后端
2022-12-11 12:40:54
SpringBoot实战:全局异常处理+错误码枚举+JSR303校验
1. 全局异常处理的必要性
在SpringBoot项目中,如果不进行全局异常处理,一旦业务层或控制器中发生异常,系统将直接抛出500错误页面,这对用户体验和项目维护都十分不利。
2. SpringBoot全局异常处理
为了解决上述问题,我们需要在SpringBoot项目中添加全局异常处理功能。具体步骤如下:
- 创建一个新的类来处理异常,如
GlobalExceptionHandler
:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleException(Exception ex, HttpServletRequest request) {
// 异常处理逻辑
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage());
}
}
- 在SpringBoot启动类上添加
@ControllerAdvice
注解并注册为Spring Bean:
@SpringBootApplication
@ControllerAdvice
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
3. 错误码枚举
在实际开发中,我们经常需要返回特定的错误码以标识不同的异常类型。因此,我们可以创建一个错误码枚举类,如ErrorCodeEnum
:
public enum ErrorCodeEnum {
PARAM_ERROR(1001, "参数错误"),
RESOURCE_NOT_FOUND(1002, "资源不存在"),
PERMISSION_DENIED(1003, "权限不足");
private int code;
private String message;
ErrorCodeEnum(int code, String message) {
this.code = code;
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
4. SpringBoot JSR303校验
SpringBoot支持JSR303校验,我们可以使用它来对请求参数进行校验。步骤如下:
- 在实体类上添加JSR303校验注解,如
@NotNull
、@Size
、@Pattern
等:
public class User {
@NotNull
private String name;
@Size(min = 6, max = 18)
private String password;
@Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+public class User {
@NotNull
private String name;
@Size(min = 6, max = 18)
private String password;
@Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")
private String email;
}
quot;)
private String email;
}
- 在控制器方法上添加
@Valid
注解,Spring会自动对请求参数进行校验:
@PostMapping("/register")
public String register(@Valid User user) {
// 处理注册逻辑
}
示例代码
// User.java
public class User {
@NotNull
private String name;
@Size(min = 6, max = 18)
private String password;
@Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+// User.java
public class User {
@NotNull
private String name;
@Size(min = 6, max = 18)
private String password;
@Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")
private String email;
}
// GlobalExceptionHandler.java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleException(Exception ex, HttpServletRequest request) {
if (ex instanceof BusinessException) {
BusinessException businessException = (BusinessException) ex;
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorCodeEnum.PARAM_ERROR);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ErrorCodeEnum.INTERNAL_SERVER_ERROR);
}
}
}
// UserController.java
@RestController
public class UserController {
@PostMapping("/register")
public String register(@Valid User user) {
// 处理注册逻辑
return "注册成功";
}
}
quot;)
private String email;
}
// GlobalExceptionHandler.java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleException(Exception ex, HttpServletRequest request) {
if (ex instanceof BusinessException) {
BusinessException businessException = (BusinessException) ex;
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorCodeEnum.PARAM_ERROR);
} else {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ErrorCodeEnum.INTERNAL_SERVER_ERROR);
}
}
}
// UserController.java
@RestController
public class UserController {
@PostMapping("/register")
public String register(@Valid User user) {
// 处理注册逻辑
return "注册成功";
}
}
结论
通过以上步骤,我们可以实现SpringBoot的全局异常处理、错误码枚举和JSR303校验功能。这可以有效提升系统稳定性和代码健壮性,同时也为后续维护和扩展提供良好的基础。
常见问题解答
- 为什么要使用错误码枚举?
错误码枚举可以统一管理错误类型,方便识别和处理不同的异常情况,提高代码的可读性和可维护性。
- JSR303校验的作用是什么?
JSR303校验可以帮助我们在请求参数校验阶段就发现问题,避免错误数据进入系统,从而提高数据的准确性和完整性。
- 全局异常处理可以捕获所有异常吗?
全局异常处理可以捕获大多数异常,但对于某些系统级异常(如内存溢出、栈溢出等)则无法捕获。
- 如何自定义错误信息?
可以在GlobalExceptionHandler
中根据异常类型返回不同的错误信息,也可以使用自定义的Exception
类抛出异常并返回自定义信息。
- 是否需要在所有控制器方法上都添加
@Valid
注解?
如果需要对控制器方法中的请求参数进行校验,则需要添加@Valid
注解。