java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > java日志打印

java日志打印实现过程

作者:噢,我明白了

这段文章详细介绍了在SpringBoot项目中使用SLF4J和Logback进行日志管理的最佳实践,包括日志级别使用、代码中获取Logger对象的方法、日志配置技巧以及最佳实践和常见错误避免指南,帮助DK

前言

在 Java(特别是 Spring Boot)项目中,日志是排查问题、监控运行状态最重要的工具。

Spring Boot 默认集成了 SLF4J 作为日志门面,底层默认使用 Logback。你不需要额外引入依赖,直接使用即可。

一.核心概念:日志级别 (Level)

日志分为 5 个主要级别,严重程度从低到高:

级别关键含义使用场景
TRACEtrace最详细极少使用,用于追踪极细微的流程(如框架内部)
DEBUGdebug调试信息开发环境常用。打印变量值、SQL 语句、执行路径。生产环境通常关闭
INFOinfo一般信息生产环境默认级别。记录关键节点(如:启动成功、用户登录、订单创建)
WARNwarn警告潜在问题,但不影响系统运行(如:配置缺失使用默认值、重试机制触发)
ERRORerror错误严重错误,导致功能失败(如:数据库连接断开、空指针异常)。必须处理!

原则:生产环境通常只开启 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.区分级别:

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>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文