1. 程式人生 > >Spring Boot日誌和AOP註解

Spring Boot日誌和AOP註解

Spring Boot日誌和AOP註解

Spring Boot日誌

整合logback需要新增spring-boot-starter-logging依賴,而此依賴已經在spring-boot-starter中預設集成了,所以不用再新增此依賴了。預設情況下,Spring Boot會用Logback來記錄日誌,並用INFO級別輸出到控制檯

logging常用配置

在這裡插入圖片描述
預設情況下,Spring Boot將日誌輸出到控制檯,不會寫到日誌檔案。如果要將日誌寫入檔案,則需在application.properties中設定logging.file或logging.path屬性。logging.file,設定日誌檔案,可以是絕對路徑,也可以是相對路徑。logging.path,設定日誌所在的目錄,會在該目錄下建立spring.log檔案,並寫入日誌內容。注意:二者不能同時使用,如若同時使用,則只有logging.file生效

預設情況下,日誌檔案的大小達到10MB時會切分一次,產生新的日誌檔案, 如果要修改大小可以通過logging.file.max-size來配置,單位為MB,logback預設的日誌級別為INFO,如果需要修改可以通過配置logging.level.包語法來配置, 包即可以是一個包名也支援全限定路徑包.類,如logging.level.com.example.demo.dao=DEBUG, logging.level.包屬性可以配置多個,可以為每個包進行單獨設定日誌級別,這種方式能夠控制每個包的輸出日誌級別, 也可以設定root的日誌級別logging.level.root=INFO

多環境日誌配置

在application.properties中配置公共的日誌配置, 開發測試配置相應的值,生產配置相應的值,使用spring.profiles.active

自定義日誌

在Spring Boot中可即可以通過在application.properties中配置日誌,也可以使用傳統的配置檔案(logback.xml)的方式來配置, 在spring boot中配置檔名字既可以是logback.xml也可以是logback-spring.xml,Spring推薦使用已logback-spring.xml, 使用logback-spring.xml可以使用多環境日誌輸出springProfile,當然配置檔案的名稱也可以是自定義的,自定義的名稱需要在application.properties中使用logging.config配置對應的名字,如:logging.config=classpath:logback-config.xml, 配置檔案的位置放在src/main/resources下面
logback-spring.xml:
在這裡插入圖片描述


根節點configuration
scan:當此屬性設定為true時,配置檔案如果發生改變,將會被重新載入,預設值為true
scanPeriod:設定監測配置檔案是否有修改的時間間隔,如果沒有給出時間單位,預設單位是毫秒。當scan為true時,此屬性生效。預設的時間間隔為1分鐘
debug:當此屬性設定為true時,將打印出logback內部日誌資訊,實時檢視logback執行狀態。預設值為false
contextName:每個logger都關聯到logger上下文,預設上下文名稱為“default”。但可以使用設定成其他名字,用於區分不同應用程式的記錄。一旦設定,不能修改,可以通過%contextName來引用日誌上下文名稱
property:用來定義變數值的標籤,通過定義的值會被插入到logger上下文中。定義變數後,可以使“${}”來使用變數

在這裡插入圖片描述
appender:用來格式化日誌輸出節點,有倆個屬性name和class,class用來指定哪種輸出策略,常用就是控制檯輸出策略和檔案輸出策略。ThresholdFilter為系統定義的攔截器,例如我們用ThresholdFilter來過濾掉ERROR級別以下的日誌不輸出到檔案中。另一種常見的日誌輸出到檔案,隨著應用的執行時間越來越長,日誌也會增長的越來越多,將他們輸出到同一個檔案並非一個好辦法。RollingFileAppender用於切分檔案日誌

  • rollingPolicy class:
    • TimeBasedRollingPolicy 根據時間來分割日誌檔案,每天生成一個,這樣可能某一天日誌檔案很大,某天日誌檔案會很小,每天的日誌檔案的大小不固定
    • SizeBasedTriggeringPolicy: 根據檔案大小來分割,每達到maxFileSize就分割出來一個檔案
    • SizeAndTimeBasedRollingPolicy: 同時按照每天和大小來分割日誌檔案, 這種方式pattern中必須包含%d和%i
  • fileNamePattern: 定義分隔的日誌檔案的名稱規則
  • maxHistory:表示只保留最近N天的日誌,以防止日誌填滿整個磁碟空間
  • totalSizeCap: 指定日誌檔案的上限大小,例如設定為1GB的話,那麼到了這個值,就會刪除舊的日誌

