SpringBoot实现日志系统的完整指南

 更新时间:2025年12月09日 08:48:52   作者:悟空码字  
没有日志系统,那就好比程序生病了,你问他哪不舒服,他只会回答我挂了,下面我们就来看看如何使用SpringBoot实现日志系统,让我们给SpringBoot程序配个贴心小秘书吧

日志系统是什么

想象一下,你的程序是个有点健忘的程序员同事(没错,就是那个总说“我本地是好的”的家伙)。日志系统就是给他配的贴身小秘书,每天拿着小本本记录:

  • 几点几分干了啥(时间戳)
  • 心里想什么(调试信息)
  • 今天工作顺利吗(INFO信息)
  • 出问题了(ERROR信息)
  • 救火啊要炸了(FATAL信息)

没有日志系统?那就好比程序生病了,你问他“哪不舒服?”,他只会回答“我挂了”。有了日志,他就能详细告诉你:“昨天下午3点,我在处理用户订单时,因为数据库连接断了,导致...”

好了,废话不多说,让我们给SpringBoot程序配个“贴心小秘书”!

第1步:SpringBoot的“天生丽质”

SpringBoot这家伙很贴心,已经内置了日志系统!就像你买手机,相机APP已经预装好了。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LogDemoController {
    
    // 创建日志记录器,就像给这个类配了个专属记者
    private static final Logger logger = LoggerFactory.getLogger(LogDemoController.class);
    
    @GetMapping("/hello")
    public String sayHello() {
        // 不同的日志级别,就像不同的说话语气
        logger.trace("这是最详细的跟踪信息 - 连我呼吸都要记录");
        logger.debug("调试信息 - 我在想:用户到底点了啥按钮?");
        logger.info("普通信息 - 用户访问了hello接口,一切正常");
        logger.warn("警告信息 - 内存有点高,像吃了太多内存的胖子");
        logger.error("错误信息 - 数据库连接失败!快来人啊!");
        
        // 还可以带参数,像填空一样
        String userName = "码农小张";
        int userId = 123;
        logger.info("用户 {} (ID: {}) 登录成功", userName, userId);
        
        return "Hello World! 快去控制台看日志吧!";
    }
    
    @GetMapping("/oops")
    public String makeMistake() {
        try {
            // 故意制造一个错误
            int result = 10 / 0;
            return "这行代码永远执行不到";
        } catch (Exception e) {
            // 记录异常信息,参数e会自动打印堆栈
            logger.error("数学老师没教好,除零错误了!", e);
            return "哎呀,出错了!详情请看日志";
        }
    }
}

第2步:配置文件 - 给秘书定规矩

application.yml(或application.properties)中配置。这是告诉小秘书:“哪些话要记,哪些话不用记,记在哪里...”

# application.yml - 日志系统的“规章制度”

# 第一部分:全局日志级别设置
logging:
  level:
    root: INFO  # 根日志级别:INFO及以上才记录
    com.example.demo: DEBUG  # 我们自己的包可以详细点
    org.springframework.web: WARN  # Spring的web包,只记录警告及以上
    
  # 第二部分:输出到哪里(控制台和文件都记)
  file:
    name: logs/myapp.log  # 日志文件路径
    max-size: 10MB  # 单个文件最大10MB,超过就切分
    max-history: 30  # 保留最近30天的日志
    
  # 第三部分:日志格式 - 给小秘书的"记录模板"
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
    
  # 第四部分:按包或类单独设置(精细化管理)
  group:
    web: org.springframework.web, org.springframework.security
    app: com.example.demo.controller, com.example.demo.service
    
  level:
    web: INFO
    app: DEBUG

# 如果你想用logback的详细配置(高级玩法)
# 在resources目录下创建logback-spring.xml

第3步:高级玩法 - 自定义日志配置

