最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用springboot aop記錄接口請(qǐng)求的參數(shù)及響應(yīng)

 更新時(shí)間:2024年09月20日 17:31:35   作者:BIGSHU0923  
該文章介紹了如何使用SpringAOP的切面注解,如@Before和@AfterReturning,來(lái)記錄Controller層的方法輸入?yún)?shù)和響應(yīng)結(jié)果,還討論了@Around注解的靈活性,允許在方法執(zhí)行前后進(jìn)行更多控制,需要的朋友可以參考下

概述

使用aop做日志記錄,記錄輸入的參數(shù)名及參數(shù)值,并且記錄接口響應(yīng)結(jié)果。

切面類(lèi)

package com.zou.metabox.common.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * @author BIGSHU0923
 * @description com.zou.metabox 中Controller層的的日志切面
 * @since 7/30/2023  5:32 PM
 */
@Aspect
@Component
@Slf4j
public class LoggingAspect {
    /**
     * com.zou.metabox.controller 包中公共方法的切入點(diǎn)
     */
    @Pointcut("execution(public * com.zou.metabox.controller.*.*(..))")
    public void loggingPointcut(){
        // 暫不用處理
    }

    /**
     在日志切入點(diǎn)之前執(zhí)行的通知。
     記錄方法名稱和請(qǐng)求參數(shù)。
     @param joinPoint 控制器類(lèi)中的連接點(diǎn)
     */
    @Before("loggingPointcut()")
    public void logBefore(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String[] parameterNames = methodSignature.getParameterNames();
        Map<String, Object> requestMap = new HashMap<>();
        IntStream.range(0, parameterNames.length)
                .forEach(i -> requestMap.put(parameterNames[i], args[i]));
        log.info("Before method:{}|{}", joinPoint.getSignature().getName(), requestMap);
    }

    /**
     在日志切入點(diǎn)之后和方法成功執(zhí)行后執(zhí)行的通知。
     記錄方法名稱和返回結(jié)果。
     @param joinPoint 控制器類(lèi)中的連接點(diǎn)
     @param result 方法的返回結(jié)果
     */
    @AfterReturning(pointcut = "execution(public * com.zou.metabox.controller.*.*(..))", returning = "result")
    public void logResponse(JoinPoint joinPoint, Object result){
        log.info("Method response:{}|{}", joinPoint.getSignature().getName(), result.toString());
    }

}

注意

這個(gè)切面定義的切點(diǎn)是在@Pointcut這個(gè)注解中定義的。我這里定義的是Controller中所有的public方法。

@After和@Afterreturning的區(qū)別

@After和@AfterReturning是兩個(gè)不同的切面通知類(lèi)型。

@After通知會(huì)在目標(biāo)方法執(zhí)行之后觸發(fā),無(wú)論目標(biāo)方法是否拋出異常。所以在@After通知中不能訪問(wèn)目標(biāo)方法的返回值。

@AfterReturning通知只在目標(biāo)方法成功執(zhí)行并返回后觸發(fā),可以訪問(wèn)目標(biāo)方法的返回值。一般使用@AfterReturning通知來(lái)收集方法的執(zhí)行結(jié)果或進(jìn)行日志記錄。

優(yōu)化

@Around注解可以更方便地控制代理鏈條的行為,具體是指通過(guò)@Around注解實(shí)現(xiàn)的方法既可以代替@Before和@AfterReturning注解,也可以控制何時(shí)進(jìn)入、何時(shí)退出被代理的方法。在執(zhí)行目標(biāo)方法之前,可以在@Around注解標(biāo)注的方法中編寫(xiě)一些邏輯來(lái)決定是否繼續(xù)執(zhí)行目標(biāo)方法,還可以修改傳遞給目標(biāo)方法的參數(shù)。在執(zhí)行完目標(biāo)方法后,可以在@Around注解

標(biāo)注的方法中對(duì)返回值進(jìn)行處理或者拋出異常。
@Around可以控制何時(shí)進(jìn)入、何時(shí)退出被代理的方法。具體是通過(guò)ProceedingJoinPoint參數(shù)調(diào)用proceed()方法來(lái)執(zhí)行目標(biāo)方法。如下面的result = pjp.proceed();這里起始執(zhí)行的就是接口的方法。所以可以控制何時(shí)進(jìn)入、何時(shí)退出被代理的方法。

    @Around("loggingPointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable{
        // 獲取類(lèi)名
        String className = pjp.getTarget().getClass().getTypeName();
        // 獲取方法名
        String methodName = pjp.getSignature().getName();
        // 獲取參數(shù)名
        String[] parameterNames = ((MethodSignature) pjp.getSignature()).getParameterNames();

        Object result = null;
        // 獲取參數(shù)值
        Object[] args = pjp.getArgs();

        // 獲取請(qǐng)求
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // 獲取請(qǐng)求的url
        String url = request.getRequestURL().toString();

        // 請(qǐng)求參數(shù),以參數(shù)名和值為鍵值對(duì)
        Map<String, Object> paramMap = new HashMap<>();
        IntStream.range(0, parameterNames.length).forEach(i->paramMap.put(parameterNames[i], args[i]));

        // header參數(shù)
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, Object> headerMap = new HashMap<>();
        while (headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            headerMap.put(headerName, headerValue);
        }

        // 打印請(qǐng)求參數(shù),記錄起始時(shí)間
        long start = System.currentTimeMillis();
        log.info("請(qǐng)求| 請(qǐng)求接口:{} | 類(lèi)名:{} | 方法:{} | header參數(shù):{} | 參數(shù):{} | 請(qǐng)求時(shí)間:{}", url, className, methodName, headerMap, paramMap, LocalDateTime.now());

        try {
            result = pjp.proceed();
        } catch (Exception e) {
            log.error("返回| 處理時(shí)間:{} 毫秒 | 返回結(jié)果 :{}", (System.currentTimeMillis() - start), "failed");
            throw e;
        }

        // 獲取執(zhí)行完的時(shí)間 打印返回報(bào)文
        log.info("返回| 處理時(shí)間:{} 毫秒 | 返回結(jié)果 :{}", (System.currentTimeMillis() - start), "success");
        return result;
    }

總結(jié)

Spring AOP 是基于代理的 AOP 框架,提供了幾個(gè)不同的切面建言(advice)注解:@Before、@AfterReturning、@Around、@AfterThrowing 和 @After。這些注解分別表示在目標(biāo)方法執(zhí)行的不同時(shí)間點(diǎn)進(jìn)行增強(qiáng)處理。

具體來(lái)說(shuō):

@Before:表示在目標(biāo)方法執(zhí)行前進(jìn)行增強(qiáng)處理。
@AfterReturning:表示在目標(biāo)方法執(zhí)行后,返回結(jié)果之后進(jìn)行增強(qiáng)處理,可以訪問(wèn)到方法的返回值。
@Around:表示在目標(biāo)方法執(zhí)行前、執(zhí)行中和執(zhí)行后都可以進(jìn)行增強(qiáng)處理,并且需要手動(dòng)控制何時(shí)進(jìn)入、何時(shí)退出被代理的方法。
@AfterThrowing:表示在目標(biāo)方法拋出異常后進(jìn)行增強(qiáng)處理。
@After:表示在目標(biāo)方法執(zhí)行后,無(wú)論是否發(fā)生異常,都進(jìn)行增強(qiáng)處理。相較于@AfterReturning,@After增強(qiáng)處理無(wú)法獲取到方法的返回值。
在實(shí)際使用時(shí),@Before 和 @AfterReturning 主要用于記錄日志、記性權(quán)限控制等與目標(biāo)方法無(wú)關(guān)的操作;@Around 則比較常用,因?yàn)樗梢栽谀繕?biāo)方法的執(zhí)行前后進(jìn)行增強(qiáng)處理,并且可以更方便地控制代理鏈條的行為;@AfterThrowing 和 @After 通常用于回收資源,如關(guān)閉數(shù)據(jù)庫(kù)連接等操作。

