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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

第五章 处理器拦截器详解——跟着开涛学SpringMVC

發布時間:2025/3/21 javascript 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第五章 处理器拦截器详解——跟着开涛学SpringMVC 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

5.1、處理器攔截器簡介

Spring Web MVC的處理器攔截器(如無特殊說明,下文所說的攔截器即處理器攔截器)類似于Servlet開發中的過濾器Filter,用于對處理器進行預處理和后處理。

?

5.1.1、常見應用場景

1、日志記錄:記錄請求信息的日志,以便進行信息監控、信息統計、計算PV(Page View)等。

2、權限檢查:如登錄檢測,進入處理器檢測檢測是否登錄,如果沒有直接返回到登錄頁面;

3、性能監控:有時候系統在某段時間莫名其妙的慢,可以通過攔截器在進入處理器之前記錄開始時間,在處理完后記錄結束時間,從而得到該請求的處理時間(如果有反向代理,如apache可以自動記錄);

4、通用行為:讀取cookie得到用戶信息并將用戶對象放入請求,從而方便后續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都需要的即可使用攔截器實現。

5、OpenSessionInView:如Hibernate,在進入處理器打開Session,在完成后關閉Session。

…………本質也是AOP(面向切面編程),也就是說符合橫切關注點的所有功能都可以放入攔截器實現。

5.1.2、攔截器接口

?

