Spring如何按业务模块输出日志到不同的文件详解

 更新时间:2022年05月06日 16:29:50   作者:huan1993  
最近做项目时有一个记录操作日志的需求,比如某个用户进行了查询、删除、修改等操作,下面这篇文章主要给大家介绍了关于Spring如何按业务模块输出日志到不同文件的相关资料,需要的朋友可以参考下

一、背景

在我们开发的过程中,可能存在如下情况:

1、有些时候我们需要调用第三方的接口,一般情况下,调用接口,我们都会记录请求的入参和响应的。如果我们自己系统的日志和第三方的日志混合到一个日志文件中,那么可能查找日志就比较麻烦了。那么我们是否可以将第三方系统的日志单独放到另外的文件中呢?

2、或者有些时候我们系统需要进行数据迁移,如果某条数据迁移失败了,是否单独放到一个日志文件中比较清晰呢?

二、需求

从上图中可以看到我们的需求比较简单

1、系统启动日志和 login 模块日志记录到 springboot-spring.log 文件中。

2、第三方业务(QQ)模块的日志记录到 springboot-qq.log文件中。

3、第三方业务(QQ)模块提供了一个login(loginName)方法,方法的入参loginName需要记录到springboot-qqLoginName.log文件中,模拟一、背景中提到的数据迁移失败,记录失败的数据到单独的日志文件中。

三、技术实现

1、采用的日志框架

此处使用logback来完成日志的记录,因为SpringBoot应用程序默认的就是采用的logback来记录日志。

2、如果实现分模块、分文件记录日志1、 编写appender,这个可以简单的理解日志需要输出到哪里。

比如:

<!-- 此处定义的日志输出到控制台 -->
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>

    </encoder>
</appender>

<!-- 此处定义日志输出到 springboot-qq-日期.第几个.log 文件中 -->
<appender name="qqAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>logs/springboot-qq-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
    </rollingPolicy>
   
</appender>

2、如何实现模块输出日志

此处就需要我们来配置 logger了。logger的name属性指定到具体的全包名,然后引用我们上面定义的appender即可。

<!-- 在QQ这个包下的日志单独使用 qqAppender 来输出 -->
<logger name="com.huan.springboot.qq" level="info" additivity="false">
    <appender-ref ref="qqAppender"/>
    <appender-ref ref="stdout"/>
</logger>

配置logger,logger的name为需要单独生成文件的那个包的全包名,然后在里面引用上面定义的appender

3、如果实现将loginName输出到指定的文件

其实还是使用 logger 来实现,logger的name需要和 LoggerFactory.getLogger("此处写具体logger的name的值")

注意:

此处可能有一个坑,就是可能会丢失类名,那么我们如何进行解决呢?可以通过MDC来解决。

.... %X{CLASSNAME}#%method:%L -%msg%n
MDC.put("CLASSNAME", QQService.class.getName());
qqLoginName.info("登录用户:[{}]", loginName);

即xml中使用%X{CLASSNAME},在java代码中使用MDC存入CLASSNAME的值。

四、代码实现

1、编写xml日志文件

1、编写appender

1、输出日志到控制台

<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
        <charset>UTF-8</charset>
    </encoder>
</appender>

2、编写login模板的日志

<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/springboot-spring-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <maxFileSize>1MB</maxFileSize>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

3、编写qq模板的日志

<appender name="qqAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/springboot-qq-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <maxFileSize>1MB</maxFileSize>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %logger{50}#%method:%L -%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

4、编写qq模块loginName单独输出到文件的日志

<appender name="qqLoginNameAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>logs/springboot-qqLoginName-%d{yyyy-MM-dd}-.%i.log</fileNamePattern>
            <maxHistory>7</maxHistory>
            <maxFileSize>1MB</maxFileSize>
            <totalSizeCap>2GB</totalSizeCap>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [${PID:- }] [%thread] %-5level %X{CLASSNAME}#%method:%L -%msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

2、配置日志输出到具体位置

1、配置login模块

