当前位置: 首页 > 后端技术 > Java

Spring根据业务模块将日志输出到不同的文件中

时间:2023-04-01 13:50:11 Java

一、背景在我们开发的过程中,可能会遇到以下几种情况:1、有时候我们需要调用第三方的接口。一般我们在调用接口的时候都会记录请求和响应的输入参数。如果我们自己的系统日志和第三方的日志混在一个日志文件里,找日志可能会比较麻烦。那么我们能不能把第三方系统的日志单独放到另外一个文件中呢?2.或者有时候我们的系统需要进行数据迁移。如果某条数据迁移失败,放在单独的日志文件里是不是更清楚?二、需求从上图可以看出我们的需求比较简单1、系统启动日志和登录模块日志记录在springboot-spring.log文件中。2、第三方业务(QQ)模块的日志记录在springboot-qq.log文件中。3、第三方业务(QQ)模块提供登录(loginName)方法。该方法的入参loginName需要记录在springboot-qqLoginName.log文件中,模拟1.后台提到的数据迁移失败,并将失败的数据记录到单独的日志文件中。三、技术实现1、这里使用的日志框架使用logback来完成日志记录,因为SpringBoot应用默认使用logback来记录日志。2.如果日志是通过模块和文件来记录的1.写appender,可以很容易的理解日志需要输出到哪里。例如:%d{yyyy-MM-ddHH:mm:ss.SSS}[${PID:-}][%thread]%-5level%logger{50}#%method:%L-%msg%nlogs/springboot-qq-%d{yyyy-MM-dd}-.%i.log2.如何实现模块输出日志这里我们需要配置记录器。logger的name属性赋值具体的全包名,然后直接引用我们上面定义的appender即可。配置logger,logger的名字是需要单独生成一个文件的包的全包名,然后引用定义的appender3多于。如果执行的话,其实logger就是用来输出loginName到指定文件的。logger的名字需要和LoggerFactory.getLogger("这里写具体logger的名字的值")一样。注意:这里可能有一个坑,就是类名可能会丢失。那我们怎么解决呢?可以通过MDC解决。....%X{CLASSNAME}#%method:%L-%msg%nMDC.put("CLASSNAME",QQService.class.getName());qqLoginName.info("登录用户:[{}]",登录名);即在xml中使用%X{CLASSNAME},在java代码中使用MDC存储CLASSNAME的值。四、代码实现1、写入xml日志文件1、写入appender1,输出日志到控制台%d{yyyy-MM-ddHH:mm:ss.SSS}[${PID:-}][%thread]%-5level%logger{50}#%method:%L-%msg%nUTF-82、写入登录模板的loglogs/springboot-spring-%d{yyyy-MM-dd}-.%i.log71MB2GB<编码器><模式>%d{yyyy-MM-ddHH:mm:ss.SSS}[${PID:-}][%线程]%-5level%logger{50}#%method:%L-%msg%nUTF-83.写qq模板的loglogs/springboot-qq-%d{yyyy-MM-dd}-.%i.log71MB2GB%d{yyyy-MM-ddHH:mm:ss.SSS}[${PID:-}][%thread]%-5level%logger{50}#%方法:%L-%msg%nUTF-84.将qq模块loginName输出的日志单独写入文件<appendername="qqLoginNameAppender"class="ch.qos.logback.core.rolling.RollingFileAppender">logs/springboot-qqLoginName-%d{yyyy-MM-dd}-.%i.log71MB2GB<编码器>%d{yyyy-MM-ddHH:mm:ss.SSS}[${PID:-}][%thread]%-5level%X{CLASSNAME}#%method:%L-%msg%nUTF-82.配置日志输出到特定位置1.配置登录模块登录模块属于我们自己的系统模块,这里使用根标签配置2.配置qq模块这里name的值直接指定为qq的全包名路径。3.配置loginName单独输出到一个文件2.编写QQ模块的代码@ComponentpublicclassQQService{privatestaticfinalLoggerlog=LoggerFactory.getLogger(QQService.class);//getLogger("qqLoginName")中的qqLoginName需要和logback-spring.xml中的loggername保持一致才可以申请privatestaticfinalLoggerqqLoginName=LoggerFactory.getLogger("qqLoginName");公共无效登录(字符串登录名){日志。info("QQ业务:用户:[{}]开始使用QQ登录系统",loginName);MDC.put("类名",QQService.class.getName());qqLoginName.info("登录用户:[{}]",loginName);}}3。编写登录模块的代码@RestControllerpublicclassLoginController{privatestaticfinalLoggerlog=LoggerFactory.getLogger(LoginController.class);@ResourceprivateQQServiceqqService;@GetMapping("login/{loginName}")publicStringlogin(@PathVariable("loginName")StringloginName){log.info("Ownbusiness:user:[{}]tologin",loginName);qqService.login(登录名);返回“确定”;}}五、运行结果可以看到得到我们预期的结果六、完整代码https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-logger-split-file七、一个小知识点在SpringBoot中,如果我们要覆盖默认的logback配置,推荐使用logback-spring.xml来配置。