成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring Boot AOP 掃盲

開發 架構
今天這篇文章就來帶大家通過實戰的方式,在編程貓 SpringBoot 項目中使用 AOP 技術為 controller 層添加一個切面來實現接口訪問的統一日志記錄。

大家好,我是二哥呀。AOP 是 Spring 體系中非常重要的兩個概念之一(另外一個是 IoC),今天這篇文章就來帶大家通過實戰的方式,在編程貓 SpringBoot 項目中使用 AOP 技術為 controller 層添加一個切面來實現接口訪問的統一日志記錄。

一、關于 AOP

AOP,也就是 Aspect-oriented Programming,譯為面向切面編程,是計算機科學中的一個設計思想,旨在通過切面技術為業務主體增加額外的通知(Advice),從而對聲明為“切點”(Pointcut)的代碼塊進行統一管理和裝飾。

這種思想非常適用于,將那些與核心業務不那么密切關聯的功能添加到程序中,就好比我們今天的主題——日志功能,就是一個典型的案例。

AOP 是對面向對象編程(Object-oriented Programming,俗稱 OOP)的一種補充,OOP 的核心單元是類(class),而 AOP 的核心單元是切面(Aspect)。利用 AOP 可以對業務邏輯的各個部分進行隔離,從而降低耦合度,提高程序的可重用性,同時也提高了開發效率。

我們可以簡單的把 AOP 理解為貫穿于方法之中,在方法執行前、執行時、執行后、返回值后、異常后要執行的操作。

二、AOP 的相關術語

來看下面這幅圖,這是一個 AOP 的模型圖,就是在某些方法執行前后執行一些通用的操作,并且這些操作不會影響程序本身的運行。

我們了解下 AOP 涉及到的 5 個關鍵術語:

1)橫切關注點,從每個方法中抽取出來的同一類非核心業務

2)切面(Aspect),對橫切關注點進行封裝的類,每個關注點體現為一個通知方法;通常使用 @Aspect 注解來定義切面。

3)通知(Advice),切面必須要完成的各個具體工作,比如我們的日志切面需要記錄接口調用前后的時長,就需要在調用接口前后記錄時間,再取差值。通知的方式有五種:

  • @Before:通知方法會在目標方法調用之前執行
  • @After:通知方法會在目標方法調用后執行
  • @AfterReturning:通知方法會在目標方法返回后執行
  • @AfterThrowing:通知方法會在目標方法拋出異常后執行
  • @Around:把整個目標方法包裹起來,在被調用前和調用之后分別執行通知方法

4)連接點(JoinPoint),通知應用的時機,比如接口方法被調用時就是日志切面的連接點。

5)切點(Pointcut),通知功能被應用的范圍,比如本篇日志切面的應用范圍是所有 controller 的接口。通常使用 @Pointcut 注解來定義切點表達式。

切入點表達式的語法格式規范如下所示:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern?)
  • modifiers-pattern? 為訪問權限修飾符
  • ret-type-pattern 為返回類型,通常用 *來表示任意返回類型
  • declaring-type-pattern? 為包名
  • name-pattern 為方法名,可以使用 * 來表示所有,或者 set* 來表示所有以 set 開頭的類名
  • param-pattern) 為參數類型,多個參數可以用 , 隔開,各個參與也可以使用 * 來表示所有類型的參數,還可以使用 (..) 表示零個或者任意參數
  • throws-pattern? 為異常類型
  • ? 表示前面的為可選項

舉個例子:

@Pointcut("execution(public * com.codingmore.controller.*.*(..))")

表示 com.codingmore.controller 包下的所有 public 方法都要應用切面的通知。

三、實操 AOP 記錄接口訪問日志

第一步,在 Spring Boot 項目的 pom.xml 文件中添加 spring-boot-starter-aop 依賴。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

第二步,添加日志信息封裝類 WebLog,用于記錄什么樣的操作、操作的人是誰、開始時間、花費的時間、操作的路徑、操作的方法名、操作主機的 IP、請求參數、返回結果等。

/**
* Controller層的日志封裝類
* Created by macro on 2018/4/26.
*/
public class WebLog {
private String description;
private String username;
private Long startTime;
private Integer spendTime;
private String basePath;
private String uri;
private String url;
private String method;
private String ip;
private Object parameter;
private Object result;
//省略了getter,setter方法
}