<root level="INFO">
    <appender-ref ref="stdout"/>
    <appender-ref ref="file"/>
</root>

login模块属于我们自己的系统模块,此处使用 root标签来配置。

2、配置qq模块

<!-- 在QQ这个包下的日志单独使用 qqAppender 来输出 -->
<logger name="com.huan.springboot.qq" level="info" additivity="false">
    <appender-ref ref="qqAppender"/>
    <appender-ref ref="stdout"/>
</logger>

此处name的值直接指定到了qq的全包名路径。

3、配置loginName单独输出到文

<!-- 将所有的QQ登录名防止在另外的文件中 -->
<logger name="qqLoginName" level="info" additivity="false">
    <appender-ref ref="qqLoginNameAppender"/>
    <appender-ref ref="stdout"/>
</logger>

2、编写QQ模块的代码

@Component
public class QQService {

    private static final Logger log = LoggerFactory.getLogger(QQService.class);

    // getLogger("qqLoginName") 里的 qqLoginName 需要和 logback-spring.xml 中 logger的name一致,才会应用
    private static final Logger qqLoginName = LoggerFactory.getLogger("qqLoginName");

    public void login(String loginName) {
        log.info("QQ业务: 用户:[{}]开始使用QQ来登录系统", loginName);

        MDC.put("CLASSNAME", QQService.class.getName());
        qqLoginName.info("登录用户:[{}]", loginName);
    }
}

3、编写login模块的代码

@RestController
public class LoginController {

    private static final Logger log = LoggerFactory.getLogger(LoginController.class);

    @Resource
    private QQService qqService;

    @GetMapping("login/{loginName}")
    public String login(@PathVariable("loginName") String loginName) {
        log.info("自己业务:用户:[{}]进行登录", loginName);
        qqService.login(loginName);
        return "ok";
    }
}

五、运行结果

可以看到得到了我们期望的结果。

六、完整代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-logger-split-file

七、一个小知识点

在SpringBoot中,如果我们要覆盖默认的logback配置,推荐使用logback-spring.xml来配置。

总结

到此这篇关于Spring如何按业务模块输出日志到不同文件的文章就介绍到这了,更多相关Spring输出日志内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • ThreadLocal简介_动力节点Java学院整理

    ThreadLocal简介_动力节点Java学院整理

    这篇文章主要为大家详细介绍了ThreadLocal简介的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • Java的super关键字与instanceof运算符使用方法

    Java的super关键字与instanceof运算符使用方法

    这篇文章主要介绍了Java的super关键字与instanceof运算符使用方法,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • Java 基础详解(泛型、集合、IO、反射)

    Java 基础详解(泛型、集合、IO、反射)

    下面小编就为大家带来一篇Java 基础详解(泛型、集合、IO、反射)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • Spring入门配置和DL依赖注入实现图解

    Spring入门配置和DL依赖注入实现图解

    这篇文章主要介绍了Spring入门配置和DL依赖注入实现图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • 详解Java比较器

    详解Java比较器

    这篇文章主要介绍了Java比较器的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • SpringBoot使用邮箱发送验证码实现注册功能

    SpringBoot使用邮箱发送验证码实现注册功能

    这篇文章主要为大家详细介绍了SpringBoot使用邮箱发送验证码实现注册功能实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • Java枚举使用方法详解

    Java枚举使用方法详解

    这篇文章主要为大家详细介绍了Java枚举的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • java模拟多线程http请求代码分享

    java模拟多线程http请求代码分享

    本篇文章给大家分享了java模拟多线程http请求的相关实例代码,对此有需要的可以跟着测试下。
    2018-05-05
  • Spring中@Autowired和@Qualifier注解的3个知识点小结

    Spring中@Autowired和@Qualifier注解的3个知识点小结

    这篇文章主要介绍了Spring中@Autowired和@Qualifier注解的3个知识点小结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Maven项目修改JDK版本全过程

    Maven项目修改JDK版本全过程

    这篇文章主要介绍了Maven项目修改JDK版本全过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03

最新评论