激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

香港云服务器
服務器之家 - 編程語言 - Java教程 - SpringBoot中使用AOP打印接口日志的方法

SpringBoot中使用AOP打印接口日志的方法

2021-05-06 11:14高超楊 Java教程

本篇文章主要介紹了SpringBoot中使用AOP打印接口日志的方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

前言

aop 是 aspect oriented program (面向切面)的編程的縮寫。他是和面向對象編程相對的一個概念。在面向對象的編程中,我們傾向于采用封裝、繼承、多態等概念,將一個個的功能在對象中來實現。但是,我們在實際情況中也發現,會有另外一種需求就是一類功能在很多對象的很多方法中都有需要。例如有一些對數據庫訪問的方法有事務管理的需求,有很多方法中要求打印日志。按照面向對象的方式,那么這些相同的功能要在很多地方來實現或者在很多地方來調用。這就非常繁瑣并且和這些和業務不相關的需求耦合太緊密了。所以后來就出現了面向切面的編程來解決這一類問題,并對面向對象的編程做了很好的補充

概念

要很好的理解面向切面的編程,先要理解 aop 的一些概念。在 java 中 aspectj 比較完整的實現了 aop 的功能,但是使用起來也比較復,所以這里主要是討論 spring 的 aop 。spring aop 采用簡單夠用的原則,實現了 aop 的核心功能。下面先說說 aop 中的具體概念

  1. aspect:方面。一個可以切入多個類的關注點。這個關注點實現了我們前面說的具體的業務功能。例如打印日志,進行數據庫的事務管理等。
  2. joint point:被切入點。是指具體要實現前面所說的例如打印日志,數據庫事務管理的被切入的點。也就是通過 aop 將切面功能動態加入進去的程序位置。在 spring aop 里面這個指的都是某個方法
  3. pointcut:切點。用來指明如何通過規則匹配 joint point。這個規則是一個表達式。在 spring 中,默認使用的是 aspectj 的 pointcut 表達式語言
  4. advice:指明在一個切入點的不同位置上采取的動作。例如對于一個數據庫訪問事務管理來說,在進入方法后要開啟事務,在方法結束前要提交事務,在發生錯誤的時候要回滾事務。這屬于三個不同的 advice,要分別進行實現。advice 通常和具體的 pointcut 關聯在一起。
  5. aop proxy:aop 代理。用來實現將 advice 功能動態加入到 pointcut 的方法。在 spring 的 aop 中采用動態代理和 cglib 代理的方式來實現。而 aspectj 則采用了特定編譯器侵入字節碼的方式來實現。

sprinboot aop 實現

前面我們已經用好幾章講述了 springboot 的基本使用。那么這里我們就用 springboot 和 aop 結合來實現一個輸出所有 rest 接口輸入參數和返回參數的日志的功能。

實現 rest 服務功能。

根據前面的文章,我們先建立一個 spingboot 的工程如下圖所示

SpringBoot中使用AOP打印接口日志的方法

demo 工程

springboot 項目配置

我們對 springboot 項目配置如下

?
1
2
3
4
5
6
7
8
9
10
11
12
server:
 port: 3030
 servlet:
  context-path: /aop-demo
spring:
 jackson:
  date-format: yyyy-mm-dd hh:mm:ss
  serialization:
   indent-output: true
logging:
 level:
  com.yanggch: debug

其中 jackson 相關配置是為了將對象輸出成 json 字符串后能夠格式化輸出

實現一個 rest 接口的 controller 類

在這里,我們實現兩個 rest 接口。一個是返回 hello 信息。一個是根據輸入返回登錄信息。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.yanggch.demo.aop.web;
 
import com.yanggch.demo.aop.domain.loginentity;
import com.yanggch.demo.aop.domain.securityentity;
import org.springframework.web.bind.annotation.pathvariable;
import org.springframework.web.bind.annotation.requestbody;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.requestmethod;
import org.springframework.web.bind.annotation.restcontroller;
 
import java.util.date;
 
/**
 * 安全相關 rest 服務
 *
 * @author : 楊高超
 * @since : 2018-05-27
 */
@restcontroller
@requestmapping("/api/v1/security")
public class securityapi {
  @requestmapping(value = "/login/{shopid}", method = requestmethod.post)
  public securityentity login(@requestbody loginentity loginentity, @pathvariable long shopid) {
    securityentity securityentity = new securityentity();
    securityentity.setshopid(shopid);
    securityentity.setaccount(loginentity.getaccount());
    securityentity.setpwd(loginentity.getpwd());
    securityentity.setlogintime(new date());
    return securityentity;
  }
 
  @requestmapping(value = "/echo/{name}", method = requestmethod.get)
  public string login(@pathvariable string name) {
    return "hello," + name;
  }
}

先在我們要通過 aop 功能將所有 rest 接口的輸入參數和返回結果輸出到日志中。

實現 web aop 功能。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.yanggch.demo.aop.comment;
 
import com.fasterxml.jackson.databind.objectmapper;
import org.aspectj.lang.joinpoint;
import org.aspectj.lang.annotation.afterreturning;
import org.aspectj.lang.annotation.aspect;
import org.aspectj.lang.annotation.before;
import org.aspectj.lang.annotation.pointcut;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.stereotype.component;
import org.springframework.web.multipart.multipartfile;
 
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
 
/**
 * web 接口日志
 *
 * @author : 楊高超
 * @since : 2018-05-27
 */
@aspect
@component
public class weblogaspect {
  private static logger log = loggerfactory.getlogger(weblogaspect.class);
 
  private final objectmapper mapper;
 
  @autowired
  public weblogaspect(objectmapper mapper) {
    this.mapper = mapper;
  }
 