java代碼: 查看復制到剪貼板打印
  • package?org.springframework.web.servlet;??
  • public?interface?HandlerInterceptor?{??
  • ????boolean?preHandle(??
  • ????????????HttpServletRequest?request,?HttpServletResponse?response,???
  • ????????????Object?handler)???
  • ????????????throws?Exception;??
  • ??
  • ????void?postHandle(??
  • ????????????HttpServletRequest?request,?HttpServletResponse?response,???
  • ????????????Object?handler,?ModelAndView?modelAndView)???
  • ????????????throws?Exception;??
  • ??
  • ????void?afterCompletion(??
  • ????????????HttpServletRequest?request,?HttpServletResponse?response,???
  • ????????????Object?handler,?Exception?ex)??
  • ????????????throws?Exception;??
  • }???
  • 我們可能注意到攔截器一個有3個回調方法,而一般的過濾器Filter才兩個,這是怎么回事呢?馬上分析。

    ?

    preHandle:預處理回調方法,實現處理器的預處理(如登錄檢查),第三個參數為響應的處理器(如我們上一章的Controller實現);

    ?????返回值:true表示繼續流程(如調用下一個攔截器或處理器);

    ?????????? ??false表示流程中斷(如登錄檢查失敗),不會繼續調用其他的攔截器或處理器,此時我們需要通過response來產生響應;

    postHandle:后處理回調方法,實現處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行處理,modelAndView也可能為null。

    afterCompletion:整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中我們可以在此記錄結束時間并輸出消耗時間,還可以進行一些資源清理,類似于try-catch-finally中的finally,但僅調用處理器執行鏈中preHandle返回true的攔截器的afterCompletion

    ?

    5.1.3、攔截器適配器

    有時候我們可能只需要實現三個回調方法中的某一個,如果實現HandlerInterceptor接口的話,三個方法必須實現,不管你需不需要,此時spring提供了一個HandlerInterceptorAdapter適配器(一種適配器設計模式的實現),允許我們只實現需要的回調方法。

    ?

    java代碼: 查看復制到剪貼板打印
  • public?abstract?class?HandlerInterceptorAdapter?implements?HandlerInterceptor?{??
  • ?????//省略代碼?此處所以三個回調方法都是空實現,preHandle返回true。??
  • }??
  • 5.1.4、運行流程圖

    ?

    圖5-1 正常流程

    ?

    ?

    圖5-2 中斷流程

    中斷流程中,比如是HandlerInterceptor2中斷的流程(preHandle返回false),此處僅調用它之前攔截器的preHandle返回true的afterCompletion方法。

    ?

    接下來看一下DispatcherServlet內部到底是如何工作的吧:


    java代碼: 查看復制到剪貼板打印
  • //doDispatch方法??
  • //1、處理器攔截器的預處理(正序執行)??
  • HandlerInterceptor[]?interceptors?=?mappedHandler.getInterceptors();??
  • if?(interceptors?!=?null)?{??
  • ????for?(int?i?=?0;?i?<?interceptors.length;?i++)?{??
  • ????HandlerInterceptor?interceptor?=?interceptors[i];??
  • ????????if?(!interceptor.preHandle(processedRequest,?response,?mappedHandler.getHandler()))?{??
  • ????????????//1.1、失敗時觸發afterCompletion的調用??
  • ????????????triggerAfterCompletion(mappedHandler,?interceptorIndex,?processedRequest,?response,?null);??
  • ????????????return;??
  • ????????}??
  • ????????interceptorIndex?=?i;//1.2、記錄當前預處理成功的索引??
  • }??
  • }??
  • //2、處理器適配器調用我們的處理器??
  • mv?=?ha.handle(processedRequest,?response,?mappedHandler.getHandler());??
  • //當我們返回null或沒有返回邏輯視圖名時的默認視圖名翻譯(詳解4.15.5?RequestToViewNameTranslator)??
  • if?(mv?!=?null?&&?!mv.hasView())?{??
  • ????mv.setViewName(getDefaultViewName(request));??
  • }??
  • //3、處理器攔截器的后處理(逆序)??
  • if?(interceptors?!=?null)?{??
  • for?(int?i?=?interceptors.length?-?1;?i?>=?0;?i--)?{??
  • ??????HandlerInterceptor?interceptor?=?interceptors[i];??
  • ??????interceptor.postHandle(processedRequest,?response,?mappedHandler.getHandler(),?mv);??
  • }??
  • }??
  • //4、視圖的渲染??
  • if?(mv?!=?null?&&?!mv.wasCleared())?{??
  • render(mv,?processedRequest,?response);??
  • ????if?(errorView)?{??
  • ????????WebUtils.clearErrorRequestAttributes(request);??
  • }??
  • //5、觸發整個請求處理完畢回調方法afterCompletion??
  • triggerAfterCompletion(mappedHandler,?interceptorIndex,?processedRequest,?response,?null);??
  • 注:以上是流程的簡化代碼,中間省略了部分代碼,不完整。

    ?

    java代碼: 查看復制到剪貼板打印
  • //?triggerAfterCompletion方法??
  • private?void?triggerAfterCompletion(HandlerExecutionChain?mappedHandler,?int?interceptorIndex,??
  • ????????????HttpServletRequest?request,?HttpServletResponse?response,?Exception?ex)?throws?Exception?{??
  • ????????//?5、觸發整個請求處理完畢回調方法afterCompletion?(逆序從1.2中的預處理成功的索引處的攔截器執行)??
  • ????????if?(mappedHandler?!=?null)?{??
  • ????????????HandlerInterceptor[]?interceptors?=?mappedHandler.getInterceptors();??
  • ????????????if?(interceptors?!=?null)?{??
  • ????????????????for?(int?i?=?interceptorIndex;?i?>=?0;?i--)?{??
  • ????????????????????HandlerInterceptor?interceptor?=?interceptors[i];??
  • ????????????????????try?{??
  • ????????????????????????interceptor.afterCompletion(request,?response,?mappedHandler.getHandler(),?ex);??
  • ????????????????????}??
  • ????????????????????catch?(Throwable?ex2)?{??
  • ????????????????????????logger.error("HandlerInterceptor.afterCompletion?threw?exception",?ex2);??
  • ????????????????????}??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????}??
  • ?

    5.2、入門

    具體內容詳見工程springmvc-chapter5。

    5.2.1、正常流程

    (1、攔截器實現

    ?

    java代碼: 查看復制到剪貼板打印
  • package?cn.javass.chapter5.web.interceptor;??
  • //省略import??
  • public?class?HandlerInterceptor1?extends?HandlerInterceptorAdapter?{//此處一般繼承HandlerInterceptorAdapter適配器即可??
  • ????@Override??
  • ????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{??
  • ????????System.out.println("===========HandlerInterceptor1?preHandle");??
  • ????????return?true;??
  • ????}??
  • ????@Override??
  • ????public?void?postHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?ModelAndView?modelAndView)?throws?Exception?{??
  • ????????System.out.println("===========HandlerInterceptor1?postHandle");??
  • ????}??
  • ????@Override??
  • ????public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler,?Exception?ex)?throws?Exception?{??
  • ????????System.out.println("===========HandlerInterceptor1?afterCompletion");??
  • ????}??
  • }??
  • ?

    以上是HandlerInterceptor1實現,HandlerInterceptor2同理 只是輸出內容為“HandlerInterceptor2”。

    (2、控制器

    ?

    java代碼: 查看復制到剪貼板打印
  • package?cn.javass.chapter5.web.controller;??
  • //省略import??
  • public?class?TestController?implements?Controller?{??
  • ????@Override??
  • ????public?ModelAndView?handleRequest(HttpServletRequest?req,?HttpServletResponse?resp)?throws?Exception?{??
  • ????????System.out.println("===========TestController");??
  • ????????return?new?ModelAndView("test");??
  • ????}??
  • }??
  • ?

    (3、Spring配置文件chapter5-servlet.xml

    ?

    java代碼: 查看復制到剪貼板打印
  • <bean?name="/test"?class="cn.javass.chapter5.web.controller.TestController"/>??
  • <bean?id="handlerInterceptor1"???
  • class="cn.javass.chapter5.web.interceptor.HandlerInterceptor1"/>??
  • <bean?id="handlerInterceptor2"???
  • class="cn.javass.chapter5.web.interceptor.HandlerInterceptor2"/>??
  • ???
  • ?

    java代碼: 查看復制到剪貼板打印
  • <bean?class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">??
  • ????<property?name="interceptors">??
  • ????????<list>??
  • ???????????<ref?bean="handlerInterceptor1"/>??
  • ??????????<ref?bean="handlerInterceptor2"/>??
  • ????????</list>??
  • ????</property>??
  • </bean>??
  • ?

    ?

    interceptors:指定攔截器鏈,攔截器的執行順序就是此處添加攔截器的順序;

    ?

    (4、視圖頁面WEB-INF/jsp/test.jsp

    ?

    java代碼: 查看復制到剪貼板打印
  • <%@?page?language="java"?contentType="text/html;?charset=UTF-8"?pageEncoding="UTF-8"%>??
  • <%System.out.println("==========test.jsp");%>??
  • test?page??
  • ?

    在控制臺輸出 test.jsp

    ?

    (5、啟動服務器測試

    輸入網址:http://localhost:9080/springmvc-chapter5/test

    控制臺輸出:

    ?

    java代碼: 查看復制到剪貼板打印
  • ===========HandlerInterceptor1?preHandle??
  • ===========HandlerInterceptor2?preHandle??
  • ===========TestController??
  • ===========HandlerInterceptor2?postHandle??
  • ===========HandlerInterceptor1?postHandle??
  • ==========test.jsp??
  • ===========HandlerInterceptor2?afterCompletion??
  • ===========HandlerInterceptor1?afterCompletion??
  • ?

    到此一個正常流程的演示完畢。和圖5-1一樣,接下來看一下中斷的流程。

    5.2.2、中斷流程

    (1、攔截器

    HandlerInterceptor3和HandlerInterceptor4 與 之前的 HandlerInteceptor1和HandlerInterceptor2一樣,只是在HandlerInterceptor4的preHandle方法返回false:

    ?

    java代碼: 查看復制到剪貼板打印
  • @Override??
  • public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)?throws?Exception?{??
  • ????System.out.println("===========HandlerInterceptor1?preHandle");??
  • onse.getWriter().print("break");//流程中斷的話需要我們進行響應的處理??
  • ????return?false;//返回false表示流程中斷??????
  • ?

    (2、控制器

    流程中斷不會執行到控制器,使用之前的TestController控制器。

    (3、Spring配置文件chapter5-servlet.xml

    ?

    java代碼: 查看復制到剪貼板打印
  • <bean?id="handlerInterceptor3"???
  • class="cn.javass.chapter5.web.interceptor.HandlerInterceptor3"/>??
  • <bean?id="handlerInterceptor4"???
  • class="cn.javass.chapter5.web.interceptor.HandlerInterceptor4"/>??
  • ???
  • ?

    java代碼: 查看復制到剪貼板打印
  • <bean?id="handlerInterceptor3"???
  • class="cn.javass.chapter5.web.interceptor.HandlerInterceptor3"/>??
  • <bean?id="handlerInterceptor4"???
  • class="cn.javass.chapter5.web.interceptor.HandlerInterceptor4"/>??
  • ???
  • ?

    java代碼: 查看復制到剪貼板打印
  • <bean?class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">??
  • ????<property?name="interceptors">??
  • ????????<list>??
  • ???????????<ref?bean="handlerInterceptor3"/>??
  • ??????????<ref?bean="handlerInterceptor4"/>??
  • ????????</list>??
  • ????</property>??
  • </bean>??
  • ?

    interceptors:指定攔截器鏈,攔截器的執行順序就是此處添加攔截器的順序;

    ?

    (4、視圖頁面

    流程中斷,不會執行到視圖渲染。

    (5、啟動服務器測試

    輸入網址:http://localhost:9080/springmvc-chapter5/test

    控制臺輸出:

    ?

    java代碼: 查看復制到剪貼板打印
  • ===========HandlerInterceptor3?preHandle??
  • ===========HandlerInterceptor4?preHandle??
  • ===========HandlerInterceptor3?afterCompletion??
  • ?

    此處我們可以看到只有HandlerInterceptor3的afterCompletion執行,否和圖5-2的中斷流程。

    而且頁面上會顯示我們在HandlerInterceptor4 preHandle 直接寫出的響應“break”。

    ?

    5.3、應用

    5.3.1、性能監控

    如記錄一下請求的處理時間,得到一些慢請求(如處理時間超過500毫秒),從而進行性能改進,一般的反向代理服務器如apache都具有這個功能,但此處我們演示一下使用攔截器怎么實現。

    ?

    實現分析:

    1、在進入處理器之前記錄開始時間,即在攔截器的preHandle記錄開始時間;

    2、在結束請求處理之后記錄結束時間,即在攔截器的afterCompletion記錄結束實現,并用結束時間-開始時間得到這次請求的處理時間。

    ?

    問題:

    我們的攔截器是單例,因此不管用戶請求多少次都只有一個攔截器實現,即線程不安全,那我們應該怎么記錄時間呢?

    解決方案是使用ThreadLocal,它是線程綁定的變量,提供線程局部變量(一個線程一個ThreadLocal,A線程的ThreadLocal只能看到A線程的ThreadLocal,不能看到B線程的ThreadLocal)。

    ?

    代碼實現:

    ?

    java代碼: 查看復制到剪貼板打印
  • package?cn.javass.chapter5.web.interceptor;??
  • public?class?StopWatchHandlerInterceptor?extends?HandlerInterceptorAdapter?{??
  • ????private?NamedThreadLocal<Long>??startTimeThreadLocal?=???
  • new?NamedThreadLocal<Long>("StopWatch-StartTime");??
  • ????@Override??
  • ????public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,???
  • Object?handler)?throws?Exception?{??
  • ????????long?beginTime?=?System.currentTimeMillis();//1、開始時間??
  • ????????startTimeThreadLocal.set(beginTime);//線程綁定變量(該數據只有當前請求的線程可見)??
  • ????????return?true;//繼續流程??
  • ????}??
  • ??????
  • ????@Override??
  • ????public?void?afterCompletion(HttpServletRequest?request,?HttpServletResponse?response,???
  • Object?handler,?Exception?ex)?throws?Exception?{??
  • ????????long?endTime?=?System.currentTimeMillis();//2、結束時間??
  • ????????long?beginTime?=?startTimeThreadLocal.get();//得到線程綁定的局部變量(開始時間)??
  • ????????long?consumeTime?=?endTime?-?beginTime;//3、消耗的時間??
  • ????????if(consumeTime?>?500)?{//此處認為處理時間超過500毫秒的請求為慢請求??
  • ????????????//TODO?記錄到日志文件??
  • ????????????System.out.println(??
  • String.format("%s?consume?%d?millis",?request.getRequestURI(),?consumeTime));??
  • ????????}??????????
  • ????}??
  • }??
  • ?

    NamedThreadLocal:Spring提供的一個命名的ThreadLocal實現。

    ?

    在測試時需要把stopWatchHandlerInterceptor放在攔截器鏈的第一個,這樣得到的時間才是比較準確的。

    ?

    5.3.2、登錄檢測

    在訪問某些資源時(如訂單頁面),需要用戶登錄后才能查看,因此需要進行登錄檢測。

    ?

    流程:

    1、訪問需要登錄的資源時,由攔截器重定向到登錄頁面;

    2、如果訪問的是登錄頁面,攔截器不應該攔截;

    3、用戶登錄成功后,往cookie/session添加登錄成功的標識(如用戶編號);

    4、下次請求時,攔截器通過判斷cookie/session中是否有該標識來決定繼續流程還是到登錄頁面;

    5、在此攔截器還應該允許游客訪問的資源。

    ?

    攔截器代碼如下所示:

    ?

    java代碼: 查看復制到剪貼板打印
  • @Override??
  • public?boolean?preHandle(HttpServletRequest?request,?HttpServletResponse?response,???
  • Object?handler)?throws?Exception?{??
  • ????//1、請求到登錄頁面?放行??
  • ????if(request.getServletPath().startsWith(loginUrl))?{??
  • ????????return?true;??
  • ????}??
  • ??????????
  • ????//2、TODO?比如退出、首頁等頁面無需登錄,即此處要放行?允許游客的請求??
  • ??????????
  • ????//3、如果用戶已經登錄?放行????
  • ????if(request.getSession().getAttribute("username")?!=?null)?{??
  • ????????//更好的實現方式的使用cookie??
  • ????????return?true;??
  • ????}??
  • ??????????
  • ????//4、非法請求?即這些請求需要登錄后才能訪問??
  • ????//重定向到登錄頁面??
  • ????response.sendRedirect(request.getContextPath()?+?loginUrl);??
  • ????return?false;??
  • }??
  • ?

    提示:推薦能使用servlet規范中的過濾器Filter實現的功能就用Filter實現,因為HandlerInteceptor只有在Spring Web MVC環境下才能使用,因此Filter是最通用的、最先應該使用的。如登錄這種攔截器最好使用Filter來實現。

    ?



    私塾在線學習網原創內容(http://sishuok.com)

    原創內容,轉載請注明私塾在線【http://sishuok.com/forum/blogPost/list/5934.html#19650】

    該帖子包含附件,回復帖子后即可下載附件。 相關筆記推薦 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC 第四章 Controller接口控制器詳解(4)——跟著開濤學SpringMVC 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC 第二章 Spring MVC入門 —— 跟開濤學SpringMVC 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
    from:?http://sishuok.com/forum/blogPost/list/5934.html

    總結

    以上是生活随笔為你收集整理的第五章 处理器拦截器详解——跟着开涛学SpringMVC的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 激情视频亚洲 | 国产成人午夜 | 免费看黄色一级视频 | 狠操av | 丝袜脚交免费网站xx | 极品探花在线观看 | www青青草| 38在线视频| 91网站免费在线观看 | 天堂中文在线资 | 亚州中文 | 亚洲乱码国产乱码精品精大量 | 久久av综合网 | 荡女精品导航 | 少妇一区二区三区 | 色婷婷综合在线 | 97影院手机版 | 91视频免费观看 | 欧美裸体xxxx | www.桃色 | 国产午夜伦鲁鲁 | 91成人短视频在线观看 | 久久久久久人妻一区二区三区 | 爱情岛论坛永久入口 | 黄网站免费大全入口 | 天天舔天天干 | 欧美精品久| 国产毛片18| 亚洲一区视频 | 亚洲另类春色 | 美女被娇喘流出白 | 婷婷天堂 | 国产精品99精品无码视亚 | 国产成人视屏 | 日韩欧美激情视频 | 欧美精品久久久久久久 | 大地资源二中文在线影视观看 | 娇妻高潮浓精白浆xxⅹ | 久久在线中文字幕 | 日韩精品极品视频在线观看免费 | 青青草原伊人 | 医生强烈淫药h调教小说视频 | 99成人在线 | 亚洲91色 | 91精品播放 | 日韩男女视频 | 国产亚洲精品久 | 操日韩 | 亚洲精选一区二区三区 | 欧美激情性做爰免费视频 | 欧美在线天堂 | 两性免费视频 | 日本女优在线看 | 免费看国产曰批40分钟 | www.精品在线 | 在线综合网 | 99精品视频网站 | 中文字幕精品一区二区三区精品 | 精品国产一区二区视频 | 国产美女无遮挡永久免费观看 | 妹子干综合网 | 欧美67194 | 福利视频导航网 | 伊人青青久久 | 国产情侣在线视频 | 日韩综合在线观看 | 岛国色图 | 精人妻无码一区二区三区 | 天天久久久 | 欧美黄视频在线观看 | 天天干狠狠 | 国产最爽的乱淫视频国语对白 | 无码人妻一区二区三区av | 亚洲制服丝袜在线播放 | 国产精品短视频 | 亚洲天堂av一区 | 中日韩精品视频在线观看 | 国产乱码精品一区二三赶尸艳谈 | 亚洲电影一区二区 | 日本男人天堂网 | 国产精品天美传媒沈樵 | 午夜免费看片 | 国产精品日日摸天天碰 | 精品国产一区二 | 西西人体44www大胆无码 | 夜色快播 | 亚洲一区视频在线 | 青青草国内自拍 | 亚洲美女av网站 | 在线波多野结衣 | 黄色一大片| 欧美性视频播放 | 久久久久久久久久久国产精品 | 亚洲天堂网在线观看视频 | 欧美国产在线看 | 日韩射吧| 亚洲av成人无码一区二区三区在线观看 | 久操资源网 | 三年电影在线观看 |