Exception异常处理实战案例

📅 2026/7/31 17:08:04 👁️ 阅读次数 📝 编程学习
Exception异常处理实战案例

Java Exception 异常处理实战案例(生产级)
本文基于 Spring Boot 3.x + JDK 17+ 环境,覆盖日常开发中 90% 以上的异常处理场景,包含错误写法 vs 正确写法对比、最佳实践和生产级完整方案。

一、异常处理核心原则(先记牢)

  • 不要吞异常:catch 块不能为空,至少要打印日志
  • 异常要带上下文:必须包含触发异常的参数、业务 ID 等关键信息
  • 分层处理:Controller 层统一返回格式,Service 层抛出业务异常,DAO 层不处理异常
  • 区分异常类型:业务异常(用户可理解)vs 系统异常(开发需排查)
  • 资源必须释放:使用 try-with-resources 自动关闭流、连接等资源

二、基础场景实战

场景 1:资源释放(最容易踩坑)

错误写法(资源泄漏)

// 问题:如果 read() 抛出异常,inputStream 永远不会关闭publicStringreadFile(Stringpath)throwsIOException{FileInputStreaminputStream=newFileInputStream(path);byte[]buffer=newbyte[1024];intlen=inputStream.read(buffer);inputStream.close();// 异常时执行不到returnnewString(buffer,0,len);}

正确写法(try-with-resources)

// 所有实现 AutoCloseable 接口的类都可以用(流、连接、Socket 等)publicStringreadFile(Stringpath)throwsIOException{try(FileInputStreaminputStream=newFileInputStream(path)){byte[]buffer=newbyte[1024];intlen=inputStream.read(buffer);returnnewString(buffer,0,len);}// 自动关闭资源,无论是否抛出异常}

场景 2:不要吞异常

错误写法(最致命的错误)

// 问题:异常被完全吞掉,出问题时根本不知道哪里错了publicvoidupdateUser(Useruser){try{userMapper.updateById(user);}catch(Exceptione){// 空 catch 块,什么都不做}}

正确写法(至少打印日志 + 保留异常链)

importlombok.extern.slf4j.Slf4j;@Slf4jpublicclassUserService{publicvoidupdateUser(Useruser){try{userMapper.updateById(user);}catch(Exceptione){// 必须打印异常堆栈 + 关键参数log.error("更新用户失败,用户 ID:{}",user.getId(),e);// 或者向上抛出异常thrownewRuntimeException("更新用户失败",e);}}}

场景 3:异常信息要带上下文

错误写法(信息不足,无法排查)

// 问题:只打印 "查询失败",不知道查什么、参数是什么publicUsergetUserById(Longid){try{returnuserMapper.selectById(id);}catch(Exceptione){log.error("查询失败",e);thrownewRuntimeException("查询失败");}}

正确写法(包含关键业务参数)

publicUsergetUserById(Longid){try{Useruser=userMapper.selectById(id