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

目录
  • 一、背景
  • 二、需求
  • 三、技术实现
  • 四、代码实现
    • 1、编写xml日志文件
      • 2、编写QQ模块的代码
      • 3、编写login模块的代码
  • 五、运行结果
  • 六、完整代码
  • 七、一个小知识点
  • 总结

一、背景

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

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输出日志内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring动态代理实现日志功能详解

    代理模式(Proxy)是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能. 1.自定义业务接口 package com.haijiao12138.demo.spring.agentLog0815; /** * @author: haijiao12138 * @ClassName: BusinessClassService * @description: TODO * @date: 2021/8/15 14:33 */ public interfa

  • 使用spring拦截器实现日志管理实例

    使用HandlerInterceptor拦截器,可以拦截请求,实现通用的日志管理操作  一.添加拦截器类 在"src/main/java"代码文件夹的"org.xs.demo1"的包下新建"LogInterceptor.java"类: package org.xs.demo1; import java.text.SimpleDateFormat; import javax.servlet.http.HttpServletRequest; impo

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

    目录 一.背景 二.需求 三.技术实现 四.代码实现 1.编写xml日志文件 2.编写QQ模块的代码 3.编写login模块的代码 五.运行结果 六.完整代码 七.一个小知识点 总结 一.背景 在我们开发的过程中,可能存在如下情况: 1.有些时候我们需要调用第三方的接口,一般情况下,调用接口,我们都会记录请求的入参和响应的.如果我们自己系统的日志和第三方的日志混合到一个日志文件中,那么可能查找日志就比较麻烦了.那么我们是否可以将第三方系统的日志单独放到另外的文件中呢? 2.或者有些时候我们系统需

  • 在Spring Boot应用程序中使用Apache Kafka的方法步骤详解

    第1步:生成我们的项目: Spring Initializr来生成我们的项目.我们的项目将提供Spring MVC / Web支持和Apache Kafka支持. 第2步:发布/读取Kafka主题中的消息: <b>public</b> <b>class</b> User { <b>private</b> String name; <b>private</b> <b>int</b> age

  • Spring boot jpa 删除数据和事务管理的问题实例详解

    今天我们介绍的是jpa删除和事务的一些坑,接下来看看具体内容. 业务场景(这是一个在线考试系统)和代码:根据问题的id删除答案 repository层: int deleteByQuestionId(Integer questionId); service 层: public void deleteChoiceAnswerByQuestionId(Integer questionId) { choiceAnswerRepository.deleteByQuestionId(questionId)

  • Spring Boot 定制与优化内置的Tomcat容器实例详解

    1.Spring Boot 定制与优化内置Tomcat容器. > 内置的容器有三个分别是Undertow.Jetty.Tomcat,Spring Boot 对这三个容器分别进行了实现,它们上层接口都是EmbeddedServletContainerFactory,该接口也是本文的主要核心. 对于内置容器的定制与优化主要有两种方式,第一种方式是通过配置文件来配置,另外一种是通过码代码的方式.接下来主要对上述两种方式进行实现. 2.通过配置文件来定制与优化Tomcat > 配置的核心内容参考org

  • 对python模块中多个类的用法详解

    如下所示: import wuhan.wuhan11 class Han: def __init__(self, config): self.batch_size = config.batch_size self.num_steps = config.num_steps class config: batch_size = 10 num_steps = 50 if __name__ == '__main__': han = Han(config) print(han.batch_size) pr

  • 对Tensorflow中tensorboard日志的生成与显示详解

    TensorBoard是TensorFlow下的一个可视化的工具,能够帮助我们在训练大规模神经网络过程中出现的复杂且不好理解的运算.TensorBoard能展示你训练过程中绘制的图像.网络结构等. 1. 构建简单的TensorBoard日志输出 import tensorflow as tf input1 = tf.constant([1.0, 2.0, 3.0], name="input1") input2 = tf.Variable(tf.random_uniform([3], n

  • python os模块常用的29种方法使用详解

    os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 print(os.getcwd()) >>E:\pycharm\test os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cd os.chdir('E:\pycharm') print(os.getcwd()) >>E:\pycharm os.curdir 是一个值,返回当前目录: ('.') print(os.curdir) >>. os

  • Java日志框架之logback使用详解

    为什么使用logback 记得前几年工作的时候,公司使用的日志框架还是log4j,大约从16年中到现在,不管是我参与的别人已经搭建好的项目还是我自己主导的项目,日志框架基本都换成了logback,总结一下,logback大约有以下的一些优点: 内核重写.测试充分.初始化内存加载更小,这一切让logback性能和log4j相比有诸多倍的提升 logback非常自然地直接实现了slf4j,这个严格来说算不上优点,只是这样,再理解slf4j的前提下会很容易理解logback,也同时很容易用其他日志框架

  • Oracle 错误日志表及异常处理包详解 附源码

    1 概述 1. 目的:'快速定位程序异常' 2. 包处理的核心思想:'自治事务' -- 自治事务的 "提交.回滚" 与 主事务 之间互不影响 3. 错误异常记录逻辑大体一致,此处记录,方便需要使用时复制.粘贴 4. 验证思路:通过执行报错的过程,观察 '程序执行结果' 和 '日志表' 数据插入情况 2 效果演示 程序执行截图: 日志表查询截图: 3 源码 说明: 1. 测试中,共有 2 个用户 -- 模拟实际开发场景 (1) odsdata: 存放业务数据 (2) odscde : 执

  • Node.js基础入门之模块与npm包管理器使用详解

    目录 require函数 模块分类 第三方模块 1. 安装第三方模块 2. 引入第三方模块 3. 示例测试 系统模块 require注意事项 exports导出对象 1. exports示例 2. exports注意事项 module模块对象 package.json包描述文件 1. 什么是package.json ? 2. 如何创建package.json文件? NPM基础 1. 常用npm命令 2. npm 示例 cnpm基础 1. 什么是cnpm ? 2. 使用cnpm 控制台输出 1.

随机推荐