本文目录导读:

我来详细介绍Java异常全局处理的几种主流实现方案。
Spring Boot 全局异常处理(推荐)
1 创建统一响应类
// 响应状态码枚举
public enum ResultCode {
SUCCESS(200, "成功"),
ERROR(500, "系统异常"),
BAD_REQUEST(400, "请求参数错误"),
UNAUTHORIZED(401, "未授权"),
FORBIDDEN(403, "权限不足"),
NOT_FOUND(404, "资源不存在");
private final int code;
private final String message;
// 构造方法、getter方法省略
}
// 统一响应类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {
private int code;
private String message;
private T data;
private long timestamp;
public static <T> Result<T> success(T data) {
return new Result<>(ResultCode.SUCCESS.getCode(),
ResultCode.SUCCESS.getMessage(),
data, System.currentTimeMillis());
}
public static <T> Result<T> error(ResultCode resultCode) {
return new Result<>(resultCode.getCode(),
resultCode.getMessage(),
null, System.currentTimeMillis());
}
public static <T> Result<T> error(int code, String message) {
return new Result<>(code, message, null, System.currentTimeMillis());
}
public static <T> Result<T> error(String message) {
return new Result<>(ResultCode.ERROR.getCode(),
message, null, System.currentTimeMillis());
}
}
2 自定义业务异常
// 业务异常类
@Getter
public class BusinessException extends RuntimeException {
private int code;
private String message;
public BusinessException(ResultCode resultCode) {
super(resultCode.getMessage());
this.code = resultCode.getCode();
this.message = resultCode.getMessage();
}
public BusinessException(int code, String message) {
super(message);
this.code = code;
this.message = message;
}
public BusinessException(String message) {
super(message);
this.code = ResultCode.ERROR.getCode();
this.message = message;
}
}
// 参数校验异常
public class ParamValidateException extends RuntimeException {
private final String field;
private final String message;
public ParamValidateException(String field, String message) {
super(message);
this.field = field;
this.message = message;
}
// getter方法省略
}
3 全局异常处理器
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 处理业务异常
*/
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.OK)
public Result<?> handleBusinessException(BusinessException e) {
log.error("业务异常:code={}, message={}", e.getCode(), e.getMessage());
return Result.error(e.getCode(), e.getMessage());
}
/**
* 处理参数校验异常
*/
@ExceptionHandler(ParamValidateException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<?> handleParamValidateException(ParamValidateException e) {
log.error("参数校验异常:field={}, message={}", e.getField(), e.getMessage());
return Result.error(ResultCode.BAD_REQUEST.getCode(), e.getMessage());
}
/**
* 处理参数绑定异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<?> handleValidationException(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
Map<String, String> errors = new HashMap<>();
bindingResult.getFieldErrors().forEach(error ->
errors.put(error.getField(), error.getDefaultMessage())
);
log.error("参数校验失败:{}", errors);
return Result.error(ResultCode.BAD_REQUEST.getCode(),
"参数校验失败:" + errors.toString());
}
/**
* 处理HTTP请求方法不支持
*/
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
@ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
public Result<?> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e) {
log.error("请求方法不支持:{}", e.getMessage());
return Result.error(405, "请求方法不支持:" + e.getMessage());
}
/**
* 处理资源找不到
*/
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Result<?> handleNoHandlerFound(NoHandlerFoundException e) {
log.error("资源不存在:{}", e.getMessage());
return Result.error(ResultCode.NOT_FOUND.getCode(), "请求的资源不存在");
}
/**
* 处理参数类型不匹配
*/
@ExceptionHandler(TypeMismatchException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<?> handleTypeMismatch(TypeMismatchException e) {
log.error("参数类型不匹配:{}", e.getMessage());
return Result.error(ResultCode.BAD_REQUEST.getCode(),
"参数类型不匹配:" + e.getPropertyName());
}
/**
* 处理缺失请求参数
*/
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Result<?> handleMissingParam(MissingServletRequestParameterException e) {
log.error("缺少必要参数:{}", e.getParameterName());
return Result.error(ResultCode.BAD_REQUEST.getCode(),
"缺少必要参数:" + e.getParameterName());
}
/**
* 处理未知异常
*/
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Result<?> handleException(Exception e, HttpServletRequest request) {
log.error("系统异常:uri={}, message={}", request.getRequestURI(), e.getMessage(), e);
return Result.error(ResultCode.ERROR.getCode(), "系统繁忙,请稍后重试");
}
}
使用示例
1 控制器中使用
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {
@PostMapping("/register")
public Result<UserVO> register(@Valid @RequestBody RegisterDTO registerDTO) {
// 业务逻辑
if (userService.existsByUsername(registerDTO.getUsername())) {
throw new BusinessException(400, "用户名已存在");
}
UserVO userVO = userService.register(registerDTO);
return Result.success(userVO);
}
@GetMapping("/{id}")
public Result<UserVO> getUser(@PathVariable Long id) {
if (id == null || id <= 0) {
throw new ParamValidateException("id", "用户ID无效");
}
UserVO userVO = userService.getUserById(id);
if (userVO == null) {
throw new BusinessException(ResultCode.NOT_FOUND);
}
return Result.success(userVO);
}
}
// 请求DTO
@Data
public class RegisterDTO {
@NotBlank(message = "用户名不能为空")
@Size(min = 3, max = 50, message = "用户名长度要在3-50之间")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度要在6-20之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
}
Java原生Web应用(非Spring)
1 Filter方式
@WebFilter("/*")
public class ExceptionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (BusinessException e) {
handleException(response, e.getCode(), e.getMessage());
} catch (Exception e) {
log.error("系统异常", e);
handleException(response, 500, "系统内部错误");
}
}
private void handleException(ServletResponse response, int code, String message)
throws IOException {
response.setContentType("application/json;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write(JSON.toJSONString(Result.error(code, message)));
writer.flush();
writer.close();
}
}
高级配置
1 配置文件
# application.yml
spring:
mvc:
throw-exception-if-no-handler-found: true
resources:
add-mappings: false
# 自定义异常配置
exception:
include-stacktrace: never
log-level: ERROR
2 配置类
@Configuration
public class ExceptionConfig {
@Bean
public FilterRegistrationBean<ExceptionFilter> exceptionFilterRegistration() {
FilterRegistrationBean<ExceptionFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new ExceptionFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1);
return registration;
}
}
测试类
@SpringBootTest
@AutoConfigureMockMvc
public class GlobalExceptionHandlerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testBusinessException() throws Exception {
mockMvc.perform(get("/api/users/999"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(404))
.andExpect(jsonPath("$.message").value("资源不存在"));
}
@Test
public void testValidationException() throws Exception {
String invalidUser = "{\"username\":\"\",\"password\":\"123\"}";
mockMvc.perform(post("/api/users/register")
.contentType(MediaType.APPLICATION_JSON)
.content(invalidUser))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value(400));
}
}
最佳实践建议
- 区分异常类型:业务异常、系统异常、参数异常分别处理
- 日志记录:不同级别异常记录不同日志
- 安全考虑:生产环境隐藏详细错误信息
- 国际化:支持多语言错误消息
- 监控告警:关键异常告警通知
这样的全局异常处理方案可以统一错误响应格式,提高代码的可维护性和用户体验。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播