1. 程式人生 > >Spring Boot學習筆記(四)使用AOP整合log4j日誌

Spring Boot學習筆記(四)使用AOP整合log4j日誌

rsources下面建立log4j.properties 新增配置資訊

# LOG4J配置
log4j.rootCategory=INFO, stdout, file, errorfile                       //級別,控制檯,檔案,錯誤的日誌
log4j.category.com.yy=DEBUG, bootfile                                  //com.yy包底下所有產生的日誌都會給它一個檔案 my.log
log4j.logger.error=errorfile
 
# 控制檯輸出
log4j.appender.stdout
=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n # root日誌輸出 log4j.appender.file=org.apache.log4j.DailyRollingFileAppender //每天會產生一個日誌檔案 log4j.appender.file.file=logs/all.log log4j.appender.file.DatePattern
='.'yyyy-MM-dd //年月日的命名檔案 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n # error下的日誌輸出 log4j.appender.errorfile=org.apache.log4j.DailyRollingFileAppender log4j.appender.errorfile.file
=logs/error.log log4j.appender.errorfile.DatePattern='.'yyyy-MM-dd log4j.appender.errorfile.Threshold = ERROR log4j.appender.errorfile.layout=org.apache.log4j.PatternLayout log4j.appender.errorfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L - %m%n # com.newer下的日誌輸出 log4j.appender.bootfile=org.apache.log4j.DailyRollingFileAppender log4j.appender.bootfile.file=logs/my.log log4j.appender.bootfile.DatePattern='.'yyyy-MM-dd log4j.appender.bootfile.layout=org.apache.log4j.PatternLayout log4j.appender.bootfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %5p %c{1}:%L ---- %m%n

pom檔案新增依賴

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

寫切面類

package com.sc.Firstboot.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
 
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
/**
 * web請求日誌切面類---專門針對控制層,如誰被請求了,花了多少時間,請求傳送的引數,返回得值等
 * @author yy
 */
@Aspect     // 表示一個切面bean
@Component  // bean容器的元件註解。雖然放在contrller包裡,但它不是控制器。如果注入service,但我們又沒有放在service包裡
@Order(3)   // 有多個日誌時,ORDER可以定義切面的執行順序(數字越大,前置越後執行,後置越前執行)
public class Log{
 
    //定義日誌記錄器--獲取sl4j包下提供的logger
    Logger logger = LoggerFactory.getLogger(this.getClass());
    ThreadLocal<Long> startTime = new ThreadLocal<>();  //執行緒副本類去記錄各個執行緒的開始時間
 
    //定義切入點
    /*1、execution 表示式主體
      2、第1個* 表示返回值型別  *表示所有型別
      3、包名  com.*.*.controller下
      4、第4個* 類名,com.*.*.controller包下所有類
      5、第5個* 方法名,com.*.*.controller包下所有類所有方法
      6、(..) 表示方法引數,..表示任何引數
      */
    @Pointcut("execution(public * com.sc.Firstboot.controller.*.*.*(..))")
    public void weblog() {}
 
    @Before("weblog()")
    public void dobefore(JoinPoint joinPoint) {        //方法裡面注入連線點
        logger.info("前置通知:");                            //info ,debug ,warn ,erro四種級別,這裡我們注入info級別
        startTime.set(System.currentTimeMillis());
 
        //獲取servlet請求物件---因為這不是控制器,這裡不能注入HttpServletRequest,但springMVC本身提供ServletRequestAttributes可以拿到
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
 
        logger.info("url:" + request.getRequestURL().toString());         // 想那個url發的請求
        logger.info("請求方式:" + request.getMethod());
        logger.info("請求路徑:" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());   // 請求的是哪個類,哪個方法
        logger.info("請求人地址:" + request.getRemoteHost());     
        logger.info("請求人埠:" + request.getRemotePort());     
        logger.info("使用者:" + request.getRemoteUser());     
        logger.info("請求引數:" + Arrays.toString(joinPoint.getArgs()));     // 方法本傳了哪些引數
    }
 
    //方法的返回值注入給ret
    @AfterReturning(returning = "ret", pointcut = "weblog()")
    public void doafter(Object ret) {
        logger.info("後置通知:");
        logger.info("返回值:" + ret);       // 響應的內容---方法的返回值responseEntity
        logger.info("花費時間:" + ( System.currentTimeMillis()-startTime.get() ));
    }
}