Java异常通知案例如何拦截

wen java案例 21

本文目录导读:

Java异常通知案例如何拦截

  1. Spring Boot全局异常拦截(最常用)
  2. 使用AOP拦截异常
  3. 第三方通知集成示例
  4. 使用Filter统一拦截
  5. 配置优先级建议
  6. 最佳实践建议

在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

最佳实践建议

  1. 异常分类处理:区分业务异常和系统异常,不同处理方式
  2. 避免重复通知:相同异常短时间内只通知一次
  3. 异步通知:通知操作使用异步线程执行,不影响主业务
  4. 分级告警:按异常严重级别采用不同通知方式
  5. 通知去重:聚合相同异常,避免通知轰炸

这样实现的异常通知系统既能保证代码简洁,又能及时获取系统异常信息。

抱歉,评论功能暂时关闭!