本文目录导读:

在Java中实现异常通知(异常拦截)主要有以下几种常用方案,我为你整理了一个完整的案例参考:
Spring Boot全局异常拦截(最常用)
自定义异常类
// 自定义业务异常
public class BusinessException extends RuntimeException {
private Integer code;
private String message;
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
this.message = message;
}
// getter/setter
}
全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
// 处理自定义业务异常
@ExceptionHandler(BusinessException.class)
public Result handleBusinessException(BusinessException e) {
logger.warn("业务异常: {}", e.getMessage());
return Result.error(e.getCode(), e.getMessage());
}
// 处理参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidationException(MethodArgumentNotValidException e) {
String errorMsg = e.getBindingResult()
.getFieldErrors()
.stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(","));
return Result.error(400, errorMsg);
}
// 处理所有未捕获异常
@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
logger.error("系统异常: ", e);
// 发送异常通知(邮件、短信等)
sendErrorNotification(e);
return Result.error(500, "服务器内部错误");
}
private void sendErrorNotification(Exception e) {
// 实现邮件/钉钉/企业微信通知逻辑
System.out.println("【异常通知】" + e.getMessage());
}
}
统一响应体
public class Result {
private Integer code;
private String message;
private Object data;
public static Result error(Integer code, String message) {
Result r = new Result();
r.code = code;
r.message = message;
return r;
}
// 其他getter/setter
}
使用AOP拦截异常
@Aspect
@Component
public class ExceptionAspect {
@Around("@annotation(ExceptionHandler)")
public Object handleException(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (BusinessException e) {
// 自定义业务异常处理
return Result.error(e.getCode(), e.getMessage());
} catch (Exception e) {
// 记录日志
log.error("方法: {} 异常: {}", pjp.getSignature(), e.getMessage());
// 发送通知
sendNotification(e);
return Result.error(500, "系统异常,请稍后重试");
}
}
}
// 自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExceptionHandler {
}
第三方通知集成示例
邮件通知
@Component
public class EmailNotifier {
@Autowired
private JavaMailSender mailSender;
@Value("${admin.email}")
private String adminEmail;
public void sendExceptionEmail(Exception e) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(adminEmail);
message.setSubject("【系统异常】" + e.getClass().getSimpleName());
message.setText("异常信息: " + e.getMessage() +
"\n堆栈信息: " + getStackTraceAsString(e));
mailSender.send(message);
}
private String getStackTraceAsString(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return sw.toString();
}
}
钉钉机器人通知
@Component
public class DingTalkNotifier {
@Value("${dingtalk.webhook}")
private String webhookUrl;
public void sendDingTalkNotification(Exception e) {
String content = String.format(
"**系统异常通知**\n" +
"- 异常类型: %s\n" +
"- 异常信息: %s\n" +
"- 发生时间: %s\n" +
"- 堆栈: %s",
e.getClass().getSimpleName(),
e.getMessage(),
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
truncateStackTrace(e, 500)
);
RestTemplate restTemplate = new RestTemplate();
Map<String, Object> request = new HashMap<>();
request.put("msgtype", "markdown");
request.put("markdown", Map.of("title", "系统异常", "text", content));
restTemplate.postForEntity(webhookUrl, request, String.class);
}
}
使用Filter统一拦截
@Component
@WebFilter(urlPatterns = "/*")
public class ExceptionFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (Exception e) {
// 日志记录
log.error("Filter层异常: ", e);
// 发送通知
notificationService.sendException(e);
// 返回统一错误响应
HttpServletResponse resp = (HttpServletResponse) response;
resp.setContentType("application/json;charset=utf-8");
resp.getWriter().write(JSON.toJSONString(Result.error(500, "系统异常")));
}
}
}
配置优先级建议
# application.yml
exception:
notification:
enabled: true
types:
- email # 邮件通知
- dingtalk # 钉钉通知
# 忽略的异常类列表
ignore-exceptions:
- java.lang.IllegalArgumentException
- com.example.BusinessException
最佳实践建议
- 异常分类处理:区分业务异常和系统异常,不同处理方式
- 避免重复通知:相同异常短时间内只通知一次
- 异步通知:通知操作使用异步线程执行,不影响主业务
- 分级告警:按异常严重级别采用不同通知方式
- 通知去重:聚合相同异常,避免通知轰炸
这样实现的异常通知系统既能保证代码简洁,又能及时获取系统异常信息。