spring-AOP 及 AOP獲取request各項(xiàng)參數(shù)操作
spring-AOP 及 AOP獲取request各項(xiàng)參數(shù)
AOP稱為面向切面編程,在程序開發(fā)中主要用來解決一些系統(tǒng)層面上的問題,比如日志,事務(wù),權(quán)限等待。
一、AOP的基本概念
Aspect(切面):通常是一個(gè)類,里面可以定義切入點(diǎn)和通知JointPoint(連接點(diǎn)):程序執(zhí)行過程中明確的點(diǎn),一般是方法的調(diào)用Advice(通知):AOP在特定的切入點(diǎn)上執(zhí)行的增強(qiáng)處理,有before,after,afterReturning,afterThrowing,aroundPointcut(切入點(diǎn)):就是帶有通知的連接點(diǎn),在程序中主要體現(xiàn)為書寫切入點(diǎn)表達(dá)式AOP代理:AOP框架創(chuàng)建的對(duì)象,代理就是目標(biāo)對(duì)象的加強(qiáng)。Spring中的AOP代理可以使JDK動(dòng)態(tài)代理,也可以是CGLIB代理,前者基于接口,后者基于子類
二、Spring AOP
Spring中的AOP代理還是離不開Spring的IOC容器,代理的生成,管理及其依賴關(guān)系都是由IOC容器負(fù)責(zé),Spring默認(rèn)使用JDK動(dòng)態(tài)代理,在需要代理類而不是代理接口的時(shí)候,Spring會(huì)自動(dòng)切換為使用CGLIB代理,不過現(xiàn)在的項(xiàng)目都是面向接口編程,所以JDK動(dòng)態(tài)代理相對(duì)來說用的還是多一些。
三、基于注解的AOP配置方式
1.啟用@AsjectJ支持
在spring配置中配置下面一句:
<aop:aspectj-autoproxy />
或者使用注解:
@EnableAspectJAutoProxy
2.通知類型介紹
(1) Before:在目標(biāo)方法被調(diào)用之前做增強(qiáng)處理,@Before只需要指定切入點(diǎn)表達(dá)式即可
(2) AfterReturning:在目標(biāo)方法正常完成后做增強(qiáng),@AfterReturning除了指定切入點(diǎn)表達(dá)式后,還可以指定一個(gè)返回值形參名returning,代表目標(biāo)方法的返回值
(3) AfterThrowing:主要用來處理程序中未處理的異常,@AfterThrowing除了指定切入點(diǎn)表達(dá)式后,還可以指定一個(gè)throwing的返回值形參名,可以通過該形參名
來訪問目標(biāo)方法中所拋出的異常對(duì)象
(4) After:在目標(biāo)方法完成之后做增強(qiáng),無論目標(biāo)方法時(shí)候成功完成。@After可以指定一個(gè)切入點(diǎn)表達(dá)式
(5) Around:環(huán)繞通知,在目標(biāo)方法完成前后做增強(qiáng)處理,環(huán)繞通知是最重要的通知類型,像事務(wù),日志等都是環(huán)繞通知,注意編程中核心是一個(gè)ProceedingJoinPoint
3.通知執(zhí)行的優(yōu)先級(jí)
進(jìn)入目標(biāo)方法時(shí),先織入Around,再織入Before,退出目標(biāo)方法時(shí),先織入Around,再織入AfterReturning,最后才織入After。
注意:Spring AOP的環(huán)繞通知會(huì)影響到AfterThrowing通知的運(yùn)行,不要同時(shí)使用!同時(shí)使用也沒啥意義。
4.切入點(diǎn)的定義和表達(dá)式
切入點(diǎn)表達(dá)式的定義算是整個(gè)AOP中的核心,有一套自己的規(guī)范
Spring AOP支持的切入點(diǎn)指示符:
execution:用來匹配執(zhí)行方法的連接點(diǎn)
A:@Pointcut(“execution(* com.aijava.springcode.service….(…))”)
第一個(gè)表示匹配任意的方法返回值,…(兩個(gè)點(diǎn))表示零個(gè)或多個(gè),上面的第一個(gè)…表示service包及其子包,第二個(gè)表示所有類,第三個(gè)*表示所有方法,第二個(gè)…表示
方法的任意參數(shù)個(gè)數(shù)
B:@Pointcut(“within(com.aijava.springcode.service.*)”)
within限定匹配方法的連接點(diǎn),上面的就是表示匹配service包下的任意連接點(diǎn)
C:@Pointcut(“this(com.aijava.springcode.service.UserService)”)
this用來限定AOP代理必須是指定類型的實(shí)例,如上,指定了一個(gè)特定的實(shí)例,就是UserService
D:@Pointcut(“bean(userService)”)
bean也是非常常用的,bean可以指定IOC容器中的bean的名稱
下面是一個(gè)使用AOP獲取統(tǒng)計(jì)計(jì)算方法執(zhí)行時(shí)間以及獲取request請(qǐng)求參數(shù)等信息的log方法:
/**
* description:
* 統(tǒng)計(jì)請(qǐng)求執(zhí)行時(shí)間
*
* @author wkGui
*/
@Component
@Aspect
public class ResExeTimeCounter {
private static Logger logger = LoggerFactory.getLogger(ResExeTimeCounter.class);
@Pointcut("execution(* com.wk.controller..*.*(..))")
public void pointCut() {
}
@Around("pointCut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
assert sra != null;
HttpServletRequest request = sra.getRequest();
String url = request.getRequestURL().toString();
String method = request.getMethod();
String queryString = request.getQueryString();
long startTime = System.currentTimeMillis();
logger.info("{url:{}, method:{}, queryString:{}}", url, method, queryString);
Object rs;
boolean successAble = false;
JsonObject paramsJson = new JsonObject();
try {
Object[] params = pjp.getArgs();
for (int i = 0; i < params.length; i++) {
if (params[i] instanceof BindingResult
|| params[i] instanceof HttpRequest
|| params[i] instanceof HttpResponse){
continue;
}
paramsJson.addProperty("param-" + i, JsonUtil.toJsonWtihNullField(params[i]));
}
rs = pjp.proceed();
successAble = true;
} finally {
logger.info("{url:{}, method:{}, success-able:{}, exe-time:{}, params:{}}", url, method, successAble, System.currentTimeMillis() - startTime, paramsJson);
}
return rs;
}
}
SpringAOP獲取request中所有參數(shù),記錄用戶操作日志
今天搞了一個(gè)AOP的管理日志,蛋疼的很....
老規(guī)矩貼代碼吧

