云笔记项目-过滤器与拦截器学习
在做云筆記項目的過程中,沒有登錄的情況下,也可以直接訪問edit.html頁面。這個跟以前自己用Servlet做過的PadAndFilterManagement情況類似,當時在沒有登錄的情況下可以訪問任何的action,后面加了過濾器才解決。只是在云筆記項目中,其使用的Spring MVC框架,即也可以使用Spring容器下的攔截器Interceptor進行攔截。但是過濾器和攔截器到底有什么區別,博客中有很多大牛分享了經驗,這里直接貼過來,作為今后自己的查看的參考。
過濾器Filter和攔截器Interceptor的主要區別
(1)使用范圍:Filter是Servlet規范的,只能用于Web程序中,而攔截器既可以用于Web程序,也可以用于Application、Swing程序中。
(2)規范不同:Filter是在Servlet規范中定義的,由Servlet容器支持。攔截器Interceptor是在Spring容器中的,由Spring框架支持。
(3)可以調用的資源不同:攔截器Interceptor是Spring的一個組件,由Spring管理,配置在Spring文件中,因此可以使用Spring里的任何資源、對象。比如Service,對象,數據源,事務管理等,通過注入到攔截器就可以進行深層次訪問。Filter不具備此功能。
(4)Filter只在Servlet前后起作用,Interceptor能夠深入到方法前后,異常拋出前后等,因此攔截器的使用具有更大的彈性,如果只攔截action請求,在Spring框架程序中,優先使用攔截器。
過濾器Filter和攔截器Interceptor的執行順序
項目中使用了過濾器進行特定網頁的過濾,如不過濾log_in.html,讓用戶首先能看到登錄頁面。并且使用了攔截器進行action的攔截,如果是登錄注冊的請求就不進行了攔截。其實項目使用過濾器也可以實現需求,但是同時使用了兩種的話,就有必要大致了解瀏覽器訪問服務端后,過濾器和攔截器的執行順序。參考了大牛的博文,進行如下測試:
(1)過濾器
1 package Filter; 2 3 import java.io.IOException; 4 5 import javax.servlet.Filter; 6 import javax.servlet.FilterChain; 7 import javax.servlet.FilterConfig; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest; 10 import javax.servlet.ServletResponse; 11 12 /** 13 * 測試過濾器 14 * @author yangchaolin 15 * 16 */ 17 public class SomeFilter implements Filter{ 18 19 public void destroy() { 20 System.out.println("過濾器的destroy方法執行了"); 21 } 22 23 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 24 throws IOException, ServletException { 25 System.out.println("過濾器的doFilter...before執行了"); 26 chain.doFilter(req, res); 27 System.out.println("過濾器的doFilter...after執行了"); 28 } 29 30 public void init(FilterConfig config) throws ServletException { 31 System.out.println("過濾器的init方法執行了"); 32 } 33 34 }(2)攔截器
1 package Interceptors; 2 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletResponse; 5 6 import org.springframework.web.servlet.HandlerInterceptor; 7 import org.springframework.web.servlet.ModelAndView; 8 /** 9 * 攔截器類需要實現HandlerInterceptor接口 10 * @author yangchaolin 11 * 12 */ 13 public class SomeInterceptor implements HandlerInterceptor{ 14 /** 15 * DispatcherServlet在收到請求后,會先調用preHandler方法,如果該方法的返回值為true,則繼續向后調用Controller的方法 16 * 如果返回值是false,則中斷請求 17 * 18 * DispatcherServlet,攔截器以及Controller會共享同一個request,response 19 * handler:Controller的方法對象,利用了java反射機制,后面了解學習 20 */ 21 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 22 throws Exception { 23 System.out.println("攔截器的preHandler方法執行了"); 24 return true; 25 } 26 /** 27 * 是Controller處理完后,在將ModelAndView返回給前端控制器DispatcherServlet之前,執行的方法 28 * 可以在該方法里,修改ModelAndView的處理結果 29 */ 30 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 31 ModelAndView modelAndView) throws Exception { 32 System.out.println("攔截器的postHandler方法執行了"); 33 34 } 35 /** 36 * 最后執行 37 * ex:是處理器Controller所拋出的異常 38 * 可以寫一個攔截器專門處理處理器Controller拋出的異常 39 */ 40 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) 41 throws Exception { 42 System.out.println("攔截器的afterCompletion方法執行了"); 43 44 } 45 46 }(3)web.xml中配置過濾器
1 <!-- 測試攔截器配置 --> 2 <filter> 3 <filter-name>someFilter</filter-name> 4 <filter-class>Filter.SomeFilter</filter-class> 5 </filter> 6 <filter-mapping> 7 <filter-name>someFilter</filter-name> 8 <url-pattern>/*</url-pattern> 9 </filter-mapping>(4)spring-mvc.xml中配置攔截器
1 <!-- 設置攔截器Interceptor --> 2 <!-- 如果想要攔截所有的請求,path應該寫成/** --> 3 <mvc:interceptors> 4 <mvc:interceptor> 5 <mvc:mapping path="/**"/> 6 <bean class="Interceptors.SomeInterceptor"></bean> 7 </mvc:interceptor> 8 </mvc:interceptors>(5)控制器中方法
1 package Controller; 2 3 import org.springframework.stereotype.Controller; 4 import org.springframework.web.bind.annotation.RequestMapping; 5 6 @Controller 7 public class HelloController { 8 @RequestMapping("/hello.do") 9 public String hello() { 10 System.out.println("控制器的hello()方法執行了"); 11 return "hello"; 13 } 14 /** 15 * 如果路徑加一個demo,然而攔截器mapping還是/*的話,將不會攔截 16 * 如果想實現各種路徑的攔截,不論幾層都能實現攔截效果的話,需要將mapping修改為/** 17 * @return 18 */ 19 @RequestMapping("/demo/hello.do") 20 public String hello1() { 21 System.out.println("控制器的hello1()方法執行了"); 22 return "hello"; 24 } 25 }?測試部分:
(1)啟動測試項目,地址1為:http://localhost:8088/SpringMVC03/hello.do,控制臺輸出結果為:
?(2)啟動測試項目,地址2為:http://localhost:8088/SpringMVC03/demo/hello.do,控制臺輸出結果為:
在兩次請求服務端后,控制臺只輸出了一次"過濾器的init方法執行了"。說明過濾器初始化過程在servlet容器中只執行了一次。
(3)啟動測試項目,地址3為:http://localhost:8088/SpringMVC03/demo.do,控制器輸出結果為:
從測試的結果來看,發現在瀏覽器發送請求給服務端的時候,過濾器Filter更早于攔截器Interceptor執行,而在瀏覽器接收服務端返回的信息時,過濾器Filter在攔截器Interceptor執行完后才執行結束,所以過濾器的方法更加靠近瀏覽器端。
?總結圖示:
① 發送action請求后,Filter的doFilter方法開始執行(此時還未執行完)。
② DispatcherServlet會得到web的請求,調用HandlerMapping進行控制器匹配,如果控制器沒有對應的action地址,將不會執行Interceptor的方法(如發送demo.do請求時沒執行攔截器的方法)。當控制器有對應的請求時會開始執行攔截器的方法。
③ Interceptor的preHandler方法執行。
④ 控制器的方法執行。
⑤ 控制器執行后,將結果(本例中為一個“hello”字符串)發給ModelAndView。
⑥?ModelAndView將結果再發送給DispatcherServlet之前,會執行Interceptor的postHandler方法。
⑦?DispatcherServlet將ModelAndView返回的結果發送給視圖解析器解析,如本例解析得到/WEB-INF/hello.jsp。
⑧ 視圖解析器將渲染頁面準備發送給瀏覽器前,將執行afterCompletion方法。
⑨ 最后,將執行完Filter的doFilter方法。
參考博客:https://blog.csdn.net/chenleixing/article/details/44573495
參考博客:https://blog.csdn.net/zxd1435513775/article/details/80556034
轉載于:https://www.cnblogs.com/youngchaolin/p/10549020.html
總結
以上是生活随笔為你收集整理的云笔记项目-过滤器与拦截器学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学生信息链表,建立,插入,删除,遍历,查
- 下一篇: django中实现websocket