往期精彩推薦html
SpringBoot系列(一)idea新建Springboot項目java
springBoot系列(三)配置文件詳解spring
SpringBoot系列(五)Mybatis整合完整詳細版springboot
SpringBoot系列(六)集成thymeleaf詳解版app
Springboot系列(七) 集成接口文檔swagger,使用,測試框架
SpringBoot系列(八)分分鐘學會Springboot多種解決跨域方式ide
SpringBoot系列(九)單,多文件上傳的正確姿式spring-boot
SpringBoot系列(十)優雅的處理統一異常處理與統一結果返回
SpringBoot系列(十一)攔截器與攔截器鏈的配置與使用詳解,你知道多少?
本文目錄
在咱們運行項目的時候,你會發現控制檯是有日誌打印的,這個日誌就是SpringBoot默認配置的日誌框架處理的。SpringBoot默認是運用logback+slf4j處理日誌,slf4j是抽象層,logback是實現層。
可是不一樣的框架可能會有不一樣日誌處理方式,若是咱們在SpringBoot中集成了不一樣的框架的話,是否是日誌的輸出也會混亂呢?很顯然,若是你有一點經驗的話,你會發現,只要你不修改SpringBoot的默認日誌配置,它的日誌輸出格式是不會變得。這是由於,在SpringBoot管理日誌的時候,它都將其餘框架的日誌經過一些中間包的形式將其餘的日誌抽象成了slf4j接口,而統一用logback的形式實現。
本文咱們來說講怎麼來配置日誌格式以及運用AOP+自定義註解簡化日誌的記錄。
SpringBoot中默認的日誌輸出級別是info,也就是說咱們日常在控制檯輸出的那些日誌都是info級別以及更高級別的日誌。咱們能夠本身定義日誌的輸出級別,通常有如下幾個級別:
trace,debug,info,warn,error //級別遞增
trace 是追蹤日誌,debug是調式日誌,info通常是自定義日誌或者是信息日誌,warn是警告日誌,error則是錯誤日誌。
可能這麼說你也不知道這個級別有什麼用,來看看這個代碼:
@RestController public class TestLogController { Logger logger = LoggerFactory.getLogger(TestLogController.class); @GetMapping("/testLog") public void testLog(){ logger.trace("這是trace級別的日誌"); logger.debug("這是debug級別的日誌"); logger.info("這是正常自定義日誌"); logger.warn("這是警告日誌"); logger.error("這是錯誤日誌"); } }
代碼說明:(上面的Logger包這裏是使用的org.slf4j.Logger)
首先咱們獲取一個日誌記錄器Logger對象,而後分別在代碼中記錄不一樣級別日誌的輸出。運行項目,而後訪問接口。
你會發現前面的trace日誌和debug日誌是不會輸出的,這你就知道了吧,不一樣等級的日誌有不一樣的功效,只會在特定的狀況下輸出。這時候咱們也能夠自定義日誌級別了,在配置文件(yml)
logging: level: com: example: demolog: debug
配置說明:
這是什麼意思呢?個人包名是com.example.demolog,因此說這個配置就是說配置日誌所在包的輸出級別,是否是很高級。這樣就能輸出debug日誌了。若是你想輸出trace日誌你就將等級設置爲trace就好了。
日誌輸出到控制檯查看起來不是很方便,怎麼辦?不要緊,SpringBoot中還能將日誌輸出到指定的文件中,yml,添加以下配置。
logging: file: path: /spring/test/
這個配置是說將日誌輸出到指定的目錄文件,而且會生成一個spring.log的日誌文件用來記錄日誌(若是你本身指定了文件名,它就會按照你本身設定的名字生成文件。),運行項目你就能直接看到生成的日誌所在,這個目錄若是你寫的和上面一致,那麼你的日誌文件就會在項目的運行根路徑,好比D盤,而後在D盤生成你寫的文件目錄/spring/test/,最後在文件目錄下面生成spring.log的日誌文件。這個路徑你也能夠直接寫絕對路徑(直接指定這個文件在那個盤,那個文件夾)。
file下面還有一個配置就是name屬性,
logging: file: name: test.log
這個是直接指定你的日誌的文件名稱,默認生成的位置是在項目所在的目錄,你也能夠本身寫絕對路徑配置日誌文件的位置,可是必須要本身設定文件的名稱。
file的name屬性和path屬性只能指定一個,若是兩個同時指定的話,只有name屬性會生效。
有時候你可能會以爲這個日誌的輸出格式太難看了,想本身定義一個日誌輸出格式,徹底ojbk!SpringBoot說:知足你,本身想怎麼玩就怎麼玩!
logging: pattern: console: "%d{yyyy-MM-dd HH:mm:ss}----- 這是全棧學習筆記 [%thread] %-5level %logger{50} - %msg%n" file: "%d{yyyy-MM-dd HH:mm:ss}----- 這是全棧學習筆記 [%thread] %-5level %logger{50} - %msg%n" # d表示日期時間, # %thread表示線程名, # %‐5level:級別從左顯示5個字符寬度 # %logger{50} 表示logger名字最長50個字符,不然按照句點分割。 # %msg:日誌消息, # %n是換行符
上面的配置分別定義了控制檯的日誌輸出格式與文件的日誌輸出格式,是否是很方便。輸出的格式大概就是這樣。
固然咱們還有一個更好的日誌配置,利用xml文件進行配置,一步到位就是這麼爽。
直接上xml文件的內容,建議將文件命名爲logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- scan:當此屬性設置爲true時,配置文件若是發生改變,將會被從新加載,默認值爲true。 scanPeriod:設置監測配置文件是否有修改的時間間隔,若是沒有給出時間單位,默認單位是毫秒當scan爲true時,此屬性生效。默認的時間間隔爲1分鐘。 debug:當此屬性設置爲true時,將打印出logback內部日誌信息,實時查看logback運行狀態。默認值爲false。 --> <configuration scan="false" scanPeriod="60 seconds" debug="false"> <!-- 定義日誌的根目錄 建議寫絕對路徑 若是不寫默認在項目運行的根路徑( D盤,C盤這種)--> <property name="LOG_HOME" value="D:/app/log" /> <!-- 定義日誌文件名稱 --> <property name="appName" value="testxml"></property> <!-- ch.qos.logback.core.ConsoleAppender 表示控制檯輸出 --> <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <!-- 日誌輸出格式: %d表示日期時間, %thread表示線程名, %-5level:級別從左顯示5個字符寬度 %logger{50} 表示logger名字最長50個字符,不然按照句點分割。 %msg:日誌消息, %n是換行符 --> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} --學習筆記--[%thread] %-5level %logger{50} - %msg%n</pattern> <!-- <springProfile name="dev">--> <!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} == 學習筆記 == [%thread] -–> %-5level %logger{50} - %msg%n</pattern>--> <!-- </springProfile>--> <!-- <springProfile name="prod">--> <!-- <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} ==學習筆記==[%thread] %-5level %logger{50} - %msg%n</pattern>--> <!-- </springProfile>--> <!-- 若是將這個文件的名字改爲logback-spring.xml 就可使用上面的功能, 上面的功能是說能夠根據不一樣的生產環境作不一樣的日誌打印 --> </layout> </appender> <!-- 滾動記錄文件,先將日誌記錄到指定文件,當符合某個條件時,將日誌記錄到其餘文件 --> <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <!-- 指定日誌文件的名稱 --> <file>${LOG_HOME}/${appName}.log</file> <!-- 當發生滾動時,決定 RollingFileAppender 的行爲,涉及文件移動和重命名 TimeBasedRollingPolicy: 最經常使用的滾動策略,它根據時間來制定滾動策略,既負責滾動也負責出發滾動。 --> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!-- 滾動時產生的文件的存放位置及文件名稱 %d{yyyy-MM-dd}:按天進行日誌滾動 %i:當文件大小超過maxFileSize時,按照i進行文件滾動 --> <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern> <!-- 可選節點,控制保留的歸檔文件的最大數量,超出數量就刪除舊文件。假設設置天天滾動, 且maxHistory是365,則只保存最近365天的文件,刪除以前的舊文件。注意,刪除舊文件是, 那些爲了歸檔而建立的目錄也會被刪除。 --> <MaxHistory>365</MaxHistory> <!-- 當日志文件超過maxFileSize指定的大小是,根據上面提到的%i進行日誌文件滾動 注意此處配置SizeBasedTriggeringPolicy是沒法實現按文件大小進行滾動的,必須配置timeBasedFileNamingAndTriggeringPolicy --> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>100MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <!-- 日誌輸出格式: --> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-5level ] [ %logger{50} : %line ] - %msg%n</pattern> </layout> </appender> <!-- logger主要用於存放日誌對象,也能夠定義日誌類型、級別 name:表示匹配的logger類型前綴,也就是包的前半部分 level:要記錄的日誌級別,包括 TRACE < DEBUG < INFO < WARN < ERROR additivity:做用在於children-logger是否使用 rootLogger配置的appender進行輸出, false:表示只用當前logger的appender-ref,true: 表示當前logger的appender-ref和rootLogger的appender-ref都有效 --> <!-- hibernate logger --> <logger name="com.example.demolog" level="debug" ></logger> <!-- Spring framework logger --> <logger name="org.springframework" level="debug" additivity="false"></logger> <!-- root與logger是父子關係,沒有特別定義則默認爲root,任何一個類只會和一個logger對應, 要麼是定義的logger,要麼是root,判斷的關鍵在於找到這個logger,而後判斷這個logger的appender和level。 --> <root level="info"> <appender-ref ref="stdout" /> <appender-ref ref="appLogAppender" /> </root> </configuration>
上面的xml配置文件配置就不細說了,裏面都有詳細的註釋說明。配置文件默認位置應該是直接放在resources下面,和yml,properties文件同級,固然你也能夠本身配置文件位置的。
logging config: classpath:static/logback.xml
這樣就將xml配置文件放在static路徑下面時能自動識別了。也能夠設置爲絕對路徑。
上面咱們建議將日誌文件設置爲logback-spring.xml,若是咱們的xml文件的名稱是logback.xml,它就會直接被日誌框架識別,若是你的xml文件是用logback-spring.xml命名,那麼他會被SpringBoot來識別並解析日誌配置,可使用SpringBoot的高級Profile功能。這個高級功能我在xml文件中有註釋說明。往上看。你也能夠去看Spring的官網,有詳細的配置說明。
引入aop依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
自定義註解,還不會註解的,看這裏,註解詳細介紹註解乾貨
@Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyLog { String value() default ""; }
自定義切面類:
@Aspect @Component public class LogAspect { private Logger logger = LoggerFactory.getLogger(LogAspect.class); @Pointcut("@annotation(com.example.demolog.annotation.MyLog)") public void myPointCut(){ //簽名,能夠理解成這個切入點的一個名稱 } @Before("myPointCut()") public void doBefore(JoinPoint joinPoint){ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //獲取url,請求方法,ip地址,類名以及方法名,參數 logger.info("url={},method={},ip={},class_method={},args={}", request.getRequestURI(),request.getMethod(),request.getRemoteAddr(),joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName(),joinPoint.getArgs()); } @AfterReturning(pointcut = "myPointCut()") public void printLog(JoinPoint joinPoint){ MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); MyLog myLog = method.getAnnotation(MyLog.class); String value = null; if (myLog!=null){ value = myLog.value(); } logger.info(new Date()+"-----"+value); } }
上面配置完成以後再去controller的方法之上添加一個自定義的 @Mylog註解
@GetMapping("/testLog") @MyLog("測試一個日誌") public void testLog(){ //和上面的一致 }
代碼說明:
@Aspect:標明這是一個切面類
@Component:標明這是一個bean
@Pointcut("@annotation(com.example.demolog.annotation.MyLog)") 定義切入點爲自定義的註解,也能夠是一個類或者是一個包,包的寫法以下:
@Pointcut("execution(public * com.example.demolog.*(..))")
上面的意思是切入點是 全部在com.example,demolog包下面的以public爲修飾,不限制返回值(*),不限制參數不限制名稱的類。
擴展知識:
而後咱們再來測試一下接口:localhost:8098/testLog
本期分享到此結束,總結一下下!
本文先講解SpringBoot的默認日誌配置,而後本身在配置文件配置日誌的輸出等級,輸出格式,將日誌輸出到文件中,而後經過xml文件來配置日誌。最後咱們引出了利用aop,簡化日誌的輸出,而且統一日誌的輸出格式。若是你以爲本文有用的話,點個贊吧!另外須要源碼的看下面。