  @pointcut("@annotation(org.springframework.web.bind.annotation.requestmapping)")
  public void weblog() {
  }
 
  @before("weblog()")
  public void dobefore(joinpoint joinpoint) {
    for (object object : joinpoint.getargs()) {
      if (
        object instanceof multipartfile
          || object instanceof httpservletrequest
          || object instanceof httpservletresponse
        ) {
        continue;
      }
      try {
        if (log.isdebugenabled()) {
          log.debug(
            joinpoint.gettarget().getclass().getname() + "." + joinpoint.getsignature().getname()
              + " : request parameter : " + mapper.writevalueasstring(object)
          );
        }
      } catch (exception e) {
        e.printstacktrace();
      }
    }
  }
 
  @afterreturning(returning = "response", pointcut = "weblog()")
  public void doafterreturning(object response) throws throwable {
    if (response != null) {
      log.debug("response parameter : " + mapper.writevalueasstring(response));
    }
  }
}

這里有幾個需要注意的地方,

  1. 需要在類上聲明 org.aspectj.lang.annotation.aspect 注解。
  2. 需要通過方法上的 org.aspectj.lang.annotation.pointcut 注解聲明一個 pointcut ,用來指明要在哪些方法切入。我們的 rest 接口都有 org.springframework.web.bind.annotation.requestmapping 注解,所以我們這里就用了 "@annotation(org.springframework.web.bind.annotation.requestmapping)" 表達式來指明。
  3. 通過 advice 相關注解來說明在切入方法的什么位置做什么事。這里用 org.aspectj.lang.annotation.before
  4. 這個實現是指明在所有具備 org.springframework.web.bind.annotation.requestmapping 注解的方法上,方法進入后打印入口參數。方法返回后,打印返回參數。

測試

在前臺通過 postman 發起請求,后臺日志輸入結果如下

2018-05-27 19:58:42.941 debug 86072 --- [nio-3030-exec-4] c.yanggch.demo.aop.comment.weblogaspect  : com.yanggch.demo.aop.web.securityapi.login : request parameter : {
  "account" : "yanggch",
  "pwd" : "123456"
}
2018-05-27 19:58:42.941 debug 86072 --- [nio-3030-exec-4] c.yanggch.demo.aop.comment.weblogaspect  : com.yanggch.demo.aop.web.securityapi.login : request parameter : 2001
2018-05-27 19:58:42.942 debug 86072 --- [nio-3030-exec-4] c.yanggch.demo.aop.comment.weblogaspect  : response parameter : {
  "shopid" : 2001,
  "account" : "yanggch",
  "pwd" : "123456",
  "logintime" : "2018-05-27 11:58:42"
}
2018-05-27 19:58:45.796 debug 86072 --- [nio-3030-exec-5] c.yanggch.demo.aop.comment.weblogaspect  : com.yanggch.demo.aop.web.securityapi.echo : request parameter : "yanggch"
2018-05-27 19:58:45.796 debug 86072 --- [nio-3030-exec-5] c.yanggch.demo.aop.comment.weblogaspect  : response parameter : "hello,yanggch"

由此可見,我們雖然沒有在 rest 接口方法中寫輸出日志的代碼,但是通過 aop 的方式可以自動的給各個 rest 入口方法中添加上輸出入口參數和返回參數的代碼并正確執行。

其他說明

前面提到了 advice 的類型和 pointcut 的 aop 表達式語言。具體參考如下。

advice 類型

  1. before advice 在方法執行前執行。
  2. after returning advice 在方法執行后返回一個結果后執行。
  3. after throwing advice 在方法執行過程中拋出異常的時候執行。
  4. around advice 在方法執行前后和拋出異常時執行,相當于綜合了以上三種通知。

aop 表達式語言

1、方法參數匹配
@args()

2、方法描述匹配
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)
其中 returning type pattern,name pattern, and parameters pattern是必須的.
. ret-type-pattern:可以為表示任何返回值,全路徑的類名等.
*. name-pattern:指定方法名, *代表所有
.set代表以set開頭的所有方法.
. parameters pattern:指定方法參數(聲明的類型),(..)代表所有參數,()代表一個參數
. (,string)代表第一個參數為任何值,第二個為string類型.

3、當前aop代理對象類型匹配

4、目標類匹配
@target()
@within()

5、標有此注解的方法匹配
@annotation()

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.jianshu.com/p/946c654f02c1

延伸 · 閱讀

精彩推薦
597
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 国色天香综合网 | 在线亚洲欧美 | 中国女警察一级毛片视频 | 狠狠色噜噜狠狠狠米奇9999 | 色操网 | 免费毛片电影 | 米奇电影网 | 中文字幕在线视频日本 | 91精品国产一区二区在线观看 | 日本特级a一片免费观看 | 午夜影视一区二区 | 桥本有菜免费av一区二区三区 | 国产精品一区二区三区99 | 91看片免费版 | 精品人伦一区二区三区蜜桃网站 | 久章草影院 | 国产精品一二区 | 黄色毛片前黄 | 女教师~淫辱の动漫在线 | 色污视频 | 久久成人免费网 | 耽美男男肉文 | 欧美日韩在线视频一区 | 亚洲精品永久视频 | 一级做a爱片毛片免费 | 精国品产一区二区三区有限公司 | 欧美成人性生活片 | 国产精品久久久毛片 | 牛牛碰在线| 黄色免费不卡视频 | 天海翼无删减av三级在线观看 | 成品片a免费直接观看 | 精品国产一区二区三区久久久蜜 | 中文字幕h| 成人毛片免费网站 | 日韩在线激情 | 久久久成人一区二区免费影院 | 毛片视频网站 | 久章草影院 | 成人午夜在线观看视频 | 九九精品在线播放 |