核心内容摘要
体验心动与温柔:女性向ASMR之夜,解锁“071silk”的丝滑触感
视频看了几百小时还迷糊关注我几分钟让你秒懂发点评论可以给博主加热度哦
真实痛点为什么你的日志总被骂“不专业”用System.out.println(用户登录了)打日志线上出问题日志里全是debug信息关键错误却找不到想关掉某个类的日志结果整个系统日志都没了日志格式乱七八糟没法用 ELK 分析根本原因你还在用“原始人方式”打日志而没用SLF4J Logback这套工业级日志方案
什么是 SLF4J一句话讲透SLF4JSimple Logging Facade for Java不是日志实现而是一个“日志门面”它让你的代码只依赖接口底层可以随时切换 Logback、Log4j、Java Util Logging 等实现零侵入、高灵活就像 JDBC 驱动你写Connection conn DriverManager.getConnection(...)底层可以是 MySQL、Oracle、PostgreSQL 驱动换数据库只需改配置代码一行不动SLF4J 就是日志界的“JDBC”
手把手实战在 Spring Boot 中正确使用 SLF4J第一步确认依赖Spring Boot 默认已集成!-- spring-boot-starter-web 已包含 spring-boot-starter-logging -- !-- 而它默认引入了SLF4J Logback -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId /dependency✅ 无需额外引入直接用即可。
第二步在业务类中声明 LoggerService public class UserService { //
声明 Logger固定写法 private static final Logger log LoggerFactory.getLogger(UserService.class); public User register(String phone, String name) { //
使用不同级别打日志 log.info(开始注册用户手机号: {}, phone); // ←←← 关键用 {} 占位符 if (phone null || phone.isEmpty()) { log.warn(注册失败手机号为空name{}, name); throw new IllegalArgumentException(手机号不能为空); } try { // 模拟保存 User user new User(phone, name); log.debug(用户对象创建成功: id{}, name{}, user.getId(), user.getName()); return user; } catch (Exception e) { //
记录异常不要用 printStackTrace log.error(注册用户时发生异常phone{}, phone, e); // ←←← 异常放最后 throw new RuntimeException(注册失败, e); } } }✅关键点用LoggerFactory.getLogger(当前类.class)永远用{}占位符不要字符串拼接性能安全异常对象作为最后一个参数传入。
反例警告这些写法你一定犯过❌ 反例 1用System.out.printlnSystem.out.println(用户注册成功: user.getName()); // ❌问题无法关闭线上不能有 stdout没有时间、类名、线程等上下文无法按级别过滤。
❌ 反例 2字符串拼接性能杀手log.info(用户 name 注册成功ID id); // ❌ 即使 debug 关闭也会拼接字符串✅ 正确写法log.info(用户 {} 注册成功ID{}, name, id); // ✅ 只有 info 级别开启时才格式化原理SLF4J 在关闭日志级别时会跳过字符串拼接极大提升性能❌ 反例 3异常打印错误try { ... } catch (Exception e) { log.error(出错了); // ❌ 没有堆栈 e.printStackTrace(); // ❌ 输出到 stderr和日志文件分离 }✅ 正确写法log.error(处理订单时失败orderId{}, orderId, e); // ✅ 堆栈自动记录
日志级别详解何时用哪个级别使用场景是否记录到生产日志trace最详细如 SQL 参数❌ 通常关闭debug调试信息如方法入参❌ 开发/测试开生产关info重要业务流程如“用户注册”、“支付成功”✅ 必须开warn警告如“配置未设置使用默认值”✅ 开error错误如“数据库连接失败”✅ 必须开黄金法则生产环境只开info及以上敏感信息密码、身份证绝不能打日志
高级技巧让日志更强大1️⃣ 动态调整日志级别无需重启在application.yml中配置logging: level: com.example.service.UserService: debug # 单独开启 UserService 的 debug org.springframework.web: warn # 降低 Spring Web 日志级别✅ 适合线上临时排查问题2️⃣ 自定义日志格式适配 ELKlogging: pattern: console: %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n file: %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} : %msg%n效果
15:45:22 [http-nio-8080-exec-1] INFO c.e.s.UserService - 开始注册用户手机号: 13800138000✅ 字段清晰方便日志系统解析3️⃣ MDC为日志添加上下文如 traceIdRestController public class UserController { PostMapping(/register) public String register(RequestBody User user) { // 添加 traceId 到日志上下文 MDC.put(traceId, UUID.randomUUID().toString()); try { userService.register(user.getPhone(), user.getName()); return success; } finally { MDC.clear(); // 清理避免内存泄漏 } } }然后在日志格式中加入%X{traceId}logging: pattern: console: %d [%thread] %-5level [%X{traceId}] %logger - %msg%n输出
15:45:22 [http-n... ] INFO [a1b2c3d4] c.e.s.UserService - 开始注册...✅ 全链路追踪必备
SLF4J 与 Logback 的关系组件角色SLF4J门面接口你代码中调用的log.info()Logback具体实现Spring Boot 默认的日志框架spring-boot-starter-logging自动集成 SLF4J Logback 如果你想换 Log4j2只需排除spring-boot-starter-logging引入spring-boot-starter-log4j2你的业务代码一行都不用改
完整 Spring Boot 示例Service public class OrderService { private static final Logger log LoggerFactory.getLogger(OrderService.class); public void processOrder(Long orderId) { log.info(开始处理订单orderId{}, orderId); if (orderId null) { log.warn(订单ID为空拒绝处理); return; } try { // 业务逻辑 log.debug(订单校验通过准备扣库存...); // ... log.info(订单 {} 处理成功, orderId); } catch (Exception e) { log.error(处理订单 {} 时发生异常, orderId, e); throw e; } } }配合application.ymllogging: level: com.example.service.OrderService: debug pattern: console: %d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} : %msg%n
九、