tft每日頭條

 > 生活

 > 利用AOP打印接口入參和出參

利用AOP打印接口入參和出參

生活 更新时间:2025-02-23 06:05:11

首先我們需要了解AOP和反射的原理,我這裡主要是實戰的開發,所以就隻對AOP和反射進行簡單的概述。

AOP指的是面向切面進行編程,就是正對某一個平面進行豎向的切割,生活中的例子就好比我們每次吃飯前都要洗手一樣,這個洗手的動作就是我們需要在切面進行的方法,而吃飯前就是類似一個切面。

反射指的是利用類加載器加載的類對象反射出該類的屬性,方法和注解。比如說我想買個華為手機的電池,可是我又不知道該買怎麼樣的電池,就可以打電話給華為官網的客服小姐姐,她就會告訴你電池的型号,并且會提供給你具體的購買渠道和地址,這就是一個簡單的小例子。

1.我們需要引入支持AOP編程的jar包

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

2.新建一個LogAspectConfiguration配置類,加上支持面向切面的aspect注解

@Component//spring 組件注解 @Aspect//支持面向切面的注解 @Slf4j//lombor的日志注解 public class LogAspectConfiguration { String controllerName;//保存我們請求的controller類的類名 String method;//保存我們請求的方法名 }

3.建立我們需要切入的切點已經切入的範圍

@Component//spring 組件注解 @Aspect//支持面向切面的注解 @Slf4j//lombor的日志注解 public class LogAspectConfiguration { String controllerName;//保存我們請求的controller類的類名 String method;//保存我們請求的方法名 @PointCut("execution(public * com. *.*(..))")//建立切點并标注範圍 public void webLog(); }

  1. 開始建立我們的請求建言(俗稱通知),我這裡指使用了before和afterreturn,因為隻需要打印請求參數和返回參數,其實還有after,afterthrows和around三種啦。

@Component//spring 組件注解 @Aspect//支持面向切面的注解 聲明是一個切面 @Slf4j//lombor的日志注解 public class LogAspectConfiguration { String controllerName;//保存我們請求的controller類的類名 String method;//保存我們請求的方法名 @PointCut("execution(public * com. *.*(..))")//建立切點并标注範圍 public void webLog(); @Before("webLog()")//在請求方法之前訪問 public void before(JoinPoint joinPoint) { } @AfterReturn("webLog()")//在請求方法之後訪問 public void afterReturn(JoinPoint joinPoint, Object obj) { } }

  1. 開始寫我們對請求在方法調用之前進行邏輯處理和日志打印,這裡我就不墨迹了,詳細的作用我會在用注釋進行說明

@Before("logWeb()") public void before(JoinPoint joinPoint){ ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest();//獲取httpservletrequest //反射獲取目标類的全名 controllerName = joinPoint.getTarget().getClass().getName();//通過目标類反射獲取目标類的全名 controllerName = controllerName.substring(controllerName.lastIndexOf(".") 1,controllerName.length());//截取全名 獲得當前包的類名 //利用路勁查找處理的方法 method = request.getRequestURL().toString(); if(method.endsWith("html")){ method = method.substring(method.lastIndexOf("/") 1,method.lastIndexOf(".")); }else{ method = method.substring(method.lastIndexOf("/") 1,method.length()); } log.info("準備進入" controllerName "類下" method "方法"); //獲取請求的所有參數 Object[] objects = joinPoint.getArgs(); for(Object obj:objects){ //去除參數中的LinkedHashMap if(obj instanceof LinkedHashMap){ continue; } if(obj!=null){ //将對象轉成json格式 并進行日志的打印 JSONObject result = JSONObject.fromObject(obj); log.info("請求" controllerName "類下" method "方法的參數為;" result); } } }

這裡會有一個疑問,為什麼我需要單獨去除參數裡面的linkedhashmap呢?其實在springMVC中,spring會默認的幫我們在請求目标對象的參數數組中建立一個linkedhashmap,用于存放返回的值,他加入的值大家應該都很熟悉,就是model和map,由于是請求過來的參數,所以我們直接把他過濾掉。如果你們的請求參數中包含list,請再添加一個判斷obj instanceof list,想打印請求的路徑和一些其他的請求信息,可以通過request自由打印,我這裡不需要就沒打印了。

  1. 書寫放回方法之後的參數打印,這裡我們需要注意一點,springMVC的方法放回一般有兩種,一種是spring放回的是一個頁面,參數通常放在model裡面,還有一種是用@responsebody返回的一個對象(當然實際上轉化為json格式的string),我們利用放射判斷是否獲取到@repsonsebody這個注解來判斷兩中情況

//返回通知 @AfterReturning(value = "logWeb(),returning = "retVal") public void after(JoinPoint joinPoint,Object retVal) { log.info("已經完成" controllerName "類下" method "方法的調用"); //反射獲取類加載器加載的目标對象類 Class objectClass = joinPoint.getTarget().getClass(); //反射獲取目标對象所有的可見方法 Method[] methods = objectClass.getDeclaredMethods(); Method methodReal = null; //前提你映射的mapper和類名必須保持一緻 才可判斷類型 for (Method classMethod : methods) { if (classMethod.getName().equals(method)) { methodReal = classMethod; break; } } Object object = methodReal.getAnnotation(ResponseBody.class); //判斷是否是responsebody标簽注解的類 if(object!=null){ //存在repsonsebody注解 則直接進行将整個放回值進行打印 JSONArray result = JSONArray.fromObject(retVal); }else{ //不存在,則将model裡面的所有參數進行打印 Object[] objects = joinPoint.getArgs(); for(Object obj:objects){ if(obj instanceof LinkedHashMap){ Iterator interator = ((LinkedHashMap) obj).keySet().iterator(); while(interator.hasNext()){ Object key = interator.next(); //判斷是否為驗證對象 if(key.toString().contains("BindingResult")){ continue; } Object value = ((LinkedHashMap) obj).get(key); //如果放回值包含list 則進行list的json轉化 if(value instanceof List){ JSONArray arrayResult = JSONArray.fromObject(value); log.info("請求完成後" controllerName "類下" method "方法的返回參數為;" arrayResult); }else{ JSONObject result = JSONObject.fromObject(value); log.info("請求完成後" controllerName "類下" method "方法的返回參數為;" result); } } } } } }

效果圖如下:

利用AOP打印接口入參和出參(利用AOP打印接口入參和出參)1

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved