日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

记录请求的耗时(拦截器、过滤器、aspect)

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 记录请求的耗时(拦截器、过滤器、aspect) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

記錄請求的耗時(攔截器、過濾器、aspect)

文章前言

記錄控制器請求的耗時處理通常有三種實現方式,分別是:過濾器、攔截器、aspect;下文將逐一實現。

?

1、Filter 過濾器

1.1、方法說明

需要實現 Filter?類,主要涉及三個方法:
  • destory:銷毀
  • doFilter:處理過濾器邏輯
  • init:filter?初始化時調用
  • 1.2、代碼部分

    @Component //表明作為spring的一個bean public class TimeFilter implements Filter {@Overridepublic void destroy() {System.out.println("time filter destroy");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {System.out.println("time filter start");long start = new Date().getTime();//過濾器主要邏輯,整個處理流程 chain.doFilter(request, response);System.out.println("time filter 耗時:"+ (new Date().getTime() - start));System.out.println("time filter finish");}@Overridepublic void init(FilterConfig arg0) throws ServletException {System.out.println("time filter init");}}

    1.3、補充說明

    通過過濾器攔截請求的方式,有一個問題,只能拿到 http?的請求和響應(request、response),意味著只能在請求或者響應里獲取一些參數; 但是當前請求到底是哪個控制器的哪個方法處理的,在filter里是無法獲取的,因為實現的 Filter 這個接口是由javax(j2e)定義的, 而我們要攔截的控制器(Controller)中的請求是springmvc定義的,所以 Filter 是無法獲取 spring 相關信息。? 帶出下一個主角,Interceptor 攔截器,springmvc 提供。

    2、Interceptor 攔截器

    2.1、方法說明

    需要實現 HandlerInterceptor 類,主要涉及三個方法:
  • preHandle:請求方法之前被調用;
  • postHandle:控制器處理方法之后會被調用,前提是沒有拋出異常,拋出異常不會調用;
  • afterCompletion:請求方法之后被調用,該方法總會被調用,如果出現了異常,將被封裝到Exception對象中。
  • 2.2、代碼部分

    @Component public class TimeInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {System.out.println("preHandle");System.out.println(((HandlerMethod)handler).getBean().getClass().getName());System.out.println(((HandlerMethod)handler).getMethod().getName());request.setAttribute("startTime", new Date().getTime());return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("postHandle");Long start = (Long) request.getAttribute("startTime");System.out.println("time interceptor 耗時:"+ (new Date().getTime() - start));}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {System.out.println("afterCompletion");Long start = (Long) request.getAttribute("startTime");System.out.println("time interceptor 耗時:"+ (new Date().getTime() - start));System.out.println("ex is "+ex);}}

    2.3、補充部分

    interceptor 其實等價于將 filter? doFilter()?方法中的?chain.doFilter(request, response) 分成兩部分:preHandle() 、?postHandle()? interceptor比?filter?的優勢在于方法上多了另外一個參數,Object handler?該參數是用來處理當前 request?請求的控制器方法的聲明; 意味著,你可以通過該參數獲取當前控制器相關的信息,如控制器名稱、請求的方法名。

    2.4、注意部分

    interceptor 跟 Filter?不一樣,光聲明一個 @Component?是無法達到攔截器起作用,還需要一些額外的配置。 @Configuration public class WebConfig extends WebMvcConfigurerAdapter {@SuppressWarnings("unused")@Autowiredprivate TimeInterceptor timeInterceptor;// 攔截器的一個注冊器 @Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(timeInterceptor);}} 這個配置類需要繼承 WebMvcConfigurerAdapter,并重寫添加攔截器的方法 addInterceptors,將自定義攔截器添加到應用中。 這時候攔截器就生效了。?

    2.5、繼續補充

    攔截器會攔截所有控制器里的方法調用。但是卻有一個缺陷,其無法獲取前端訪問方法的時候所攜帶的參數的。 為什么會這么說? 從Spring MVC 的 DispatcherServlet 的源代碼中可以發現,找到 doDispatch() 方法,也就是請求分發的方法,有一段代碼如下: 如果我們自定的 Interceptor 的 preHandler 方法返回的是 false,分發任務就會截止,不再繼續執行下面的代碼, 而下面的一行代碼正是將前端攜帶的參數進行映射的邏輯,也就是說,preHandler 方法不會接觸到前端攜帶來的參數,也就是說攔截器無法處理參數。 所以這里引進 AOP 進行攔截。

    3、Aspect

    描述AOP常用的一些術語有:通知(Adivce)、連接點(Join point)、切點(Pointcut)、切面(Aspect)、引入(Introduction)、織入(Weaving) 首先明確的核心概念:切面 = 切點 + 通知。

    3.1、通知(Adivce)

    通知分為五種類型: Before(前置通知):在目標方法被調用之前調用通知功能 After(后置通知):在目標方法完成后調用通知,無論方法是否執行成功,不會關心方法的輸出是什么 After-returning(返回通知):在目標方法成功執行之后調用通知 After-throwing(異常通知):在目標方法拋出異常后調用通知 Around(通知環繞):通知包裹了被通知的方法,在被通知的方法調用之前和調用之后執行自定義的行為

    3.2、連接點(Join point)

    連接點是一個應用執行過程中能夠插入一個切面的點。 比如:方法調用、方法執行、字段設置/獲取、異常處理執行、類初始化、甚至是for循環中的某個點。 理論上, 程序執行過程中的任何時點都可以作為作為織入點, 而所有這些執行時點都是Joint point, 但 Spring AOP 目前僅支持方法執行 (method execution)。

    3.3、切點(Pointcut)

    通知(advice)定義了切面何時,那么切點就是定義切面“何處” 描述某一類 Joint points, 比如定義了很多 Joint point, 對于 Spring AOP 來說就是匹配哪些方法的執行。

    3.4、切面(Aspect)

    切面是切點和通知的結合。通知和切點共同定義了關于切面的全部內容 —— 它是什么時候,在何時和何處完成功能。

    3.5、引入(Introduction)

    引用允許我們向現有的類添加新的方法或者屬性

    3.6、織入(Weaving)

    組裝方面來創建一個被通知對象。這可以在編譯時完成(例如使用AspectJ編譯器),也可以在運行時完成。 Spring和其他純Java AOP框架一樣,在運行時完成織入。

    ?


    ?

    來看一下 Aspect 怎么寫: @Aspect @Component public class TimeAspect {@Around("execution(* club.sscai.security.web.controller.UserController.*(..))")public Object handleTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("time aspect is start.");for (Object object : proceedingJoinPoint.getArgs()) {System.out.println(object);}long startTime = System.currentTimeMillis();Object obj = proceedingJoinPoint.proceed();System.out.println("time aspect 耗時:" + (System.currentTimeMillis() - startTime));System.out.println("time aspect finish.");return obj;} } @Around 定義了環繞通知,也就是定義了何時使用切面,表達式"execution(* club.sscai.security.web.controller.UserController.*(..))"定義了再哪里使用。 ProceedingJoinPoint 對象的 proceed() 方法表示執行被攔截的方法,它有一個 Object 類型的返回值,是原有方法的返回值,后期使用的時候往往需要強轉。 對于上面三種攔截方式,他們的執行有一個基本的順序,進入的順序是: Filter-->Interceptor-->Aspect-->Controller-->Aspect-->Interceptor-->Filter(不考慮異常的發生)。 如下所示:

    ?

    博客地址:http://www.cnblogs.com/niceyoo posted @ 2018-12-22 19:02 niceyoo 閱讀(...) 評論(...) 編輯 收藏

    總結

    以上是生活随笔為你收集整理的记录请求的耗时(拦截器、过滤器、aspect)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。