首先除了aop的包以外需要這三個(gè)包。
自行度娘。

如果想切入controllers,請(qǐng)將這個(gè)代碼寫入你的mvc配置中,糾結(jié)了一上午切不進(jìn)去就是這個(gè)原因.

method為你切入類的方法名

可以照這個(gè)打個(gè)模版出來,PS:無視注釋哈,逼死強(qiáng)迫癥

因?yàn)槲业目刂祁惱锩嬷粫?huì)有兩個(gè)參數(shù)request和response ,所以我這里request就直接等于了下標(biāo)為0,
下面的
Enumeration parameter = request.getParameterNames();
while(parameter.hasMoreElements()) {
String a=(String) parameter.nextElement();
System.out.println(request.getParameter(a));
}
可以獲取從頁面上傳過來的所有參數(shù)以及參數(shù)名,參數(shù):request.getParameter(a),參數(shù)名:a
上面的代碼放在aop中實(shí)測(cè)可以,但如果放在攔截器中,實(shí)測(cè)會(huì)返回一個(gè)date,不知道什么鬼,get請(qǐng)求的話偶爾會(huì)正常。post一定不正常,aop中無問題
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot webflux 過濾器(使用RouterFunction實(shí)現(xiàn))
這篇文章主要介紹了springboot webflux 過濾器(使用RouterFunction實(shí)現(xiàn)),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
深入淺析springboot中static和templates區(qū)別
這篇文章主要介紹了springboot中static和templates區(qū)別,本文通過圖文實(shí)例代碼相結(jié)合給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Spring?security?oauth2以redis作為tokenstore及jackson序列化失敗問題
這篇文章主要介紹了Spring?security?oauth2以redis作為tokenstore及jackson序列化失敗問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教<BR>2024-04-04
理解 MyBatis 是如何在 Spring 容器中初始化的
這篇文章主要介紹了理解 MyBatis 是如何在 Spring 容器中初始化的,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
RocketMQ?offset確認(rèn)機(jī)制示例詳解
這篇文章主要為大家介紹了RocketMQ?offset確認(rèn)機(jī)制示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
SpringBoot使用validation做參數(shù)校驗(yàn)說明
這篇文章主要介紹了SpringBoot使用validation做參數(shù)校驗(yàn)說明,首先通過添加hibernate-validator展開全文內(nèi)容,具有一定的參考價(jià)值,需要的小伙伴可以參考與喜愛2022-04-04
java 使用DecimalFormat進(jìn)行數(shù)字的格式化實(shí)例詳解
這篇文章主要介紹了java 使用DecimalFormat進(jìn)行數(shù)字的格式化實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-06-06

