新四季網

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

2023-09-20 05:57:07

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

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

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

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

org.springframework.boot spring-boot-starter-aop

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;}

開始建立我們的請求建言(俗稱通知),我這裡指使用了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) { }}

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

@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自由列印,我這裡不需要就沒列印了。

書寫放回方法之後的參數列印,這裡我們需要注意一點,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); } } } } }}

效果圖如下:

,
同类文章
葬禮的夢想

葬禮的夢想

夢見葬禮,我得到了這個夢想,五個要素的五個要素,水火只好,主要名字在外面,職業生涯良好,一切都應該對待他人治療誠意,由於小,吉利的冬天夢想,秋天的夢是不吉利的
找到手機是什麼意思?

找到手機是什麼意思?

找到手機是什麼意思?五次選舉的五個要素是兩名士兵的跡象。與他溝通很好。這是非常財富,它擅長運作,職業是仙人的標誌。單身男人有這個夢想,主要生活可以有人幫忙
我不怎麼想?

我不怎麼想?

我做了什麼意味著看到米飯烹飪?我得到了這個夢想,五線的主要土壤,但是Tu Ke水是錢的跡象,職業生涯更加真誠。他真誠地誠實。這是豐富的,這是夏瑞的巨星
夢想你的意思是什麼?

夢想你的意思是什麼?

你是什​​麼意思夢想的夢想?夢想,主要木材的五個要素,水的跡象,主營業務,主營業務,案子應該抓住魅力,不能疏忽,春天夢想的吉利夢想夏天的夢想不幸。詢問學者夢想
拯救夢想

拯救夢想

拯救夢想什麼意思?你夢想著拯救人嗎?拯救人們的夢想有一個現實,也有夢想的主觀想像力,請參閱週宮官方網站拯救人民夢想的詳細解釋。夢想著敵人被拯救出來
2022愛方向和生日是在[質量個性]中

2022愛方向和生日是在[質量個性]中

[救生員]有人說,在出生88天之前,胎兒已經知道哪天的出生,如何有優質的個性,將走在什麼樣的愛情之旅,將與生活生活有什么生活。今天
夢想切割剪裁

夢想切割剪裁

夢想切割剪裁什麼意思?你夢想切你的手是好的嗎?夢想切割手工切割手有一個真正的影響和反應,也有夢想的主觀想像力。請參閱官方網站夢想的細節,以削減手
夢想著親人死了

夢想著親人死了

夢想著親人死了什麼意思?你夢想夢想你的親人死嗎?夢想有一個現實的影響和反應,還有夢想的主觀想像力,請參閱夢想世界夢想死亡的親屬的詳細解釋
夢想搶劫

夢想搶劫

夢想搶劫什麼意思?你夢想搶劫嗎?夢想著搶劫有一個現實的影響和反應,也有夢想的主觀想像力,請參閱週恭吉夢官方網站的詳細解釋。夢想搶劫
夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂

夢想缺乏缺乏紊亂什麼意思?你夢想缺乏異常藥物嗎?夢想缺乏現實世界的影響和現實,還有夢想的主觀想像,請看官方網站的夢想組織缺乏異常藥物。我覺得有些東西缺失了