亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

spring boot 使用Aop通知打印控制器請求報文和返回報文問題

2024-07-14 08:40:24
字體:
來源:轉載
供稿:網友

一、簡介

開發過程中我們往往需要寫許多例如: 

@GetMapping("/id/get")  public Result getById( String id) throws Exception{    log.info("請求參數為:"+id);    verify(new VerifyParam("部門id", id));    Result result = new Result("通過id獲取部門信息成功!", service.queryById(id));    log.info("返回報文為:"+result.toString());    return result;  }

打印請求參數以及返回參數的方法,而這些操作存在于每個方法之中,使得我們代碼較為冗余,為此我們可以通過動態代理將打印參數和打印返回報文作為切面,使用切入點表達式將其切入至每個方法之中。

二、步驟

1、引入Aop相關的依賴:

<!--AOP相關的依賴--><dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-aop</artifactId></dependency>

引入依賴后spring-aop會加載其需要的依賴,spring默認使用aspectJ實現通知

其中aspectjweaver.jar中包含了解析aspectJ切入點表達式的文件,使用切入點表達式處理事務的時候也需要加入此依賴。

2、配置:

1)、創建配置類:

/** * @功能描述:用于controller層操作的AOP類 * @author Administrator */@Component // 將對象交由spring進行管理@Aspect // 代表此類為一個切面類public class ControllerAop {}

其中@Aspect 注解代表其為一個切面管理類,可以在其下定義切入點表達式,aspectJ框架會進行解析。

2)、定義切入點表達式:

@Pointcut("execution(public * com.hzt.manage.*.web.controller..*.*(..))") // 切入點表達式  public void privilege() {  }

其中,@Pointcut代表此方法為一個切入點表達式。其value值為切入點表達式,其中value可以省略其大致格式為:

  @注解(表達標簽+表達式格式)
的格式,Spring AOP支持的AspectJ切入點指示符如下:

1、 execution:用于匹配方法執行的連接點;

2、within:用于匹配指定類型內的方法執行;

3、this:用于匹配當前AOP代理對象類型的執行方法;注意是AOP代理對象的類型匹配,這樣就可能包括引入接口也類型匹配;

4、target:用于匹配當前目標對象類型的執行方法;注意是目標對象的類型匹配,這樣就不包括引入接口也類型匹配;

5、args:用于匹配當前執行的方法傳入的參數為指定類型的執行方法;

6、@within:用于匹配所以持有指定注解類型內的方法;

7、@target:用于匹配當前目標對象類型的執行方法,其中目標對象持有指定的注解;

8、@args:用于匹配當前執行的方法傳入的參數持有指定注解的執行;

9、@annotation:用于匹配當前執行方法持有指定注解的方法;

10、bean:Spring AOP擴展的,AspectJ沒有對于指示符,用于匹配特定名稱的Bean對象的執行方法;

11、reference pointcut:表示引用其他命名切入點,只有@ApectJ風格支持,Schema風格不支持。

args中定義了切入點表達式方法執行時候的參數:

  @Pointcut(value="execution(public * com.hzt.manage.*.web.controller..*.*(..))&&args(param)",argNames="param") // 切入點表達式  public void privilege1(String param) {  }

我們重點介紹 execution 方法連接點的表達式,其大概結構為:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

1、修飾符匹配(modifier-pattern?)(可省略)

2、返回值匹配(ret-type-pattern)可以為*表示任何返回值 ,如 (String) 代表只篩選返回String類型的切入點 ,全路徑的類名等(不可省略)

3、類路徑匹配(declaring-type-pattern?)如*.manage代表一級包為任意,二級包為manage的名稱。*..manage代表所有manage包下的子類包。com..*.comtroller代表com包下所有的controller包等,*代表所有包都匹配。(不可省略)

4、方法名匹配(name-pattern)可以指定方法名 或者 *代表所有, get* 代表以get開頭的所有方法,也可指定前綴*get代表任意后綴為get的方法(不可省略)

5、參數匹配((param-pattern))可以指定具體的參數類型,多個參數間用“,”隔開,各個參數也可以用“*”來表示匹配任意類型的參數,如(String)表示匹配一個String參數的方法;(*,String) 表示匹配有兩個參數的方法,第一個參數可以是任意類型,而第二個參數是String類型;可以用(..)表示任意參數(不可省略)

6、異常類型匹配(throws-pattern?)

3、定義切面方法

