springboot+aop切點記錄請求和響應信息
阿新 • • 發佈:2018-12-25
pid platform config etc line https eba 學習資料 enc 本篇主要分享的是springboot中結合aop方式來記錄請求參數和響應的數據信息;這裏主要講解兩種切入點方式,一種方法切入,一種註解切入;首先創建個springboot測試工程並通過maven添加如下依賴:
org.springframework.boot
spring-boot-starter-aop
com.alibaba
fastjson
1.2.44
復制代碼
先來說方法的切點方式,需要創建個名為LogAspect的組件類,然後用@Aspect註解修飾組件類,再通過設置方法切入點方式做公共日誌記錄,如下創建切入點:
復制代碼
//切點入口 Controller包下面所有類的所有方法
private final String pointcut = "execution(* com.platform.Controller..*(..))";
//切點
@Pointcut(value = pointcut)
public void log() {
}
復制代碼
這裏的execution( com.platform.Controller..(..))主要的意思是:切入點入口是Controller包下面所有類的所有方法;再來通過@Around環繞註解方法裏面做請求參數和響應信息的記錄,如下代碼:
復制代碼
@Around(value = "log()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result = null;
StringBuilder sbLog = new StringBuilder("\n");
try {
sbLog.append(String.format("類名:%s\r\n", proceedingJoinPoint.getTarget().getClass().getName()));
MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
sbLog.append(String.format("方法:%s\r\n", methodSignature.getMethod().getName()));
Object[] args = proceedingJoinPoint.getArgs();
for (Object o : args) {
sbLog.append(String.format("參數:%s\r\n", JSON.toJSON(o)));
}
long startTime = System.currentTimeMillis();
result = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
sbLog.append(String.format("返回:%s\r\n", JSON.toJSON(result)));
sbLog.append(String.format("耗時:%ss", endTime - startTime));
} catch (Exception ex) {
sbLog.append(String.format("異常:%s", ex.getMessage()));
} finally {
logger.info(sbLog.toString());
}
return result;
}
復制代碼
此刻主要代碼就完成了,再來我們配置下日誌的記錄方式;首先在 resources目錄增加名為logback-spring.xml的文件,其配置信息如:
復制代碼
1
2
6
7
8
9
10
11
12
13
14
15 logback
16
17
18
21
22 %d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n
23
24
25
26
27 ${logPathAll}
28
29 ${logPathAll}.%d{yyyy-MM-dd}.zip
30
31
32 %date %level [%thread] %logger{36} [%file : %line] %msg%n
33
34
35
36
37
38
39
40
41
42
復制代碼
然後application.yml的配置信息如:
復制代碼
1 logging:
2 config: classpath:logback-spring.xml
3 logback:
4 level: info #info ,debug
5 path: /home/app/data/applogs/weblog
6 appname: web
復制代碼
此刻日誌和公共的aop記錄類都完成了,我們需要創建個測試用例,其代碼如:
復制代碼
1 @PostMapping("/addUser")
2 public ResponseEntity addUser(@RequestBody MoStudent moStudent) throws Exception {
3 moStudent.setNumber(UUID.randomUUID().toString());
4 // throw new Exception("錯誤了");
5 return new ResponseEntity<>(moStudent, HttpStatus.OK);
6 }
復制代碼
最後,通過postman模擬post請求,能夠得到如下的日誌結果:
上面的方式切入點是所有方法,所有方法都記錄日誌可能有是不是需求想要的,此時可以通過註解的方式來標記想記錄日誌的方法;先來創建個日誌註解:
復制代碼
1 @Target(ElementType.METHOD)
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 public @interface LogAnnotation {
5 /**
6 * 描述
7 *
8 * @return
9 */
10 String des() default "";
11 }
復制代碼
同樣再來創建註解的切入點:
復制代碼
1 //匹配方法上包含此註解的方法
2 private final String annotationPointCut = "@annotation(com.platform.Aop.LogAnnotation)";
3
4 //註解切點
5 @Pointcut(value = annotationPointCut)
6 public void logAnnotation() {
7 }
復制代碼
再通過@Around註解綁定具體的操作方法:
復制代碼
1 @Around(value = "logAnnotation()")
2 public Object aroundAnnotation(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
3 Object result = null;
4 StringBuilder sbLog = new StringBuilder("\n");
5 try {
6 sbLog.append(String.format("類名:%s\r\n", proceedingJoinPoint.getTarget().getClass().getName()));
7
8 MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
9 Method method = methodSignature.getMethod();
10 LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
11 if (logAnnotation != null && !logAnnotation.des().isEmpty()) {
12 sbLog.append(String.format("說明:%s\r\n", logAnnotation.des()));
13 }
14 sbLog.append(String.format("方法:%s\r\n", method.getName()));
15
16 Object[] args = proceedingJoinPoint.getArgs();
17 for (Object o : args) {
18 sbLog.append(String.format("參數:%s\r\n", JSON.toJSON(o)));
19 }
20
21 long startTime = System.currentTimeMillis();
22 result = proceedingJoinPoint.proceed();
23 long endTime = System.currentTimeMillis();
24 sbLog.append(String.format("返回:%s\r\n", JSON.toJSON(result)));
25 sbLog.append(String.format("耗時:%ss", endTime - startTime));
26 } catch (Exception ex) {
27 sbLog.append(String.format("異常:%s", ex.getMessage()));
28 } finally {
29 logger.info(sbLog.toString());
30 }
31 return result;
32 }
復制代碼
這個方法裏需要註意的是註解方式相比第一種其實就多了如下幾行代碼:
1 Method method = methodSignature.getMethod();
2 LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
3 if (logAnnotation != null && !logAnnotation.des().isEmpty()) {
4 sbLog.append(String.format("說明:%s\r\n", logAnnotation.des()));
5 }
下面是註解測試用例:
復制代碼
1 @LogAnnotation(des = "註解記錄日誌")
2 @PostMapping("/addUser01")
3 public ResponseEntity addUser01(@RequestBody MoStudent moStudent) throws Exception {
4 moStudent.setNumber(UUID.randomUUID().toString());
5 return new ResponseEntity<>(moStudent, HttpStatus.OK); 歡迎工作一到五年的Java工程師朋友們加入Java群: 891219277
群內提供免費的Java架構學習資料(裏面有高可用、高並發、高性能及分布式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!
6 }
復制代碼
復制代碼
springboot+aop切點記錄請求和響應信息