實戰(zhàn)代碼(四):Springboot AOP實現(xiàn)接口訪問次數(shù)統(tǒng)計

一、理論基礎

1.1 AOP是什么

  • AOP(Aspect Oriented Programming)--面向切面編程
  • 可以通過預編譯方式和運行期動態(tài)代理實現(xiàn)在不修改源代碼的情況下給程序動態(tài)統(tǒng)一添加功能的一種技術

以上介紹來自百度百科-AOP

1.2 AOP能做什么

  • 統(tǒng)計接口訪問次數(shù)
  • 增強功能:在不改動代碼的情況下,為接口增加一些額外的功能

二、實戰(zhàn)代碼

2.1 依賴引入

<!-- AOP -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.4</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.12</version>
</dependency>

2.2 AOP示例

/**
 * API訪問歷史統(tǒng)計
 * @author yangjunqiang
 */
@Component
@Aspect
public class ApiVisitHistory {

    private Logger log = LoggerFactory.getLogger(ApiVisitHistory.class);

    ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * 定義切面
     * - 此處代表com.smile.demo.controller包下的所有接口都會被統(tǒng)計
     */
    @Pointcut("execution(* com.smile.demo.controller..*.*(..))")
    public void pointCut(){

    }

    /**
     * 在接口原有的方法執(zhí)行前,將會首先執(zhí)行此處的代碼
     */
    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        startTime.set(System.currentTimeMillis());
        //獲取傳入目標方法的參數(shù)
        Object[] args = joinPoint.getArgs();
        log.info("類名:{}", joinPoint.getSignature().getDeclaringType().getSimpleName());
        log.info("方法名:{}", joinPoint.getSignature().getName() );
        // 計數(shù)
        AtomicCounter.getInstance().increase();
    }

    /**
     * 只有正常返回才會執(zhí)行此方法
     * 如果程序執(zhí)行失敗,則不執(zhí)行此方法
     */
    @AfterReturning(returning = "returnVal", pointcut = "pointCut()")
    public void doAfterReturning(JoinPoint joinPoint, Object returnVal) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        log.info("所有接口的總點擊:{}", AtomicCounter.getInstance().getValue());
    }

    /**
     * 當接口報錯時執(zhí)行此方法
     */
    @AfterThrowing(pointcut = "pointCut()")
    public void doAfterThrowing(JoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        log.info("接口訪問失敗,URI:[{}], 耗費時間:[{}] ms", request.getRequestURI(), System.currentTimeMillis() - startTime.get());
    }
}

2.3 定義接口,進行測試

@RestController
@RequestMapping("/demo/aop")
public class HelloController {

    @GetMapping("hello")
    public String hello() {
        return "hello World!";
    }

    @GetMapping("hello2")
    public String hello2() {
        int i = 1 / 0;
        return "測試報錯的AOP方法";
    }
}

2.4 源碼地址

https://github.com/lysmile/spring-boot-demo/tree/master/springboot-aop-demo

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容