Spring Boot使用AOP在控制檯列印請求、響應資訊

java_lover發表於2019-02-20

AOP稱為面向切面程式設計,在程式開發中主要用來解決一些系統層面上的問題,比如日誌,事務,許可權等。

AOP簡介

AOP全稱Aspect Oriented Programming,面向切面,AOP主要實現的目的是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。其與設計模式完成的任務差不多,是提供另一種角度來思考程式的結構,來彌補物件導向程式設計的不足。

  通俗點講就是提供一個為一個業務實現提供切面注入的機制,通過這種方式,在業務執行中將定義好的切面通過切入點繫結到業務中,以實現將一些特殊的邏輯繫結到此業務中。

  比如,現在需要列印請求、響應資訊,很多地方有需要,這時候又不能把程式碼複製一遍,所有需要AOP來實現。

常用註解說明

@Aspect — 作用是把當前類標識為一個切面供容器讀取
@Pointcut — (切入點):就是帶有通知的連線點,在程式中主要體現為書寫切入點表示式
@Before — 標識一個前置增強方法,相當於BeforeAdvice的功能
@AfterReturning — 後置增強,相當於AfterReturningAdvice,方法退出時執行
@AfterThrowing — 異常丟擲增強,相當於ThrowsAdvice
@After — final增強,不管是丟擲異常或者正常退出都會執行
@Around — 環繞增強,相當於MethodInterceptor

pom.xml中引入AOP的jar包

<!-- aop -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
        <!-- fastjson -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

切面類程式碼

package com.example.helloSpringBoot.aop;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 切面 列印請求、返回引數資訊
 */
@Aspect // 定義一個切面
@Configuration
public class LogRecordAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogRecordAspect.class);

    // 定義切點Pointcut
    @Pointcut("execution(* com.example.helloSpringBoot.controller.*Controller.*(..))")
    public void excudeService() {
    }

    @Around("excudeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        String method = request.getMethod();
        String uri = request.getRequestURI();
        String paraString = JSON.toJSONString(request.getParameterMap());
        logger.info("***************************************************");
        logger.info("請求開始, URI: {}, method: {}, params: {}", uri, method, paraString);

        // result的值就是被攔截方法的返回值
        Object result = pjp.proceed();
        logger.info("請求結束,controller的返回值是 " + JSON.toJSONString(result));
        return result;
    }
}

測試列印結果

瀏覽器分別訪問 http://localhost:8080/hello?a=1&b=2 和http://localhost:8080/hello?c=11&d=22,控制檯列印結果如下:

***************************************************
請求開始, URI: /hello, method: GET, params: {"a":["1"],"b":["2"]}
請求結束,controller的返回值是 "hello spring boot!"
***************************************************
請求開始, URI: /hello, method: GET, params: {"c":["11"],"d":["22"]}
請求結束,controller的返回值是 "hello spring boot!"

下面的是我的公眾號二維碼圖片,歡迎關注,歡迎留言,一起學習,一起進步。

Java碎碎念公眾號Java碎碎念公眾號

 

相關文章