spring AOP實現(xiàn)@Around輸出請求參數(shù)和返回參數(shù)
@Around輸出請求參數(shù)和返回參數(shù)
spring 的AOP是通過cglib動態(tài)代理和jdk的動態(tài)代理實現(xiàn)的。
先把我的打印日志代碼貼出來
package com.zhd.exploit.api.config; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.servlet.http.HttpServletResponseWrapper; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.servlet.mvc.method.annotation.ExtendedServletRequestDataBinder; import com.alibaba.fastjson.JSONObject; @Aspect @Component @Order(1) public class ControllerLogInterceptor { private static final Logger log = LoggerFactory.getLogger(ControllerLogInterceptor.class); //創(chuàng)建Pointcut表示式,表示所有controller請求 @Pointcut("execution(* com..*.controller..*(..))") private void controllerAspect() { }// 請求method前打印內(nèi)容 @Around(value = "controllerAspect()") public void around(ProceedingJoinPoint pjp) throws Throwable { //通過uuid關(guān)聯(lián)請求參數(shù)和返回參數(shù) String uuid = UUID.randomUUID().toString().replaceAll("-", ""); methodBefore(pjp, uuid); try { Object proceed = pjp.proceed(); methodAfterReturing(proceed, uuid); } catch (Exception e) { log.error("[{}]Response異常內(nèi)容:{}", uuid, e); throw e; } } public void methodBefore(JoinPoint joinPoint, String uuid) { // 打印請求內(nèi)容 try { // 下面兩個數(shù)組中,參數(shù)值和參數(shù)名的個數(shù)和位置是一一對應(yīng)的。 Object[] objs = joinPoint.getArgs(); String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); // 參數(shù)名 Map<String, Object> paramMap = new HashMap<String, Object>(); for (int i = 0; i < objs.length; i++) { if (!(objs[i] instanceof ExtendedServletRequestDataBinder) && !(objs[i] instanceof HttpServletResponseWrapper)) { paramMap.put(argNames[i], objs[i]); } } if (paramMap.size() > 0) { log.info("\n[{}]方法:{}\n參數(shù):{}", uuid, joinPoint.getSignature(), JSONObject.toJSONString(paramMap)); } } catch (Exception e) { log.error("[{}]AOP methodBefore:", uuid, e); } } public void methodAfterReturing(Object o, String uuid) { try { if (o != null) log.info("[{}]Response內(nèi)容:{}", uuid, JSONObject.toJSON(o)); } catch (Exception e) { log.error("[{}]AOP methodAfterReturing:", uuid, e); } } }
測試
請求參數(shù)類型1
?? ?@RequestMapping(value = "/test0", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE }) ?? ?public Result test0(@RequestParam String name, @RequestParam String password) { ?? ??? ?System.out.println("test0 OK"); ?? ??? ?return new Result("1", "mock a Result"); ?? ?}
打印日志:
[fe7155a3089b4dd7896b759a933cf958]方法:Result com.zhd.exploit.api.controller.TestController.test0(String,String)
參數(shù):{"password":"123","name":"zhang"}
請求參數(shù)類型2
?? ?@RequestMapping(value = "/test1", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE }) ?? ?public Result test1(PayDTO payDTO) { ?? ??? ?System.out.println("test1 OK"); ?? ??? ?return new Result("1", "mock a Result"); ?? ?}
打印日志:
[a2f7d19dea834c54a45b480bd4e8c3cd]方法:Result com.zhd.exploit.api.controller.TestController.test1(PayDTO)
參數(shù):{"payDTO":{"appmount":"10","paytype":"1"}}
請求參數(shù)類型3
?? ?@RequestMapping(value = "/test2", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE }) ?? ?public Result test2(@RequestBody PayDTO payDTO) { ?? ??? ?System.out.println("test2 OK"); ?? ??? ?return new Result("2", "mock a Result"); ?? ?}
打印日志:
[cd6a3d9d05244eee95bbf3c607d038cc]方法:Result com.zhd.exploit.api.controller.TestController.test2(PayDTO)
參數(shù):{"payDTO":{"appmount":"10","paytype":"1"}}
spring AOP中Around切面處理參數(shù)
最近遇到一個場景,在業(yè)務(wù)流程處理中,很多的方法都需要對傳入的參數(shù)對象做公共的處理【比如:添加編輯人信息】,而且這些傳入對象都繼承自一個父類,同時需要用到HttpServletRequest。
解決的辦法
使用自定義annotation+aop來實現(xiàn)預(yù)處理 具體的處理流程是
1、自定義一個annotation用于標(biāo)記需要處理的地方
2、創(chuàng)建切面類,在pointcut時對annotation進(jìn)行攔截,在@Around環(huán)繞通知里面獲取@annotation對應(yīng)的當(dāng)前對象,獲取當(dāng)前對象參數(shù),并修改參數(shù)內(nèi)容,然后proceed一下,繼續(xù)執(zhí)行
具體的代碼
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Operate { }
@Aspect @Component public class OperateInterceptor {? ? ? @Pointcut("@annotation(com.yili.web.entity.Operate)") ? ? public void interceptor() { ? ? } ? ? ? @Resource ? ? private SqlObjectUtil sqlObjectUtil; ? ? ? @Around(value = "interceptor()") ? ? public Object check(ProceedingJoinPoint pjp) throws Throwable { ? ? ? ? System.out.println("進(jìn)入interceptor"); ? ? ? ? Signature signature = pjp.getSignature(); ? ? ? ? if (!(signature instanceof MethodSignature)) { ? ? ? ? ? ? throw new IllegalArgumentException("該注解只適用于方法"); ? ? ? ? } ? ? ? ? Object[] objects = pjp.getArgs(); ? ? ? ? RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); ? ? ? ? ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) attributes; ? ? ? ? HttpServletRequest request = servletRequestAttributes.getRequest(); ? ? ? ? String loginToken = getLoginToken(request); ? ? ? ? ? ? ? ? for (int i=0;i<objects.length;i++){ ? ? ? ? ? ? if (SqlObject.class.isAssignableFrom(objects[i].getClass()))) { ? ? ? ? ? ? ? ? sqlObjectUtil.setOperatorInfo(loginToken,(SqlObject)objects[i]); ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return pjp.proceed(objects); ? ? }
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java 高并發(fā)七:并發(fā)設(shè)計模型詳解
本文主要介紹Java高并發(fā) 并發(fā)設(shè)計模型的知識,這里主要講解 1. 什么是設(shè)計模式 2. 單例模式 3. 不變模式 4. Future模式 5. 生產(chǎn)者消費者,有需要的小伙伴可以參考下2016-09-09SpringSecurity跨域請求偽造(CSRF)的防護(hù)實現(xiàn)
本文主要介紹了SpringSecurity跨域請求偽造(CSRF)的防護(hù)實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07java 定義長度為0的數(shù)組/空數(shù)組案例
這篇文章主要介紹了java 定義長度為0的數(shù)組/空數(shù)組案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03javascript與jsp發(fā)送請求到servlet的幾種方式實例
本文分別給出了javascript發(fā)送請求到servlet的5種方式實例與 jsp發(fā)送請求到servlet的6種方式實例2018-03-03Mybatis的mapper.xml中if標(biāo)簽test判斷的用法說明
這篇文章主要介紹了Mybatis的mapper.xml中if標(biāo)簽test判斷的用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06不寫mybatis的@Param有的報錯有的卻不報錯問題分析
這篇文章主要為大家介紹了不寫mybatis的@Param有的報錯有的卻不報錯問題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09java實現(xiàn)圖片水平和垂直翻轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)圖片水平和垂直翻轉(zhuǎn)效果,圖片旋轉(zhuǎn)的靈活運用,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-01-01Java數(shù)據(jù)結(jié)構(gòu)常見幾大排序梳理
Java常見的排序算法有:直接插入排序、希爾排序、選擇排序、冒泡排序、歸并排序、快速排序、堆排序等。本文詳解介紹它們的實現(xiàn)以及圖解,需要的可以參考一下2022-03-03