resources目录下创建logback-spring.xml,这是给小秘书的详细工作手册

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
    
    <!-- 控制台输出 - 给开发人员看的 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 彩色日志,让控制台不再单调! -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss} %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 按天滚动的文件输出 - 给运维人员看的 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/application.log</file>
        <!-- 每天一个文件,最多保存30天 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/application.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <timeBasedFileNamingAndTriggeringPolicy 
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    
    <!-- 错误日志单独文件 - 重要的事情说三遍,重要的错误单独记 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/error.log</file>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>90</maxHistory>  <!-- 错误日志保留更久 -->
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 不同环境的配置 -->
    <springProfile name="dev">
        <root level="INFO">
            <appender-ref ref="CONSOLE"/>
        </root>
        <logger name="com.example" level="DEBUG" additivity="false">
            <appender-ref ref="CONSOLE"/>
        </logger>
    </springProfile>
    
    <springProfile name="prod">
        <root level="WARN">
            <appender-ref ref="FILE"/>
            <appender-ref ref="ERROR_FILE"/>
        </root>
        <logger name="com.example" level="INFO" additivity="false">
            <appender-ref ref="FILE"/>
            <appender-ref ref="ERROR_FILE"/>
        </logger>
    </springProfile>
    
</configuration>

第4步:AOP实现方法日志 - 自动记录每个方法

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MethodLogAspect {
    
    private static final Logger logger = LoggerFactory.getLogger(MethodLogAspect.class);
    
    /**
     * 自动记录Controller层每个方法的执行情况
     * 就像给每个方法配了个贴身观察员
     */
    @Around("execution(* com.example.demo.controller..*.*(..))")
    public Object logControllerMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().toShortString();
        Object[] args = joinPoint.getArgs();
        
        long startTime = System.currentTimeMillis();
        logger.info("方法开始执行: {},参数: {}", methodName, args);
        
        try {
            Object result = joinPoint.proceed();
            long executionTime = System.currentTimeMillis() - startTime;
            
            logger.info("方法执行成功: {},耗时: {}ms,返回值: {}", 
                       methodName, executionTime, result);
            return result;
            
        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            logger.error("方法执行失败: {},耗时: {}ms,异常: {}", 
                        methodName, executionTime, e.getMessage(), e);
            throw e;
        }
    }
}

第5步:日志工具类 - 让日志更智能

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StopWatch;

/**
 * 日志工具类 - 给日志加点"智能"
 */
public class LogUtil {
    
    /**
     * 性能监控 - 记录代码块执行时间
     */
    public static <T> T monitorPerformance(Logger logger, String taskName, 
                                          Supplier<T> task) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        
        logger.info("开始执行: {}", taskName);
        
