java日志打印实现过程
作者:噢,我明白了
前言:
在 Java(特别是 Spring Boot)项目中,日志是排查问题、监控运行状态最重要的工具。
Spring Boot 默认集成了 SLF4J 作为日志门面,底层默认使用 Logback。你不需要额外引入依赖,直接使用即可。
一.核心概念:日志级别 (Level)
日志分为 5 个主要级别,严重程度从低到高:
| 级别 | 关键 | 含义 | 使用场景 |
|---|---|---|---|
| TRACE | trace | 最详细 | 极少使用,用于追踪极细微的流程(如框架内部) |
| DEBUG | debug | 调试信息 | 开发环境常用。打印变量值、SQL 语句、执行路径。生产环境通常关闭 |
| INFO | info | 一般信息 | 生产环境默认级别。记录关键节点(如:启动成功、用户登录、订单创建) |
| WARN | warn | 警告 | 潜在问题,但不影响系统运行(如:配置缺失使用默认值、重试机制触发) |
| ERROR | error | 错误 | 严重错误,导致功能失败(如:数据库连接断开、空指针异常)。必须处理! |
原则:生产环境通常只开启 INFO、WARN、ERROR,以节省磁盘空间和性能。
二. 如何在代码中使用?
第一步:获取 Logger 对象
在你的类中定义一个静态常量 log(或 logger)。
推荐写法(使用 Lombok 简化):
如果你已经引入了 Lombok,只需加一个注解 @Slf4j,无需手动创建 logger 对象。
package com.example.demo.service;
import lombok.extern.slf4j.Slf4j; // 👈 导入这个
import org.springframework.stereotype.Service;
@Slf4j // 👈 加上这个注解,Lombok 会自动生成 private static final Logger log = ...
@Service
public class UserService {
public void addUser(String name) {
// 直接使用 log 变量
log.info("开始添加用户: {}", name);
try {
// 业务逻辑...
log.debug("用户数据校验通过");
} catch (Exception e) {
// 捕获异常时,务必打印堆栈信息
log.error("添加用户失败, name={}", name, e);
}
}
}
传统写法(如果不使用 Lombok):
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserService {
// 手动创建 logger,参数通常是当前类的 Class 对象
private static final Logger log = LoggerFactory.getLogger(UserService.class);
public void addUser(String name) {
log.info("开始添加用户: {}", name);
}
}
第二步:打印日志
使用占位符 {} 来拼接字符串,不要使用 + 号拼接(性能更好,且避免空指针)。
// ✅ 正确写法:使用 {} 占位符
log.info("用户 ID: {}, 姓名: {}", userId, userName);
// 错误写法:使用 + 拼接(每次都要创建新字符串,浪费性能)
log.info("用户 ID: " + userId + ", 姓名: " + userName);
// ✅ 打印异常堆栈(重要!)
try {
// ...
} catch (Exception e) {
// 最后一个参数传 exception 对象,才会打印完整的堆栈轨迹
log.error("操作失败", e);
}
3. 如何配置日志? (application.yml)
logging:
level:
# 根日志级别(默认 INFO)
root: INFO
# 指定某个包的日志级别
# 开发时可以将自己的包设为 DEBUG,方便看 SQL 和细节
com.example.demo: DEBUG
# 查看 MyBatis-Plus 生成的 SQL 语句
com.baomidou.mybatisplus: DEBUG
# 查看 Hibernate/MyBatis 的 SQL 参数绑定(如果用了原生 MyBatis)
# org.mybatis: DEBUG
# 日志文件配置(可选,生产环境推荐写入文件)
file:
name: logs/demo.log # 日志文件路径
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"💡 查看 SQL 的技巧:
如果你想看到 MP 生成的完整 SQL 语句,将 com.baomidou.mybatisplus 或你的 Mapper 包级别设为 DEBUG 即可。
4. 最佳实践与避坑指南
✅ 要做的事:
1.使用占位符 {}:log.info(“Id: {}”, id)。
2.异常必须打印堆栈:log.error(“Msg”, exception),否则出了错你不知道哪一行代码崩了。
3.区分级别:
- 正常流程用 INFO。
- 预期内的非致命问题用 WARN。
- 程序崩溃用 ERROR。
- 调试细节用 DEBUG。
4.生产环境关闭 DEBUG:避免日志文件爆炸,拖慢系统速度。
❌ 不要做的事:
1.不要在循环里打印 INFO/DEBUG:
// ❌ 坏味道:如果列表有 10万条,日志文件会瞬间几个 G
for (User u : users) {
log.info("User: {}", u);
}
2.不要吞掉异常:
// ❌ 坏味道:出错了却什么都不打,后期排查如同大海捞针
catch (Exception e) {
// 空的 catch 块
}
// ❌ 坏味道:只打印消息,不打印堆栈
catch (Exception e) {
log.error("出错了:" + e.getMessage()); // 看不到是哪行代码错的
}
3.不要在生产环境打印敏感信息:
密码、身份证号、银行卡号等不要直接 log.info 打印出来,需脱敏处理。
5. 快速测试
你可以写一个简单的 Controller 测试一下:
package com.example.demo.controller;
import lombok.extern.slf4j.Slf4j; // 👈 导入 SLF4J 日志门面(Lombok 提供)
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j // 👈 自动生成 log 对象
@RestController // 👈 标记为 REST 控制器
public class TestController {
@GetMapping("/test/log")
public String testLog() {
log.trace("这是 TRACE 日志");
log.debug("这是 DEBUG 日志");
log.info("这是 INFO 日志");
log.warn("这是 WARN 日志");
log.error("这是 ERROR 日志");
return "日志已经打印,请查看控制台";
}
}
在test文件下建立测试TestControllerTest
路径位置如图:

