Spring Boot 日志 配置 SLF4J 和 Logback

06-01 1099阅读

文章目录

  • 一、前言
  • 二、案例一:初识日志
  • 三、案例二:使用Lombok输出日志
  • 四、案例三:配置Logback

    一、前言

    在开发 Java 应用时,日志记录是不可或缺的一部分。日志可以记录应用的运行状态、错误信息和调试信息,帮助开发者快速定位和解决问题。Spring Boot 项目默认集成了 SLF4J 和 Logback,使得日志配置变得简单而灵活。本文将详细介绍如何在 Spring Boot 项目中配置 SLF4J 和 Logback,包括基本的日志配置、日志文件的输出路径、日志级别、日志格式和环境区分配置。

    日志的重要性

    1. 快速定位问题:通过分析日志,开发者可以迅速定位应用程序中的错误或性能问题。
    2. 确保合规性:许多行业要求应用程序符合特定标准,日志记录了应用程序的运行状态,便于审计和合规性检查。
    3. 提高开发效率:日志记录了应用程序的历史行为,有助于快速复现问题并优化代码。

    日志框架介绍

    Spring Boot 日志 配置 SLF4J 和 Logback

    门面模式(Facade Pattern)又称为外观模式

    门面模式(Facade Pattern)又称为外观模式, 提供了一个统⼀的接口, ⽤来访问⼦系统中的⼀群接口.

    其主要特征是定义了⼀个高层接口, 让子系统更容易使用。

    门面模式主要包含2种角色:

    1. 外观角色(Facade): 也称门面角色,系统对外的统⼀接口.
    2. 子系统角色(SubSystem): 可以同时有⼀个或多个 SubSystem. 每个 SubSytem 都不是⼀个单独的类,而是⼀个类的集合. SubSystem 并不知道 Facade 的存在, 对于 SubSystem 而言, Facade 只是另⼀个客户端而已(即 Facade 对 SubSystem 透明)

    比如去医院看病,可能要去挂号, 门诊, 化验, 取药, 让患者或患者家属觉得很复杂, 如果有提供接待人员, 只让接待⼈员来处理, 就很方便。

    Spring Boot 日志 配置 SLF4J 和 Logback

    日志级别分类

    1.Trace:

    最低级别的日志,追踪, 指明程序运行轨迹,比DEBUG更细粒度的信息事件(除非有特殊用意,否则请使用DEBUG级别替代)

    2.Debug

    详细调试信息,常用于调试过程中使用的调试信息

    3.Info

    一般信息或状态更新,常用于提供程序运行的基本信息

    4.Warning

    警告性信息,常用于提醒可能的问题或性能优化建议

    5.ERROR

    错误信息, 级别较高的错误日志信息, 但仍然不影响系统的继续运行。

    6.FATAL

    致命信息,表示需要立即被处理的系统级错误。

    Spring Boot 日志 配置 SLF4J 和 Logback

    二、案例一:初识日志

    1. 引入依赖

      Spring Boot 项目默认已经包含了 SLF4J 和 Logback 的依赖,如果你使用的是 Spring Initializr 初始化的项目,通常不需要额外添加依赖。如果你的项目中没有这些依赖,可以在pom.xml中添加如下依赖:

        org.springframework.boot
        >spring-boot-starter-logging
    
    
    1. 基本日志配置

    Spring Boot 允许通过application.yml或application.properties文件进行简单的日志配置。以下是一个基本的配置示例:

    注意:你需要改动日志监控包的位置,即com.example.yourpackage

    application.yml

    logging:
      level:
        root: INFO
        com.example.yourpackage: DEBUG  # 你的项目包路径
      file:
        name: application.log
      pattern:
        console: "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"
        file: "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"
    

    application.properties

    logging.level.root=INFO
    logging.level.com.example.yourpackage=DEBUG  # 你的项目包路径
    logging.file.name=application.log
    logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
    logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
    

    以上配置将日志级别设置为INFO,并为你的项目包设置为DEBUG级别。同时,设置了日志文件的名称和日志输出的格式。

    1. 日志的打印

    创建控制层类 LoggerController.java

    注意创建的日志对象,Logger和LoggerFactory类都是来自于Slf4j包底下的类。

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    @RequestMapping("/logger")
    public class LoggerController {
    	// 要想打印日志的前提是要有一个日志对象,日志对象来自于LoggerFactory类中  
    	// 创建日志对象
    	private Logger logger= LoggerFactory.getLogger(LoggerController.class);
    	//打印不同级别的日志
      
    	@RequestMapping("/log")
    	public String log(){
    		logger.info("====日志内容=====");
    		logger.trace("====日志内容=====");
    		logger.debug("====日志内容=====");
    		logger.error("====日志内容=====");
    		logger.warn("====日志内容=====");
    		return "打印日志";
    	}
    }
    

    代码运行结果:

    因本项目端口为9000

    故访问路径:http://localhost:9000/logger/log

    Spring Boot 日志 配置 SLF4J 和 Logback

    1. 日志持久化

    以上的日志都是输出在控制台上的, 然而在线上环境中, 我们需要把日志保存下来, 以便出现问题之后追溯问题. 把日志保存下来就叫持久化。

    日志持久化有两种方式:

    1. 配置日志文件名
    2. 配置日志的存储目录

    配置日志文件名:

    yml配置

    logging:
      file:
      # 在源目录下创建日志文件
        name: log/log.log
    

    Spring Boot 日志 配置 SLF4J 和 Logback

    配置日志的保存路径

    yml文件配置

    logging:
      file:
      #  日志在指定路径下面
        path: d/loggeController
    

    三、案例二:使用Lombok输出日志

    上面创建日志对象的方式还是比较麻烦的,如果程序中的类比较多的话,每个类都需要创建一个日志对象,就很繁琐,此时我们可以借助lombok中的**@Slf4j**注解来更简单的输出日志。

    @RestController
    @RequestMapping("/logger")
    @Slf4j
    public class LoggerController {
    	// @Slf4j 等同于
    	//	private Logger log= LoggerFactory.getLogger(LoggerController.class);
    	@RequestMapping("/log")
    	public String log(){
    		// 添加@Slf4j注解后,类会自动生成一个log对象
    		log.info("====日志内容=====");
    		log.trace("====日志内容=====");
    		log.debug("====日志内容=====");
    		log.error("====日志内容=====");
    		log.warn("====日志内容=====");
    		return "打印日志";
    	}
    }
    

    四、案例三:配置Logback

    Logback 是 SLF4J 的一个实现,提供了更强大的日志配置功能。你可以通过logback-spring.xml文件进行更详细的日志配置。以下是一个示例配置文件:

    1、logback-spring.xml

        
        
        
        
        
            
                %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
            
        
        
        
            ${LOG_FILE}
            
                
                ${LOG_PATH}/application-%d{yyyy-MM-dd}.log
                30  
            
            
                %d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
            
        
        
        
            
            
        
        
            
            
        
        
        
            
            
        
    
    

    2、环境区分配置

    在实际项目中,不同环境(如开发环境、测试环境、生产环境)的日志配置需求可能会有所不同。Spring Boot 支持多配置文件来区分不同环境。你可以在src/main/resources目录下创建多个配置文件,例如:

    • application-dev.yml:开发环境配置
    • application-test.yml:测试环境配置
    • application-prod.yml:生产环境配置

      application-dev.yml

      spring:
        config:
          activate:
            on-profile: dev
      logging:
        level:
          root: DEBUG
          com.example.yourpackage: DEBUG
        file:
          name: application-dev.log
        pattern:
          console: "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"
          file: "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"
      

      application-test.yml

      spring:
        config:
          activate:
            on-profile: test
      logging:
        level:
          root: INFO
          com.example.yourpackage: INFO
        file:
          name: application-test.log
        pattern:
          console: "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"
          file: "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"
      

      application-prod.yml

      spring:
        config:
          activate:
            on-profile: prod
      logging:
        level:
          root: WARN
          com.example.yourpackage: INFO
        file:
          path: /var/log/yourapp
          name: application-prod.log
        pattern:
          console: "%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"
          file: "%d{yyyy-MM-dd HH:mm:ss} %thread %-5level %logger{36} - %msg%n"
      

      启动应用时,可以通过命令行参数指定使用哪个配置文件:

      java -jar -Dspring.profiles.active=prod yourapp.jar
      

      3、日志文件路径权限

      确保 Spring Boot 应用在服务器上有写日志文件的权限。你可以通过以下命令检查和修改目录权限:

      # 检查目录权限
      ls -ld /var/log/yourapp
      # 修改目录权限
      sudo chown -R youruser:yourgroup /var/log/yourapp
      sudo chmod -R 755 /var/log/yourapp
      

      4、日志文件查看

      启动应用后,检查日志文件是否正确生成并记录了日志。你可以在服务器上使用以下命令查看日志文件:

      # 查看日志文件
      tail -f /var/log/yourapp/application-prod.log
      

      5、使用自定义拦截器

      如果你需要在日志中记录特定的信息,例如 SQL 执行时间,可以使用自定义拦截器。以下是一个示例拦截器:

      SqlTimingInterceptor.java

      package com.example.yourpackage.interceptor;
      import org.apache.ibatis.executor.Executor;
      import org.apache.ibatis.executor.statement.StatementHandler;
      import org.apache.ibatis.logging.Log;
      import org.apache.ibatis.logging.slf4j.Slf4jImpl;
      import org.apache.ibatis.plugin.*;
      import java.sql.Statement;
      import java.util.Properties;
      @Intercepts(@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}))
      public class SqlTimingInterceptor implements Interceptor {
          @Override
          public Object intercept(Invocation invocation) throws Throwable {
              long start = System.currentTimeMillis();
              try {
                  return invocation.proceed();
              } finally {
                  long end = System.currentTimeMillis();
                  long timeTaken = end - start;
                  StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
                  String sql = (String) SystemMetaObject.forObject(statementHandler).getValue("delegate.boundSql.sql");
                  Log log = Slf4jImpl.create(this.getClass());
                  log.debug("SQL: " + sql);
                  log.debug("执行时间: " + timeTaken + " ms");
              }
          }
          @Override
          public Object plugin(Object target) {
              return Plugin.wrap(target, this);
          }
          @Override
          public void setProperties(Properties properties) {
              // 可以设置一些自定义属性
          }
      }
      

      MyBatisConfig.java

      package com.example.yourpackage.config;
      import com.example.yourpackage.interceptor.SqlTimingInterceptor;
      import org.apache.ibatis.plugin.Interceptor;
      import org.apache.ibatis.session.SqlSessionFactory;
      import org.mybatis.spring.SqlSessionFactoryBean;
      import org.mybatis.spring.annotation.MapperScan;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
      import org.springframework.jdbc.datasource.DriverManagerDataSource;
      import javax.sql.DataSource;
      import java.util.Properties;
      @Configuration
      @MapperScan("com.example.yourpackage.mapper")
      public class MyBatisConfig {
          @Bean
          public DataSource dataSource() {
              DriverManagerDataSource dataSource = new DriverManagerDataSource();
              dataSource.setDriverClassName("org.postgresql.Driver");
              dataSource.setUrl("jdbc:postgresql://localhost:5432/yourdb");
              dataSource.setUsername("yourusername");
              dataSource.setPassword("yourpassword");
              return dataSource;
          }
          @Bean
          public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
              SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
              factoryBean.setDataSource(dataSource);
              factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
              // 注册拦截器
              SqlTimingInterceptor sqlTimingInterceptor = new SqlTimingInterceptor();
              Properties properties = new Properties();
              properties.setProperty("someProperty", "someValue"); // 根据需要设置拦截器属性
              sqlTimingInterceptor.setProperties(properties);
              factoryBean.setPlugins(new Interceptor[]{sqlTimingInterceptor});
              return factoryBean.getObject();
          }
      }
      
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码