本文目录导读:

在Java中全局捕获异常主要有以下几种方式,下面按常见场景详细介绍:
Web应用全局异常处理(Spring Boot)
使用@ControllerAdvice + @ExceptionHandler
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理所有未捕获的异常
@ExceptionHandler(Exception.class)
public Result<String> handleException(Exception e) {
// 记录日志
log.error("系统异常", e);
return Result.error(500, "系统繁忙,请稍后重试");
}
// 处理特定异常
@ExceptionHandler(IllegalArgumentException.class)
public Result<String> handleIllegalArgument(IllegalArgumentException e) {
return Result.error(400, e.getMessage());
}
// 处理业务异常
@ExceptionHandler(BusinessException.class)
public Result<String> handleBusinessException(BusinessException e) {
return Result.error(e.getCode(), e.getMessage());
}
}
自定义业务异常
public class BusinessException extends RuntimeException {
private Integer code;
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
public Integer getCode() {
return code;
}
}
Java桌面应用全局异常捕获
使用UncaughtExceptionHandler
public class GlobalExceptionCatcher {
public static void main(String[] args) {
// 设置全局异常处理器
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
// 记录日志
System.err.println("线程 " + t.getName() + " 发生未捕获异常:");
e.printStackTrace();
// 显示友好提示
JOptionPane.showMessageDialog(null,
"程序发生异常,请检查日志文件",
"系统异常",
JOptionPane.ERROR_MESSAGE);
}
}
);
// 启动应用程序
SwingUtilities.invokeLater(() -> {
new MyApplication().start();
});
}
}
完整的Swing应用示例
public class SwingExceptionHandler {
public static void main(String[] args) {
// 1. 设置线程异常处理器
Thread.setDefaultUncaughtExceptionHandler(
(thread, throwable) -> handleException(throwable)
);
// 2. 设置AWT事件异常处理器
System.setProperty("sun.awt.exception.handler",
AWTExceptionHandler.class.getName());
// 3. 启动应用
EventQueue.invokeLater(() -> {
try {
new MyFrame().setVisible(true);
} catch (Exception e) {
handleException(e);
}
});
}
private static void handleException(Throwable e) {
// 记录异常到文件
try (FileWriter fw = new FileWriter("error.log", true);
PrintWriter pw = new PrintWriter(fw)) {
e.printStackTrace(pw);
} catch (IOException ex) {
ex.printStackTrace();
}
// 显示友好提示
JOptionPane.showMessageDialog(null,
"系统出现异常,请查看error.log文件了解详情",
"错误",
JOptionPane.ERROR_MESSAGE);
}
}
// AWT异常处理器
public class AWTExceptionHandler {
public void handle(Throwable throwable) {
SwingExceptionHandler.handleException(throwable);
}
}
多线程环境下的全局异常捕获
线程池异常处理
public class ThreadPoolExceptionHandler {
public static void main(String[] args) {
// 创建自定义线程工厂
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setUncaughtExceptionHandler((thread, throwable) -> {
System.err.println("线程 " + thread.getName() +
" 发生异常: " + throwable.getMessage());
}).build();
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(5, threadFactory);
// 或者直接设置
ThreadPoolExecutor pool = new ThreadPoolExecutor(
5, 10, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler(
(thread, throwable) -> {
System.err.println("异常处理: " +
throwable.getMessage());
}
);
return t;
}
}
);
}
}
CompletableFuture异常处理
public class CompletableFutureExceptionHandler {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture
.supplyAsync(() -> {
if (Math.random() > 0.5) {
throw new RuntimeException("异步任务异常");
}
return "成功";
})
.exceptionally(throwable -> {
System.err.println("捕获异常: " + throwable.getMessage());
return "默认值";
})
.handle((result, throwable) -> {
if (throwable != null) {
System.err.println("异常处理: " + throwable.getMessage());
return "处理异常";
}
return result;
});
}
}
Filter方式全局异常捕获(Web应用)
@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 (Exception e) {
// 全局异常处理
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
// 记录日志
log.error("请求 {} 发生异常", req.getRequestURI(), e);
// 返回统一错误响应
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().write(JSON.toJSONString(
Result.error(500, "系统异常")
));
}
}
}
最佳实践建议
组合使用多种捕获方式
@Configuration
public class ExceptionConfig {
// 1. 全局异常处理
@Bean
public GlobalExceptionHandler globalExceptionHandler() {
return new GlobalExceptionHandler();
}
// 2. 线程异常处理器
@PostConstruct
public void initThreadExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(
(thread, throwable) -> {
log.error("线程 [{}] 发生未捕获异常",
thread.getName(), throwable);
// 发送告警通知
alertService.sendAlert(throwable);
}
);
}
// 3. 自定义异常处理策略
@Bean
public ExceptionHandler exceptionHandler() {
return new SimpleMappingExceptionResolver() {{
setDefaultErrorView("error");
setExceptionAttribute("exception");
setDefaultStatusCode(500);
// 特定异常映射
setExceptionMappings(new Properties() {{
put("java.lang.IllegalArgumentException", "error-400");
put("com.example.BusinessException", "error-biz");
}});
}};
}
}
异常处理注意事项
- 不要过度捕获:只捕获确实需要全局处理的异常
- 区分异常类型:业务异常、系统异常、第三方异常应分开处理
- 保留原始异常:在包装异常时保留原始异常信息
- 日志记录:所有全局捕获的异常都要记录日志
- 友好提示:用户界面显示友好的错误信息,不要暴露技术细节
选择哪种方式取决于应用类型和需求,通常Web应用推荐使用@ControllerAdvice,桌面应用使用UncaughtExceptionHandler。