第三步,添加統一日志處理切面 WebLogAspect。

/**
* 統一日志處理切面
* Created by 石磊
*/
@Aspect
@Component
@Order(1)
public class WebLogAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);

@Pointcut("execution(public * com.codingmore.controller.*.*(..))")
public void webLog() {
}

@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
}

@AfterReturning(value = "webLog()", returning = "ret")
public void doAfterReturning(Object ret) throws Throwable {
}

@Around("webLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
//獲取當前請求對象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//記錄請求信息(通過Logstash傳入Elasticsearch)
WebLog webLog = new WebLog();
Object result = joinPoint.proceed();
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method.isAnnotationPresent(ApiOperation.class)) {
ApiOperation log = method.getAnnotation(ApiOperation.class);
webLog.setDescription(log.value());
}
long endTime = System.currentTimeMillis();
String urlStr = request.getRequestURL().toString();
webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));
webLog.setIp(request.getRemoteUser());
Map<String,Object> logMap = new HashMap<>();
logMap.put("spendTime",webLog.getSpendTime());
logMap.put("description",webLog.getDescription());
LOGGER.info("{}", JSONUtil.parse(webLog));
return result;
}
}

第四步,運行項目,并對 controller 下的某個控制器進行測試。

Swagger knife4j 訪問地址:http://localhost:9022/doc.html

執行登錄用戶查詢操作:

可以在控制臺可以看到以下日志信息:

源碼地址:https://github.com/itwanger/coding-more

參考鏈接:

作者 cxuan:https://www.cnblogs.com/cxuanBlog/p/13060510.html

灰小猿:https://bbs.huaweicloud.com/blogs/289045

山高我為峰:https://www.cnblogs.com/liaojie970/p/7883687.html

macrozheng:https://github.com/macrozheng/mall

本文轉載自微信公眾號「沉默王二」,可以通過以下二維碼關注。轉載本文請聯系沉默王二公眾號。

責任編輯:武曉燕 來源: 沉默王二
相關推薦

2021-03-01 23:26:41

日志Spring BootAOP

2022-02-08 17:07:54

Spring BooSpring Aop日志記錄

2009-06-19 13:28:30

Spring AOPSpring 2.0

2022-06-07 07:58:45

SpringSpring AOP

2025-03-12 14:09:56

2009-06-22 10:41:34

Spring.AOP

2022-06-08 08:04:28

Springservicerepository

2009-09-29 10:00:40

Spring AOP框

2009-06-19 11:09:27

Spring AOP

2024-11-04 16:29:19

2025-06-18 02:12:00

2022-09-01 10:40:29

SpringAOPJDK

2023-03-29 08:24:30

2024-12-24 14:01:10

2025-03-17 08:10:00

aviatorSpringJVM

2009-06-18 14:54:52

Spring AOP

2019-11-29 16:21:22

Spring框架集成

2012-09-27 09:47:43

SpringJava面向對象

2012-09-28 10:20:14

IBMdw

2024-09-26 14:48:35

SpringAOP范式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 人人干视频在线 | 国产精品成人在线 | 国产一区二区三区四区 | 紧缚调教一区二区三区视频 | 久久久久一区 | 黄色一级大片在线免费看产 | 欧美久久不卡 | 亚洲精品二区 | 欧美成人一区二免费视频软件 | 97av视频| 91日b| 欧美 日韩 国产 成人 在线 | 久久精品国产99国产精品 | 国产高清在线 | 欧美日韩不卡合集视频 | 日韩在线视频观看 | 国产成人一区二区三区久久久 | 欧美 日韩 国产 成人 在线 | 麻豆一区 | 久久一区二区三区四区 | 性欧美精品一区二区三区在线播放 | 九九久久久久久 | 特一级毛片| 台湾av在线 | 3p视频在线观看 | 犬夜叉在线观看 | 久久久久久国产精品 | 欧美一区二| 国产精品亚洲精品 | 日韩欧美一区二区三区免费观看 | av在线黄 | 国产亚洲精品精品国产亚洲综合 | 欧美久久久网站 | 成人免费淫片aa视频免费 | 亚洲精彩免费视频 | 久久91精品久久久久久9鸭 | 成人超碰在线 | 欧美黑人体内she精在线观看 | 成人亚洲视频 | 久久国产一区二区三区 | 欧美三级视频在线观看 |