Spring Boot中日志管理与异常处理
以下是Spring Boot中日志管理与异常处理的系统化实践指南,结合最佳实践与核心配置,确保应用健壮性与可维护性。
📊 一、日志管理核心配置
-
默认框架与级别控制
- Logback 是Spring Boot默认日志框架,通过
application.yml
快速配置:logging:level:root: INFOcom.example.service: DEBUG # 包级自定义级别file:name: logs/app.log # 输出到文件
- 级别优先级:
TRACE < DEBUG < INFO < WARN < ERROR < FATAL
。
- Logback 是Spring Boot默认日志框架,通过
-
文件输出与轮转策略
- 基础配置:
logging.file.name
指定路径,logging.file.path
设置目录(默认生成spring.log
)。 - 高级轮转(通过
logback-spring.xml
):
支持按日期/大小归档,避免日志文件过大。<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>logs/app.log</file><rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"><fileNamePattern>logs/archived/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern><maxFileSize>500MB</maxFileSize> <!-- 按大小切割 --><maxHistory>30</maxHistory> <!-- 保留30天 --></rollingPolicy> </appender>
- 基础配置:
-
日志分组与环境适配
- 预定义分组:如
web
(Spring Web相关日志)、sql
(数据库操作日志)。logging:group:sql: org.hibernate.SQL, org.springframework.jdbclevel:sql: DEBUG
- 环境区分:在
logback-spring.xml
中使用<springProfile>
隔离开发/生产配置。
- 预定义分组:如
⚙️ 二、全局异常处理机制
-
分层异常处理策略
分层 异常处理规则 DAO层 不捕获异常,直接抛出(避免掩盖底层问题)。 Service层 抛出自定义 BusinessException
(继承RuntimeException
),确保事务回滚。Controller层 不处理异常,由全局处理器统一接管。 -
自定义异常设计
- 基类定义(支持错误码与消息):
public class BusinessException extends RuntimeException {private final int code; // 业务错误码public BusinessException(int code, String message) {super(message);this.code = code;} }
- 子类细化(如
UserNotFoundException
),增强可读性。
- 基类定义(支持错误码与消息):
-
全局异常处理器
使用@RestControllerAdvice
统一捕获并返回JSON错误信息:@RestControllerAdvice public class GlobalExceptionHandler {private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);// 处理业务异常@ExceptionHandler(BusinessException.class)public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {logger.warn("Business error: {}", ex.getMessage()); // WARN级别记录return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ErrorResponse(ex.getCode(), ex.getMessage()));}// 处理未预期异常@ExceptionHandler(Exception.class)public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception ex) {logger.error("System error: ", ex); // ERROR级别记录堆栈return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new ErrorResponse(500, "Internal Server Error"));} }
关键点:业务异常无需记录堆栈(
logger.warn
),系统异常需完整日志(logger.error
)。
🛠️ 三、日志与异常结合的最佳实践
-
上下文信息记录
- 在异常处理器中捕获请求详情(如参数、URL):
避免单纯打印@ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception ex, WebRequest request) {logger.error("Request URL: {}, Error: {}", request.getDescription(false), ex.getMessage(), ex);// ... }
ex.getMessage()
,需包含堆栈和请求数据。
- 在异常处理器中捕获请求详情(如参数、URL):
-
日志级别与异常匹配
ERROR
:未处理异常、系统级错误(如数据库连接失败)。WARN
:业务异常(如参数校验失败)。DEBUG
:开发期详细流程跟踪(生产环境关闭)。
-
占位符代替字符串拼接
使用{}
提升性能与可读性:logger.debug("User id={} not found", userId); // 正确✅ logger.debug("User id=" + userId + " not found"); // 避免❌
🔧 四、生产环境增强策略
-
集中化日志收集
- 集成ELK(Elasticsearch + Logstash + Kibana)或Syslog,聚合多实例日志。
- 日志格式标准化(JSON格式便于解析):
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/> <!-- 在logback中配置 -->
-
Dubbo等RPC框架异常处理
- 自定义
ExceptionFilter
放行自定义异常,避免被包装为RuntimeException
:
通过public class CustomExceptionFilter extends ExceptionFilter {@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) {Result result = invoker.invoke(invocation);if (result.getException() instanceof BusinessException) {return result; // 放行自定义异常}return super.invoke(invoker, invocation);} }
META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
文件注册过滤器。
- 自定义
-
健康检查与监控
- 通过Spring Boot Actuator暴露
/health
端点,结合日志分析系统(如Prometheus+Grafana)实时监控错误率。
- 通过Spring Boot Actuator暴露
💎 总结:关键原则
- 日志:按场景分级(开发用
DEBUG
,生产用INFO
+ERROR
),集中化管理。 - 异常:早抛出(Service层)、晚捕获(全局处理器),区分业务异常与系统错误。
- 工具链:
logback-spring.xml
定制日志策略,@RestControllerAdvice
统一异常响应。