1. 程式人生 > >Spring Boot中統一日誌解決方案

Spring Boot中統一日誌解決方案

日誌是整個系統中非常重要的一環,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非常簡單~
再也不需要在每個類和方法裡都引入日誌程式碼,解耦了程式碼,方便了維護。