Spring Boot中統一日誌解決方案
阿新 • • 發佈:2018-12-14
日誌是整個系統中非常重要的一環,JAVA中也有很多日誌框架,本文實現了在Spring Boot中利用logback和aop統一處理日誌。本文比較簡單,已記錄為主O(∩_∩)O~
首先在resources目錄下新建logback-spring.xml作為logback的配置檔案:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <property name="LOG_HOME" value="/data/log" /> <!--<property name="LOG_HOME" value=" D:/data/log" />--> <!--寫入日誌到控制檯的appender,用預設的,但是要去掉charset,否則windows下tomcat下亂碼--> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> <!--格式化輸出:%d表示日期,%thread表示執行緒名,%-5level:級別從左顯示5個字元寬度%msg:日誌訊息,%n是換行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 滾動記錄檔案,先將日誌記錄到指定檔案,當符合某個條件時,將日誌記錄到其他檔案 --> <appender name="StackRollingFileAppender" class="ch.qos.logback.core.rolling.RollingFileAppender"> <File>${LOG_HOME}/vcash-order.log</File> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <FileNamePattern>${LOG_HOME}/vcash-order.%d{yyyy-MM-dd}.log</FileNamePattern> <!-- 最多儲存60day日誌檔案 --> <maxHistory>60</maxHistory> </rollingPolicy> <encoder> <Pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n</Pattern> </encoder> </appender> <springProfile name="dev"> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> <appender-ref ref="StackRollingFileAppender" /> </root> </springProfile> <springProfile name="test"> <root level="INFO"> <appender-ref ref="CONSOLE" /> <appender-ref ref="StackRollingFileAppender" /> </root> </springProfile> <springProfile name="prd"> <root level="INFO"> <appender-ref ref="StackRollingFileAppender" /> </root> </springProfile> </configuration>
可以看到,通過LOG_HOME這個property指定了日誌存放的路徑
通過springProfile指定了3種不同的環境,分別對應開發、測試和生產環境,在這裡面指定了日誌級別,並且引用了上面定義的兩個appender
新建一個註解@Log:
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
}
新建一個aspect類,在該類中處理日誌的記錄:
@Aspect @Component public class VBSAspect { private static final Logger log= LoggerFactory.getLogger(VBSAspect.class); @Pointcut("@annotation(com.vcash.wechat.annotation.Log)") public void logPointcut(){} @Around("logPointcut()") public Object logHandler(ProceedingJoinPoint process) throws Throwable{ long startTime=System.currentTimeMillis(); MethodSignature methodSignature= (MethodSignature) process.getSignature(); Method method=methodSignature.getMethod(); String methodName=method.getName(); String className= method.getDeclaringClass().getName(); Object[] args=process.getArgs(); StringBuilder params=new StringBuilder(); for (int i = 0; i < args.length; i++) { params.append(args[i].toString()); params.append(";"); } Object result= null; try { result = process.proceed(); } catch (Throwable throwable) { String exception=throwable.getClass()+":"+throwable.getMessage(); long costTime=System.currentTimeMillis()-startTime; log.error("請求時間:{},請求耗時:{},請求類名:{},請求方法:{},請求引數:{},請求結果:{}",startTime,costTime,className,methodName,params.toString(),exception); return CustomerResponse.buildFail(throwable.getMessage()); } long costTime=System.currentTimeMillis()-beginTime; log.info("請求時間:{},請求耗時:{},請求類名:{},請求方法:{},請求引數:{},請求結果:{}",startTime,costTime,className,methodName,params.toString(), result); return result; } }
可以看到,@Pointcut裡指定了需要切入的地方為註解@Log存在的地方,而@Log又是註解在方法上的,所以在logHandler方法裡,獲取了@Log所註解方法的一系列引數,比如方法名、入參、出參、耗時等,並將這些引數以特定的格式寫入日誌,當然,你也可以在這裡把日誌寫到資料庫。
以上,就完成了整個系統裡的日誌處理,484非常簡單~
再也不需要在每個類和方法裡都引入日誌程式碼,解耦了程式碼,方便了維護。