Spring如何按業(yè)務模塊輸出日志到不同的文件詳解
一、背景
在我們開發(fā)的過程中,可能存在如下情況:
1、有些時候我們需要調用第三方的接口,一般情況下,調用接口,我們都會記錄請求的入參和響應的。如果我們自己系統(tǒng)的日志和第三方的日志混合到一個日志文件中,那么可能查找日志就比較麻煩了。那么我們是否可以將第三方系統(tǒng)的日志單獨放到另外的文件中呢?
2、或者有些時候我們系統(tǒng)需要進行數據遷移,如果某條數據遷移失敗了,是否單獨放到一個日志文件中比較清晰呢?
二、需求

從上圖中可以看到我們的需求比較簡單
1、系統(tǒng)啟動日志和 login 模塊日志記錄到 springboot-spring.log 文件中。
2、第三方業(yè)務(QQ)模塊的日志記錄到 springboot-qq.log文件中。
3、第三方業(yè)務(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模塊屬于我們自己的系統(tǒng)模塊,此處使用 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業(yè)務: 用戶:[{}]開始使用QQ來登錄系統(tǒng)", 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("自己業(yè)務:用戶:[{}]進行登錄", 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如何按業(yè)務模塊輸出日志到不同文件的文章就介紹到這了,更多相關Spring輸出日志內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java中Connection timed out和Connection refused的區(qū)別講解
今天小編就為大家分享一篇關于Java中Connection timed out和Connection refused的區(qū)別講解,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-04-04
Spring Boot中使用Spring-data-jpa的配置方法詳解
今天小編就為大家分享一篇關于Spring Boot中使用Spring-data-jpa的配置方法詳解,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03