package com.example.demo.controller;
import org.testng.annotations.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
@WebMvcTest(TestController.class) // 👈 只加载 TestController,不加载其他 Bean
public class TestControllerTest {
@Autowired
private MockMvc mockMvc; // 👈 模拟发送 HTTP 请求
@Test
void testLogEndpoint() throws Exception {
// 发送 GET 请求到 /log
mockMvc.perform(MockMvcRequestBuilders.get("/log"))
// 验证 HTTP 状态码是 200 OK
.andExpect(MockMvcResultMatchers.status().isOk())
// 验证返回内容包含预期字符串
.andExpect(MockMvcResultMatchers.content().string("日志已经打印,请查看控制台"));
}
}
访问 http://localhost:8080/test/log,观察 IDEA 控制台的输出颜色和内容。
打印结果:

注意:
当前测试可使用完整依赖文件内容:Desktop/demo/pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.12</version> <!-- ✅ 稳定版,避免兼容性问题 --> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>MyBatis-Plus CRUD Demo</description> <properties> <java.version>17</java.version> </properties> <dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- MyBatis-Plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <!-- ✅ 改为 3.5.7 或更高,这是支持 Spring Boot 3.2/3.3 的稳定版本 --> <version>3.5.7</version> </dependency> <!-- MySQL Driver --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <!-- Lombok (简化实体类) --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.34</version> <optional>true</optional> </dependency> <!-- Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.7</version> <exclusions> <!-- 👇 必须排除这个导致冲突的旧版依赖 --> <exclusion> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> </exclusion> </exclusions> </dependency> <!-- 👇 必须手动引入这个兼容 Spring Boot 3 的新版依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>3.0.3</version> <!-- 必须是 3.0.0 以上 --> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>RELEASE</version> <scope>compile</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
总结
- 注解:类上加 @Slf4j。 方法:log.info(), log.error()。
- 格式:用 {} 占位,别用 +。
- 异常:log.error(“msg”, e) 把异常对象传进去。
- 配置:在 application.yml 里调整logging.level。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