@Around("privilege()")  public Object around(ProceedingJoinPoint pjd) throws Throwable {    // 獲取方法名    String className = pjd.getSignature().getClass().getName();    // 獲取執行的方法名稱    String methodName = pjd.getSignature().getName();    /** 初始化日志打印 */    Logger log = LoggerFactory.getLogger(className);    // 定義返回參數    Object result = null;    // 記錄開始時間    long start = System.currentTimeMillis();    // 獲取方法參數    Object[] args = pjd.getArgs();    String params = "前端請求參數為:";    //獲取請求參數集合并進行遍歷拼接    for (Object object : args) {      params += object.toString() + ",";    }    params = params.substring(0, params.length() - 1);    //打印請求參數參數    log.info(className+"類的"+methodName + "的" + params);    // 執行目標方法    result = pjd.proceed();    // 打印返回報文    log.info("方法返回報文為:" + (result instanceof Result ? (Result) result : result));    // 獲取執行完的時間    log.info(methodName + "方法執行時長為:" + (System.currentTimeMillis() - start));    return result;  }

5、@Around 環繞通知,如上代碼所示便是環繞通知,其有ProceedingJoinPoint參數

其中 pjd.proceed();方法代表去執行目標方法,并獲得一個Object類型的返回值 ,我們可以對返回值進行加工處理,如裝飾加工等。

return的值為方法執行的結果。上述代碼中首先獲取類名、方法名、方法請求參數等,進行打印的拼接,并且記錄方法執行的開始時間,并進行打印至日志。

然后執行方法,獲取到方法返回結果,進行打印執行時間和執行結果。

最后返回執行結果。即使用Aop打印請求報文和返回報文的aop切面編碼結束。

其中@Around代表其為一個環繞通知方法,其有以下幾種類型:

1、@Before前置通知,擁有請求參數 JoinPoint ,用來連接當前連接點的連接細節,一般包括方法名和參數值。在方法執行前進行執行方法體,不能改變方法參數,也不能改變方法執行結果。

  @Before(value = "privilege()")  public void before(JoinPoint joinPoint) {  }

2、@After 后置通知:在目標方法執行之后,無論是否發生異常,都進行執行的通知。在后置通知中,不能訪問目標方法的執行結果(因為有可能發生異常),不能改變方法執行結果。

@Before(value = "privilege()")  public void after(JoinPoint joinPoint) {      }

3、@AfterReturning 返回通知,在目標方法執行結束時,才執行的通知,同后置方法相同。其能訪問方法執行結果(因為正常執行)和方法的連接細節,但是不能改變方法執行結果。

  @AfterReturning(value = "privilege()")  public void afterReturing(JoinPoint joinPoint,Object result) {  }

result中存放的為方法的返回值。

4、@AfterThrowing 異常通知:在目標方法出現異常時才會進行執行的代碼。 throwing屬性代表方法體執行時候拋出的異常,其值一定與方法中Exception的值需要一致。

  @AfterThrowing(value="privilege()",throwing="ex")  public void exce(JoinPoint joinPoint, Exception ex) {      }

三、測試

編寫一個Controller方法

@RestController@RequestMapping("/api/v1/dept")public class DeptController extends BaseController{  /** 日志記錄類 */  private Logger log = LoggerFactory.getLogger(getClass());  /** 自家的service */  @Autowired  private DeptService service;  /**   * @功能描述:根據id查詢部門內容的方法   * @return Dept   */  @GetMapping("/id/get")  public Result getById( String id) throws Exception{    verify(new VerifyParam("部門id", id));    return new Result("通過id獲取部門信息成功!", service.queryById(id));  }}

如此我們的controller層中的方法就大大的簡潔了。

測試結果:

2018-04-10 22:59:27.468  INFO 1460 --- [nio-8088-exec-5] nProceedingJoinPoint$MethodSignatureImpl : getById的前端請求參數為:22
2018-04-10 22:59:27.470  INFO 1460 --- [nio-8088-exec-5] nProceedingJoinPoint$MethodSignatureImpl : 方法返回報文為:Result [result_code=suc, result_message=通過id獲取部門信息成功!, data=Dept [id=22, no=22, name=22, manager=22, description=22, phone=22, createTime=Thu Apr 19 23:38:37 CST 2018, editTime=null]]
2018-04-10 22:59:27.470  INFO 1460 --- [nio-8088-exec-5] nProceedingJoinPoint$MethodSignatureImpl : getById方法執行時長為:2

如此便能很雅觀簡潔隱式的打印請求參數、返回結果和執行時間等!


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲成年网站在线观看| 色www亚洲国产张柏芝| 日韩免费观看在线观看| 国模叶桐国产精品一区| 欧美电影免费观看高清完整| 日韩欧美在线视频日韩欧美在线视频| 国产精品99久久久久久久久| 91精品国产综合久久香蕉最新版| 欧美大码xxxx| 久久久伊人日本| 久久久久国色av免费观看性色| 亚洲欧美综合区自拍另类| 亚洲国产精品一区二区久| 欧美日韩在线免费| 欧美成人全部免费| 欧美专区在线观看| 国产视频精品自拍| 97久久精品国产| 久久久精品在线观看| 久久久久久国产精品久久| 午夜精品视频网站| 国产日韩精品在线观看| 欧洲s码亚洲m码精品一区| 欧美贵妇videos办公室| 欧美日韩国产色视频| 国产视频福利一区| 久久久久一本一区二区青青蜜月| 亚洲成人三级在线| 国产精品老女人视频| 午夜欧美不卡精品aaaaa| 77777少妇光屁股久久一区| 欧美伊久线香蕉线新在线| 久久久久国产精品免费| 精品久久久久久亚洲精品| 欧美电影在线观看网站| 欧美成人免费网| 日韩精品一区二区三区第95| 久久成人免费视频| 亚洲第一男人天堂| 2019最新中文字幕| 日韩欧美一区二区三区久久| 亚洲深夜福利在线| 亚洲精品动漫100p| 精品美女国产在线| 亚洲国产精品女人久久久| 91久久精品国产| 国产精品国产三级国产aⅴ浪潮| 中文字幕在线看视频国产欧美在线看完整| 欧美日韩在线看| 欧美性猛交xxxx免费看| 亚洲网站在线观看| 亚洲国产成人久久| 日韩成人在线电影网| 国产精品91在线观看| 欧美午夜影院在线视频| 久久久99免费视频| 日本高清视频一区| 亚洲精品自拍视频| 日韩麻豆第一页| 欧美日本精品在线| 日韩网站免费观看高清| 日韩免费在线电影| 亚洲国产日韩欧美在线图片| 亚洲精品电影网站| 成人网址在线观看| 热99在线视频| 亚洲成人黄色网址| 国产精品久久久久久亚洲影视| 欧美主播福利视频| 51ⅴ精品国产91久久久久久| 欧美性猛交99久久久久99按摩| 91免费看片在线| 日韩欧美成人免费视频| 国产成人精品一区| 久久最新资源网| 2019最新中文字幕| 日韩中文字幕精品视频| 91视频国产高清| 成人黄在线观看| 精品一区二区电影| 97人人模人人爽人人喊中文字| 国产aⅴ夜夜欢一区二区三区| 日韩av三级在线观看| 欧美理论电影在线播放| 性色av一区二区三区| 欧美三级xxx| 国产亚洲欧洲高清一区| 亚洲精品狠狠操| 亚洲片国产一区一级在线观看| 成人激情在线观看| 久久久91精品国产一区不卡| 国产精品久久久久久久av电影| 久久精品国产一区二区电影| 日韩av电影手机在线| 富二代精品短视频| 成人中心免费视频| 久久97久久97精品免视看| 欧美黑人狂野猛交老妇| www.亚洲男人天堂| 97在线视频免费看| 国产日韩在线观看av| 国产精品久久国产精品99gif| 中文字幕av一区二区三区谷原希美| 亚洲天堂av网| 欧美电影免费观看高清完整| 国产精品999999| 欧美激情网站在线观看| 欧美—级a级欧美特级ar全黄| 亚洲午夜久久久久久久| 91亚洲国产成人久久精品网站| 久久久久久久一区二区三区| 日韩精品视频在线播放| 国产精品美女久久久久av超清| 色婷婷综合成人av| 国产精品爱久久久久久久| 欧美午夜精品久久久久久浪潮| 亚洲天堂开心观看| 少妇激情综合网| 久久久综合av| 欧美日韩国产一区在线| 日韩精品丝袜在线| 综合网日日天干夜夜久久| 日韩电影免费观看在线观看| 国产精品男人爽免费视频1| 欧美大胆a视频| 欧美一区二区大胆人体摄影专业网站| 精品国内亚洲在观看18黄| 国产日韩精品一区二区| 精品中文字幕在线| 91精品国产综合久久久久久蜜臀| 国产精品天天狠天天看| 久久精品视频免费播放| 国产精品揄拍500视频| 欧美激情三级免费| 欧美整片在线观看| 日韩av黄色在线观看| 亚洲美女黄色片| 欧美影院在线播放| 欧美一性一乱一交一视频| 亚洲一区二区三区在线免费观看| 国内精品国产三级国产在线专| 欧美成人性生活| 91精品久久久久久久久不口人| 成人女保姆的销魂服务| 国产亚洲欧美aaaa| 亚洲精品天天看| 亚洲韩国日本中文字幕| 日韩av在线免费| 国产精品91在线观看| 久久99国产精品自在自在app| 成人激情av在线| 黑人极品videos精品欧美裸| 亚洲精品福利视频| 欧美高清在线观看| 日韩三级成人av网| 美日韩精品免费观看视频| 亚洲一区二区精品| 欧美激情高清视频| 亚洲欧美变态国产另类| 日韩欧美一区二区三区久久| 国产欧美日韩精品在线观看| 国产成人综合久久| 午夜精品在线观看| 欧美日韩午夜剧场|