相關(guān)文章

  • 詳解spring注解配置啟動(dòng)過(guò)程

    詳解spring注解配置啟動(dòng)過(guò)程

    這篇文章主要為大家詳細(xì)介紹了詳解spring注解配置啟動(dòng)過(guò)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • mybatis取別名typeAliases標(biāo)簽的位置放錯(cuò)導(dǎo)致報(bào)錯(cuò)的解決

    mybatis取別名typeAliases標(biāo)簽的位置放錯(cuò)導(dǎo)致報(bào)錯(cuò)的解決

    這篇文章主要介紹了mybatis取別名typeAliases標(biāo)簽的位置放錯(cuò)導(dǎo)致報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • java中字符串如何計(jì)算字節(jié)長(zhǎng)度

    java中字符串如何計(jì)算字節(jié)長(zhǎng)度

    這篇文章主要介紹了java中字符串如何計(jì)算字節(jié)長(zhǎng)度,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • ReentrantReadWriteLock不能鎖升級(jí)的原因總結(jié)

    ReentrantReadWriteLock不能鎖升級(jí)的原因總結(jié)

    今天給大家?guī)?lái)的是關(guān)于Java并發(fā)的相關(guān)知識(shí),文章圍繞著為什么ReentrantReadWriteLock不能鎖升級(jí)展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • java selenium Selenium IDE介紹及用法

    java selenium Selenium IDE介紹及用法

    本文主要介紹java selenium Selenium IDE,這里整理了相關(guān)資料和介紹如何安裝 Selenium IDE和使用方法,有需要的小伙伴可以參考下
    2016-08-08
  • Spring事務(wù)失效的場(chǎng)景梳理總結(jié)

    Spring事務(wù)失效的場(chǎng)景梳理總結(jié)

    實(shí)際項(xiàng)目開(kāi)發(fā)中,如果涉及到多張表操作時(shí),為了保證業(yè)務(wù)數(shù)據(jù)的一致性,大家一般都會(huì)采用事務(wù)機(jī)制,好多小伙伴可能只是簡(jiǎn)單了解一下,遇到事務(wù)失效的情況,便會(huì)無(wú)從下手,下面這篇文章主要給大家介紹了關(guān)于Spring事務(wù)失效場(chǎng)景的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • Java編程中利用InetAddress類(lèi)確定特殊IP地址的方法

    Java編程中利用InetAddress類(lèi)確定特殊IP地址的方法

    這篇文章主要介紹了Java編程中利用InetAddress類(lèi)確定特殊IP地址的方法,InetAddress類(lèi)是Java網(wǎng)絡(luò)編程中一個(gè)相當(dāng)實(shí)用的類(lèi),需要的朋友可以參考下
    2015-11-11
  • Spring Boot中的 6 種API請(qǐng)求參數(shù)讀取方式示例詳解

    Spring Boot中的 6 種API請(qǐng)求參數(shù)讀取方式示例詳解

    使用Spring Boot開(kāi)發(fā)API的時(shí)候,讀取請(qǐng)求參數(shù)是服務(wù)端編碼中最基本的一項(xiàng)操作,Spring Boot中也提供了多種機(jī)制來(lái)滿足不同的API設(shè)計(jì)要求,這篇文章主要介紹了Spring Boot中的 6 種API請(qǐng)求參數(shù)讀取方式示例詳解,需要的朋友可以參考下
    2024-05-05
  • SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案

    SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案

    這篇文章主要給大家介紹了關(guān)于SpringBoot前后端傳輸加密設(shè)計(jì)實(shí)現(xiàn)方案的相關(guān)資料,包括數(shù)據(jù)加密方案、解密傳輸數(shù)據(jù)實(shí)現(xiàn)方案和響應(yīng)數(shù)據(jù)加密實(shí)現(xiàn)方案,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-11-11
  • 解析Spring中的靜態(tài)代理和動(dòng)態(tài)代理

    解析Spring中的靜態(tài)代理和動(dòng)態(tài)代理

    學(xué)習(xí) Spring 的過(guò)程中,不可避免要掌握代理模式。這篇文章總結(jié)一下代理模式。顧名思義,代理,就是你委托別人幫你辦事,所以代理模式也有人稱作委托模式的。比如領(lǐng)導(dǎo)要做什么事,可以委托他的秘書(shū)去幫忙做,這時(shí)就可以把秘書(shū)看做領(lǐng)導(dǎo)的代理
    2021-06-06

最新評(píng)論

中西区| 类乌齐县| 无为县| 迭部县| 新兴县| 西乌| 寿光市| 银川市| 河东区| 巴塘县| 珠海市| 武宣县| 湘阴县| 九寨沟县| 秦安县| 诸暨市| 芜湖市| 太仓市| 木里| 潞西市| 大竹县| 邵武市| 兴城市| 新民市| 石阡县| 寿光市| 遂宁市| 宁都县| 外汇| 即墨市| 曲阳县| 德格县| 绵竹市| 乌兰浩特市| 扎赉特旗| 洱源县| 克东县| 浦县| 澎湖县| 连山| 广宁县|