编辑
2025-08-07
工具-Hutool
00

目录

Hutool ExceptionUtil工具使用说明
一、3 个核心功能,解决 80% 的异常处理痛点
1. 异常信息提取:精准定位问题根源
2. 异常类型判断:不用再写一堆 instanceof

Hutool ExceptionUtil工具使用说明

一、3 个核心功能,解决 80% 的异常处理痛点

1. 异常信息提取:精准定位问题根源

最烦的就是异常被层层包装,比如调用第三方接口时,IOException被包在ServiceException里,又被包在RuntimeException里,想找根因得一层层getCause()。

用 ExceptionUtil 的getCausedBy()一眼看穿: 

try { // 调用可能抛出多层异常的方法 thirdPartyService.syncData(); } catch (Exception e) { // 直接找到最底层的IOException Throwable rootCause = ExceptionUtil.getCausedBy(e, IOException.class); if (rootCause != null) { log.error("数据同步失败,根本原因:{}", rootCause.getMessage()); // 处理IO异常(比如重试) } } 

还有两个常用方法:

getMessage(e):获取完整异常信息(包括所有嵌套异常),日志里记这个准没错

stacktraceToString(e):把堆栈转成字符串,存数据库或日志文件特别方便

2. 异常类型判断:不用再写一堆 instanceof

判断异常类型时,传统写法得堆一堆instanceof: 

// 传统写法:又长又丑 catch (Exception e) { if (e instanceof IOException) { // 处理IO异常 } else if (e instanceof SQLException) { // 处理SQL异常 } else if (e instanceof TimeoutException) { // 处理超时异常 } }

用isCausedBy()一行搞定: 

catch (Exception e) { if (ExceptionUtil.isCausedBy(e, IOException.class)) { log.error("IO异常:{}", e.getMessage()); } else if (ExceptionUtil.isCausedBy(e, SQLException.class)) { log.error("数据库异常:{}", e.getMessage()); } }

3. 受检异常转运行时:告别 try-catch 嵌套地狱

Java 里的受检异常(比如IOException)必须用 try-catch 处理,有时候会导致代码嵌套得像千层饼: // 传统写法:受检异常逼你加try-catch public String readFile() {     try {         return Files.readString(Paths.get("config.properties"));     } catch (IOException e) {         throw new RuntimeException(e); // 手动包装成运行时异常     } } wrapRuntime()一键转换,连 Lambda 都支持: // 一行搞定,代码清爽多了 public String readFile() {     return ExceptionUtil.wrapRuntime(() ->          Files.readString(Paths.get("config.properties"))     ); } 二、3 个实战场景,看完直接能用

  1. Web 统一异常处理:给用户友好提示,日志记完整堆栈Controller 层用 ExceptionUtil 统一处理异常,既给用户返回友好信息,又在日志里保留完整堆栈: @RestControllerAdvice public class GlobalExceptionHandler {     @ExceptionHandler(Exception.class)     public Result handleException(Exception e) {         // 日志里记录完整堆栈,方便排查         log.error("请求异常:{}", ExceptionUtil.stacktraceToString(e));                  // 判断异常类型,返回对应提示         if (ExceptionUtil.isCausedBy(e, IllegalArgumentException.class)) {             return Result.fail(400, "参数错误:" + e.getMessage());         } else {             return Result.fail(500, "系统繁忙,请稍后再试");         }     } } 2. 分布式任务:异常堆栈存数据库,方便追溯定时任务或分布式任务失败时,用stacktraceToString()把堆栈存起来,后续排查问题有依据: @Scheduled(cron = "0 0 3 * * ?") public void backupData() {     try {         // 执行数据备份         dataBackupService.backup();     } catch (Exception e) {         // 堆栈转字符串存到日志表         String stackTrace = ExceptionUtil.stacktraceToString(e);         taskLogService.saveLog("backupData", "FAILED", stackTrace);                  // 发送告警         alertService.send("数据备份失败:" + e.getMessage());     } } 3. 第三方接口调用:精准捕获特定异常,针对性处理调用第三方接口时,经常会遇到各种异常,用getCausedBy()精准定位后针对性处理: public void callPaymentApi(PaymentRequest request) {     try {         thirdPartyPayment.call(request);     } catch (Exception e) {         // 提取底层异常         Throwable root = ExceptionUtil.getCausedBy(e);                  if (root instanceof ConnectException) {             // 网络连接异常,重试几次             retryCall(request);         } elseif (root instanceof TimeoutException) {             // 超时异常,记录到待处理队列             pendingQueue.add(request);         } else {             // 其他异常,直接告警             log.error("支付接口调用失败:{}", ExceptionUtil.getMessage(e));         }     } } 三、为什么说它比原生异常处理强 10 倍? 代码量锐减:一行wrapRuntime()替代一堆 try-catch,Lambda 支持更友好逻辑更清晰:isCausedBy()比一堆instanceof好懂多了,新人也能快速上手性能优化:支持静态异常和堆栈清除,高并发场景下减少内存占用(比如频繁抛出的已知异常,可清除堆栈节省资源)异常链透透透:不管异常被包了多少层,getCausedBy()总能找到根因,排查问题效率翻倍 四、最佳实践:这 3 招让异常处理更规范 日志记录要完整:用stacktraceToString()而不是e.getMessage(),避免关键信息丢失自定义异常结合用:配合 Hutool 的StatefulException(带状态码的异常),实现业务异常分层: // 自定义业务异常 public class OrderException extends StatefulException {     public OrderException(int code, String message) {         super(code, message);     } }

// 抛出时 if (order.getAmount() <= 0) {     throw new OrderException(400, "订单金额必须大于0"); } 封装全局异常工具:把常用操作封装成工具类,全项目统一用法: public class ExceptionHandlerUtil {     public static void logAndAlert(Exception e, String taskName) {         String stackTrace = ExceptionUtil.stacktraceToString(e);         log.error("{}失败:{}", taskName, stackTrace);         // 发送告警消息         messageService.sendToDingTalk("【" + taskName + "失败】" + e.getMessage());     } } 以前总觉得异常处理是个麻烦事,直到用了 Hutool 的 ExceptionUtil 才发现:原来几行代码就能把异常处理得既规范又高效。现在团队里的新人再也不用为 try-catch 怎么写纠结了,代码里的异常处理逻辑清爽了一大截。下次写异常处理时,别再堆 try-catch 了,试试 ExceptionUtil,你会回来感谢我的

本文作者:Allen Tang

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!