[轉(zhuǎn)載]springboot aop攔截脑融、修改請求參數(shù)

前言
最近有這么個功能缩宜,由于使用了thymeleaf锻煌,多個頁面遇到要使用同一個數(shù)據(jù)的問題,但是如果在每個Controller下都要向Model放數(shù)據(jù)匣沼,那么就有很多重復(fù)代碼捂龄,不太優(yōu)雅倦沧,所以想到了AOP,在進(jìn)入方法前取到Model實例局荚,向他增加數(shù)據(jù)即可愈污。

引入依賴
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-aop</artifactId>
 </dependency>

doBefore中的代碼也可以放入到@After下執(zhí)行暂雹。

@Aspect
@Component
public class ResultAop {

    @Pointcut("execution(public * com.he.edu.edu.controller.IndexController.*(..)))")
    public void BrokerAspect(){

    }

    @Before("BrokerAspect()")
    public void doBefore(JoinPoint joinPoint){
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof Model){
                Model model = (Model) arg;
                model.addAttribute("test","存放公共參數(shù)");
            }
        }
    }


    @After("BrokerAspect()")
    public void doAfter(JoinPoint joinPoint){

    }

}
@Controller
public class IndexController {
    Logger logger = LoggerFactory.getLogger(IndexController.class);
    
     @GetMapping("test")
     public String test(Model model){
         logger.info("{}",model.getAttribute("test"));
         return "test";
     }
 }
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div th:text="${test}"></div>
</body>
</html>

這樣杭跪,每個方法下的Model中都有了這份數(shù)據(jù)涧尿,取出渲染即可。


image.png

獲取請求參數(shù)
我們可以通過RequestContextHolder獲取url中的參數(shù)缺亮,RequestContextHolder就是一個典型的ThreadLocal應(yīng)用萌踱,用于在當(dāng)前線程中獲取當(dāng)前請求及其屬性,如果要在service層中使用request鸳粉,或者其他任何地方园担,都可以直接調(diào)用RequestContextHolder來獲取request對象和response對象粉铐。

@Aspect
@Component
public class TestAop {
    private Logger logger = LoggerFactory.getLogger(TestAop.class);
    @Pointcut("execution(public * com.he.edu.edu.controller.IndexController.*(..)))")
    public void BrokerAspect(){

    }

    @Before("BrokerAspect()")
    public void doBefore(JoinPoint joinPoint){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        logger.info("URL參數(shù)={}",requestAttributes.getRequest().getQueryString());

    }

}
  @GetMapping("test")
  public String test(Model model,@RequestParam("id") Integer id){
      logger.info("id={}",id);
      model.addAttribute("test",id);
      return "test";
  }
image.png

修改請求參數(shù)
可以利用@Around來修改請求參數(shù)蝙泼,@Around功能非常強(qiáng)大汤踏,作用如下:

可以在目標(biāo)方法之前增加邏輯舔腾,也可以在執(zhí)行目標(biāo)方法之后增加邏輯.
可以決定目標(biāo)方法在什么時候執(zhí)行稳诚,如何執(zhí)行,也可以阻止目標(biāo)目標(biāo)方法執(zhí)行.
可以改變執(zhí)行目標(biāo)方法的參數(shù)值才避,也可以改變執(zhí)行目標(biāo)方法之后的返回值.
使用ProceedingJoinPoint時如果要改變參數(shù)氨距,必須調(diào)用 proceed(Object[] var1)方法俏让,傳入新的參數(shù)數(shù)組首昔,數(shù)組元素類型必須和目標(biāo)方法相互對應(yīng),否則會報ClassCastException異常预鬓。

下面是將傳入的id擴(kuò)大十倍撬陵。

@Aspect
@Component
public class TestAop {
    private Logger logger = LoggerFactory.getLogger(TestAop.class);
    @Pointcut("execution(public * com.he.edu.edu.controller.IndexController.*(..)))")
    public void BrokerAspect(){

    }

    @Around("BrokerAspect()")
    public void doAround(ProceedingJoinPoint proceedingJoinPoint){
        Object[] sourceObject =proceedingJoinPoint.getArgs();
        sourceObject[1] =new Integer(((Integer) sourceObject[1])*10);
        try {
            proceedingJoinPoint.proceed(sourceObject);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

}
 @GetMapping("test")
 public String test(Model model,@RequestParam("id") Integer id){
     logger.info("id={}",id);
     model.addAttribute("test",id);
     return "test";
 }
image.png

修改返回值
proceed方法的返回值就是目標(biāo)方法的返回值蟋定,我們可以拿到他做一些修改驶兜,或者返回新的數(shù)據(jù)。

下面加了ResponseBody注解屠凶,會將對象轉(zhuǎn)換成json矗愧,將返回user1唉韭,user2犯犁,user3酸役。

 @GetMapping("listUser")
 @ResponseBody
 public List<String> listUser(){
     return Stream.of("user1","user2","user3").collect(Collectors.toList());
 }

在切入點(diǎn)進(jìn)行修改,返回user4贱呐,user5吼句,user6惕艳。

 @Around("BrokerAspect()")
 public Object doAround(ProceedingJoinPoint proceedingJoinPoint){
     try {
         Object proceed = proceedingJoinPoint.proceed();
         return Stream.of("user4","user5","user6").collect(Collectors.toList());
     } catch (Throwable throwable) {
         throwable.printStackTrace();
     }
     return  null;
 }
image.png

打印帶有指定注解方法的參數(shù)
首先自定義一個注解远搪,最終將做到打印標(biāo)有這個注解的請求參數(shù)谁鳍。

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodLog {
}
@MethodLog
@GetMapping("log")
public String log(Model model,@RequestParam("id") Integer id){

    model.addAttribute("test",id);
    return "test";
}
@GetMapping("noLog")
public String noLog(Model model,@RequestParam("id") Integer id){

    model.addAttribute("test",id);
    return "test";
}

接下來取到目標(biāo)方法倘潜,從方法中判斷是否存有MethodLog注解涮因,有的話就通過RequestContextHolder來獲取請求參數(shù)养泡。

@Before("BrokerAspect()")
public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException {
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature)signature;
    Method targetMethod = methodSignature.getMethod();
    if (((MethodSignature) joinPoint.getSignature()).getMethod().getDeclaredAnnotation(MethodLog.class)!=null){
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        logger.info("URL參數(shù)={}",requestAttributes.getRequest().getQueryString());
    }
}

訪問不帶注解方法時:

11.gif

訪問帶有注解方法時:

22.gif

版權(quán)聲明:本文為HouXinLin_CSDN原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議肩榕,轉(zhuǎn)載請附上原文出處鏈接和本聲明点把。
本文鏈接:https://blog.csdn.net/HouXinLin_CSDN/article/details/108430756

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市褒翰,隨后出現(xiàn)的幾起案子优训,更是在濱河造成了極大的恐慌揣非,老刑警劉巖早敬,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異琐驴,居然都是意外死亡绝淡,警方通過查閱死者的電腦和手機(jī)悬包,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門玉罐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潘拨,“玉大人吊输,你說我怎么就攤上這事√罚” “怎么了季蚂?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長琅束。 經(jīng)常有香客問我扭屁,道長,這世上最難降的妖魔是什么涩禀? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任料滥,我火速辦了婚禮,結(jié)果婚禮上艾船,老公的妹妹穿的比我還像新娘葵腹。我一直安慰自己,他們只是感情好屿岂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布践宴。 她就那樣靜靜地躺著,像睡著了一般爷怀。 火紅的嫁衣襯著肌膚如雪阻肩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天运授,我揣著相機(jī)與錄音烤惊,去河邊找鬼。 笑死徒坡,一個胖子當(dāng)著我的面吹牛撕氧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播喇完,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼伦泥,長吁一口氣:“原來是場噩夢啊……” “哼剥啤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起不脯,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤府怯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后防楷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牺丙,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年复局,在試婚紗的時候發(fā)現(xiàn)自己被綠了冲簿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡亿昏,死狀恐怖峦剔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情角钩,我是刑警寧澤吝沫,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站递礼,受9級特大地震影響惨险,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脊髓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一辫愉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧将硝,春花似錦一屋、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽闸衫。三九已至涛贯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蔚出,已是汗流浹背弟翘。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留骄酗,地道東北人稀余。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像趋翻,于是被迫代替她去往敵國和親睛琳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容