        try {
            T result = task.get();
            stopWatch.stop();
            
            logger.info("执行完成: {},耗时: {}ms", 
                       taskName, stopWatch.getTotalTimeMillis());
            return result;
            
        } catch (Exception e) {
            stopWatch.stop();
            logger.error("执行失败: {},耗时: {}ms,错误: {}", 
                        taskName, stopWatch.getTotalTimeMillis(), e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 业务日志 - 记录关键业务操作
     */
    public static void businessLog(Logger logger, String operation, 
                                  String userId, Object... details) {
        // 这里可以扩展,比如记录到数据库或发送到消息队列
        logger.info("业务操作 - 用户: {}, 操作: {}, 详情: {}", 
                   userId, operation, details);
    }
    
    // 使用示例
    public void exampleUsage() {
        Logger logger = LoggerFactory.getLogger(this.getClass());
        
        // 监控性能
        String result = monitorPerformance(logger, "计算用户报表", () -> {
            // 模拟耗时操作
            Thread.sleep(1000);
            return "报表数据";
        });
        
        // 记录业务日志
        businessLog(logger, "用户登录", "user123", "IP: 192.168.1.1", "设备: Chrome");
    }
}

第6步:与ELK等日志系统集成(高级玩法)

# application-prod.yml - 生产环境配置
logging:
  # 输出JSON格式,方便ELK采集
  pattern:
    console: '{"timestamp":"%d{yyyy-MM-dd HH:mm:ss.SSS}", "level":"%level", "thread":"%thread", "logger":"%logger", "message":"%msg", "exception":"%ex"}'
  
  # Logstash收集配置(如果需要)
  logstash:
    enabled: true
    host: localhost
    port: 5000

总结:日志系统的"生存指南"

经过这一番折腾,我们的SpringBoot程序终于有了一个称职的贴身秘书。让我们总结一下日志系统的几个关键点:

为什么要用日志系统

  • 故障排查:程序说“我挂了” → 日志说“3点15分数据库连接超时”
  • 性能分析:用户说“好卡” → 日志说“这个接口平均响应2.3秒”
  • 行为追踪:老板说“谁干的” → 日志说“用户admin在10点修改了配置”
  • 数据统计:产品说“有多少人用” → 日志说“今天有15234次访问”

最佳实践

  • 级别要分明:DEBUG用于开发,INFO用于日常,ERROR用于异常
  • 信息要详细:时间、线程、级别、类名、消息、异常,一个都不能少
  • 性能要注意:日志IO是性能杀手,异步日志是个好选择
  • 安全要牢记:密码、token等敏感信息别往日志里写

常见坑点

  • 日志太多:把DEBUG级别放到生产环境,日志文件瞬间爆炸
  • 日志太少:出问题时,日志里只有“出错了”,没有“为啥错”
  • 格式混乱:今天用JSON,明天用文本,后天ELK不认了
  • 忘记归档:日志文件把磁盘写满了,程序真挂了

最后

给你的日志系统起个名字吧!比如叫“小日志”、“程序记录仪”、“代码摄像头”。毕竟,它要陪你度过无数个排查BUG的不眠之夜,是你在茫茫代码海洋中的灯塔,是你在程序崩溃时的救命稻草

现在,去给你的SpringBoot程序配个“贴心小秘书”吧!当程序再次崩溃时,至少有人(日志)能告诉你:“亲,这次是因为...”

到此这篇关于SpringBoot实现日志系统的完整指南的文章就介绍到这了,更多相关SpringBoot日志系统内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java发邮件错误javax.net.ssl.SSLHandshakeException:No appropriate protocol问题及解决

    java发邮件错误javax.net.ssl.SSLHandshakeException:No appropr

    这篇文章主要介绍了java发邮件错误javax.net.ssl.SSLHandshakeException:No appropriate protocol问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2026-05-05
  • 一文详解Java属性为什么不能是is开头的boolean

    一文详解Java属性为什么不能是is开头的boolean

    在Java实体类定义中,boolean类型的属性命名常引发争议,阿里巴巴Java开发手册建议避免使用is作为布尔类型属性的前缀,原因在于当实体类被序列化或反序列化时,基于JavaBean规范的框架可能会移除或忽略is,导致不一致的字段名,文中介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • 浅谈spring boot 1.5.4 异常控制

    浅谈spring boot 1.5.4 异常控制

    下面小编就为大家带来一篇浅谈spring boot 1.5.4 异常控制。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Java基于swing实现的弹球游戏代码

    Java基于swing实现的弹球游戏代码

    这篇文章主要介绍了Java基于swing实现的弹球游戏代码,包含了窗体界面设计与游戏的逻辑功能处理,具有不错的参考借鉴价值,需要的朋友可以参考下
    2014-11-11
  • java前后端加密解密crypto-js的实现

    java前后端加密解密crypto-js的实现

    这篇文章主要介绍了java前后端加密解密crypto-js的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • eclipse中自动生成javadoc文档的方法

    eclipse中自动生成javadoc文档的方法

    这篇文章主要介绍了eclipse中自动生成javadoc文档的方法,是实用eclipse开发Java程序时非常实用的技巧,对于进行Java项目开发具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • java设置日期返回格式的4种方式小结

    java设置日期返回格式的4种方式小结

    这篇文章主要为大家详细介绍了java设置日期返回格式的4种方式,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-12-12
  • JAVA学习进阶篇之时间与日期相关类

    JAVA学习进阶篇之时间与日期相关类

    在日常的开发工作当中,我们经常需要用到日期相关的类,下面这篇文章主要给大家介绍了关于JAVA学习进阶篇之时间与日期相关类的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • JAVA开发环境搭建教程

    JAVA开发环境搭建教程

    这篇文章主要为大家详细介绍了JAVA开发环境搭建教程,配置JAVA开发环境,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • ArrayList和LinkedList区别及使用场景代码解析

    ArrayList和LinkedList区别及使用场景代码解析

    这篇文章主要介绍了ArrayList和LinkedList区别及使用场景代码解析,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01

最新评论