在這裡插入圖片描述

  • root:用來指定最基礎的日誌輸出級別,只有一個level屬性,用來設定列印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,可以包含零個或多個元素,標識這個appender將會新增到這個logger

  • logger:用來設定某一個包或者具體的某一個類的日誌列印級別、以及指定appender

    • name:用來指定受此logger約束的某一個包或者具體的某一個類。
    • level:用來設定列印級別,大小寫無關:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF;如果未設定此屬性,那麼當前logger將會繼承上級的級別,所謂像上級傳遞就是是否使用root的配置
    • addtivity:是否向上級logger傳遞列印資訊。預設是true

當使用mybatis時,sql語句是debug下才會列印,而這裡我們只配置了info,所以想要檢視sql語句的話,有以下兩種操作:

  • 第一種把 改成 這樣就會列印sql,不過這樣日誌那邊會出現很多其他訊息。
  • 第二種就是單獨給dao下目錄配置debug模式,程式碼如下,這樣配置sql語句會列印,其他還是正常info級別:
    在這裡插入圖片描述

AOP:面向切面程式設計

新增aop依賴

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

AOP的基本概念

切面(Advisor):表示從業務邏輯中分離出來的橫切邏輯,比如效能監控,日誌記錄,許可權控制等
連線點(JointPoint):程式執行過程中明確的點,一般是方法的呼叫
通知(Advice): 通知是切面的一種實現,可以完成簡單的織入功能。通知定義了增強程式碼切入到目的碼的時間點,是目標方法執行之前執行,還是執行之後執行等。切入點定義切入的位置,通知定義切入的時間
切入點(PointCut): 就是帶有通知的連線點,切入點指切面具體織入的方法
織入(Weaving): 織入是指將切面程式碼插入到目標物件的過程。代理的invoke方法完成的工作,可以稱為織入
目標物件(Target): 目標物件指將要被增強的物件。即包含主業務邏輯的類的物件

實現AOP的切面主要有以下幾個要素:

  • @Aspect: 將一個java類定義為切面類
  • @Pointcut: 定義一個切入點,可以是一個規則表示式
  • @Order(i): 當有多個切面滿足條件時,需要定義切面的優先順序,i值越小越先執行
  • @Before: 在切入點開始處切入內容
  • @After: 在切入點結尾處切入內容
  • @AfterReturning: 在切入點return內容之後切入內容(可以用來對處理返回值做一些加工處理)
  • @Around: 在切入點前後切入內容,並自己控制何時執行切入點自身的內容
  • @AfterThrowing: 用來處理當切入內容部分丟擲異常之後的處理邏輯

當同時有個多切面需要執行時,通過Order來定義優先順序,值越小越優先執行。例如有兩個切面,一個是記錄請求@Order(1),一個是驗證介面中的引數@Order(2),那麼切面方法的執行順序是先執行@Order(1)的before, 再執行@Order(2)的before; 然後再執行@Order(2)的@After或@AfterReturning,最後再執行@Order(1)的@After或@AfterReturning

示例

@Aspect
@Component
public class LoginAspect {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    //宣告切入點
    @Pointcut("execution(public * com.example.demo.controller.*.*())")
    public void poincut(){}

    //定義前切切面
    @Before("poincut()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        logger.info("ip: " + request.getRemoteAddr());
        logger.info("url:" + request.getRequestURL().toString());
        logger.info("HTTP_METHOD:" + request.getMethod());
        //joinPoint.getSignature()獲取切入點的相關資訊
        logger.info("target: " + joinPoint.getSignature());
        logger.info("class_method:" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("args:" + Arrays.toString(joinPoint.getArgs()));
    }

    //定義return切面
    @AfterReturning(pointcut = "poincut()", returning = "rep")
    public void doAfterReturn(Object rep){
        logger.info("rep: " + rep);
    }

}

控制檯
在這裡插入圖片描述


轉載
Spring Boot入門教程(六): 日誌