SpringBoot開(kāi)發(fā)教程之AOP日志處理
日志處理:
需求分析
日志處理需要記錄的是:
- 請(qǐng)求的URL
- 訪問(wèn)者IP
- 調(diào)用的方法
- 傳入的參數(shù)
- 返回的內(nèi)容
上面的內(nèi)容要求在控制臺(tái)和日志中輸出。
在學(xué)習(xí)這部分知識(shí)的時(shí)候,真的感覺(jué)收獲很多,在之前Spring學(xué)習(xí)的aop只是初步了解,現(xiàn)在有了一些深入的理解。好記性不如爛筆頭!
在日志處理這部分主要是aop的使用,通過(guò)切面的方式來(lái)整合到項(xiàng)目了,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開(kāi)發(fā)的效率。
人話:Aop 在不改變?cè)写a的情況下 , 去增加新的功能
需要了解的:
- 橫切關(guān)注點(diǎn):跨越應(yīng)用程序多個(gè)模塊的方法或功能。即是,與我們業(yè)務(wù)邏輯無(wú)關(guān)的,但是我們需要關(guān)注的部分,就是橫切關(guān)注點(diǎn)。如日志 , 安全 , 緩存 , 事務(wù)等等 ....
- 切面(ASPECT):橫切關(guān)注點(diǎn) 被模塊化 的特殊對(duì)象。即,它是一個(gè)類(lèi)。
- 通知(Advice):切面必須要完成的工作。即,它是類(lèi)中的一個(gè)方法。
- 切入點(diǎn)(PointCut):切面通知 執(zhí)行的 “地點(diǎn)”的定義。
- 連接點(diǎn)(JointPoint):與切入點(diǎn)匹配的執(zhí)行點(diǎn)。
通知(Advice)里面還有幾種方法來(lái)幫助實(shí)現(xiàn),這里我列舉了該部分實(shí)現(xiàn)的方法:
- doBefore方法(方法前執(zhí)行),需要注解@Before實(shí)現(xiàn)
- After方法(方法后執(zhí)行),需要注解@After實(shí)現(xiàn)
- doAfterReturning方法,需要注解@AfterReturning實(shí)現(xiàn)
具體實(shí)現(xiàn)看后面部分。
重要部分:導(dǎo)入依賴
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <scope>test</scope> </dependency>
提醒:導(dǎo)入包以后,刷新下Maven,如果運(yùn)行的時(shí)候找不到包,重啟試試,網(wǎng)上有很多的解決方法(也試過(guò)),最后個(gè)人只是重啟一下子再刷新下maven就可以使用了。
這里就沒(méi)有給出解決方法,只是一個(gè)提醒。
實(shí)現(xiàn)過(guò)程:
創(chuàng)建一個(gè)類(lèi)(LogAspect),將該類(lèi)定義成一個(gè)切面(@Aspect)并且加入容器中(@Component)。
首先創(chuàng)建一個(gè)切入點(diǎn),后面的Advice是建立在切入點(diǎn)上:
@Pointcut("execution(* com.blog.Controller..*.*(..))") public void log(){}
整個(gè)表達(dá)式可以分為五個(gè)部分
1、execution():表達(dá)式主體。
2、第一個(gè)*號(hào):表示返回類(lèi)型,*號(hào)表示所有的類(lèi)型。
3、包名:表示需要攔截的包名,后面的兩個(gè)句點(diǎn)分別表示當(dāng)前包和當(dāng)前包的所有子包,com.blog.Controller包、子孫包下所有類(lèi)的方法。
4、第二個(gè)*號(hào):表示類(lèi)名,*號(hào)表示所有的類(lèi)。
5、*(..) :第三個(gè)星號(hào)表示方法名,*號(hào)表示所有的方法,后面括弧里面表示方法的參數(shù),兩個(gè)句點(diǎn)表示任何參數(shù)
定義完切入點(diǎn)后,處理前置通知和后置通知:
@Before("log()") public void doBefore(JoinPoint joinPoint){ System.out.println("在進(jìn)入controller之前處理流-------------"); } @After("log()") public void doAfter(){ System.out.println("在進(jìn)入controller之后處理流-------------"); } //在切入點(diǎn)return內(nèi)容之后切入內(nèi)容(可以用來(lái)對(duì)處理返回值做一些加工處理) @AfterReturning(returning = "result",pointcut="log()") public void doAfterReturning(Object result){ logger.info("Return ------ {}",result ); }
通過(guò)上述的簡(jiǎn)單介紹,可以知道我們?nèi)绻枰佬枨罄锩娴囊?,我們的重點(diǎn)應(yīng)該放到前置通知里面,在流處理之前獲取前端操作的信息。
核心代碼如下:
//通過(guò)上下文來(lái)獲取請(qǐng)求里面的信息 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //獲取封裝了署名信息的對(duì)象,在該對(duì)象中可以獲取到目標(biāo)方法名,所屬類(lèi)的Class等信息(反射) String classMethod = joinPoint.getSignature().getDeclaringTypeName()+","+joinPoint.getSignature().getName(); // 1. 獲取URL String url = request.getRequestURL().toString(); //2. 獲取ip地址 String addr = request.getRemoteAddr(); /*創(chuàng)建一個(gè)類(lèi)RequestData,來(lái)保存相關(guān)信息*/ RequestData requestData = new RequestData( url, addr, classMethod, joinPoint.getArgs() ); //在控制臺(tái)打印出來(lái) logger.info("RequestData------{}",requestData);
創(chuàng)建的類(lèi)是內(nèi)部類(lèi)(RequestData),只是封裝一下需要打印的信息。
實(shí)驗(yàn)效果:
在進(jìn)入controller之前處理流-------------
2021-08-15 15:19:43.923 INFO 9644 --- [nio-8080-exec-1] com.blog.AspectAop.LogAspect : RequestData------RequestData{url='http://localhost:8080/', ipAddr='0:0:0:0:0:0:0:1', classMethod='com.blog.Controller.IndexController,index', args=[]}
2021-08-15 15:19:43.932 INFO 9644 --- [nio-8080-exec-1] com.blog.AspectAop.LogAspect : Return ------ index
在進(jìn)入controller之后處理流-------------
參考文獻(xiàn):
狂神說(shuō)Spring
總結(jié)
到此這篇關(guān)于SpringBoot開(kāi)發(fā)教程之AOP日志處理的文章就介紹到這了,更多相關(guān)SpringBoot AOP日志處理 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java synchronized重量級(jí)鎖實(shí)現(xiàn)過(guò)程淺析
這篇文章主要介紹了Java synchronized重量級(jí)鎖實(shí)現(xiàn)過(guò)程,synchronized是Java里的一個(gè)關(guān)鍵字,起到的一個(gè)效果是"監(jiān)視器鎖",它的功能就是保證操作的原子性,同時(shí)禁止指令重排序和保證內(nèi)存的可見(jiàn)性2023-02-02在Spring Boot中使用Spring-data-jpa實(shí)現(xiàn)分頁(yè)查詢
如何使用jpa進(jìn)行多條件查詢以及查詢列表分頁(yè)呢?下面我將介紹兩種多條件查詢方式。具體實(shí)例代碼大家參考下本文吧2017-07-07MyBatis Map結(jié)果的Key轉(zhuǎn)為駝峰式
今天小編就為大家分享一篇關(guān)于MyBatis Map結(jié)果的Key轉(zhuǎn)為駝峰式,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12Java SSM整合開(kāi)發(fā)統(tǒng)一結(jié)果封裝詳解
這篇文章主要介紹了Java SSM整合開(kāi)發(fā)實(shí)現(xiàn)統(tǒng)一結(jié)果封裝,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Java CharacterEncodingFilter案例詳解
這篇文章主要介紹了Java CharacterEncodingFilter案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08Java創(chuàng)建線程三種方式的優(yōu)缺點(diǎn)
今天小編就為大家分享一篇關(guān)于Java創(chuàng)建線程三種方式的優(yōu)缺點(diǎn),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12