Java Servlet 过滤器与 springmvc 拦截器的区别?
前言:在工作中,遇到需要記錄日志的情況,不知道該選擇過濾器還是攔截器,故總結了一下。
servlet 過濾器
定義
java過濾器能夠對目標資源的請求和響應進行截取。過濾器的工作方式分為四種
應用場景
可以通過 doFilter 方法的?request、response 提前過濾一些不想要的信息,統一設置一些參數、統一設置字符集、控制權限是否登錄等。
配置
<!-- 定義Filter --><filter><!-- Filter的名字 --><filter-name>loginFilter</filter-name><!-- Filter的實現類 --><filter-class>com.yule.common.filters.LoginFilter</filter-class></filter><!-- 定義Filter攔截的URL地址 --><filter-mapping><!-- Filter的名字 --><filter-name>loginFilter</filter-name><!-- Filter負責攔截的URL 全部以/的請求,如果/*,將會所有的請求--><url-pattern>/*</url-pattern></filter-mapping>過濾器的4種工作方式
<filter-mapping><filter-name>myFilter</filter-name><servlet-name>目標資源</servlet-name><dispatcher>REQUEST</dispatcher> </filter-mapping>四中工作方式通過配置?<dispatcher> 標簽來決定
執行順序
根據 web.xml 的代碼順序來決定過濾器的執行順序。Filter 鏈:?一個Web應用中,可以編寫多個Filter,這些 Filter 組合起來稱之為一個Filter鏈。
當第一個 Filter 的 doFilter 方法被調用時,web 服務器會創建一個代表 Filter 鏈的 FilterChain 對象傳遞給該方法。在 doFilter 方法中,如果調用了 FilterChain 對象的 doFilter 方法,則 web 服務器會檢 FilterChain 對象中是否還有 filter ,如果有,則調用第下一個 filter,如果沒有,則調用目標資源。
init() 方法和?destroy() 方法隨著項目的啟動和關閉才會被調用,且僅一次。
舉個栗子
web.xml 中
<!-- 定義Filter --><filter><!-- Filter的名字 --><filter-name>demoFilter</filter-name><!-- Filter的實現類 --><filter-class>com.yule.common.filters.DemoFilter</filter-class></filter><!-- 定義Filter攔截的URL地址 --><filter-mapping><!-- Filter的名字 --><filter-name>demoFilter</filter-name><!-- Filter負責攔截的URL 全部以/的請求,如果/*,將會所有的請求--><url-pattern>/*</url-pattern></filter-mapping>Java 代碼
package com.yule.common.filters;import javax.servlet.*; import java.io.IOException;/*** 過濾器* @author yule* @date 2018/7/2 21:52*/ public class DemoFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("demo過濾器init。。。");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("demo過濾器doFilter。。。此處省略業務處理邏輯");//通過判斷是否繼續往下走 filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {System.out.println("demo過濾器destroy。。。");} }?
springmvc 攔截器
定義
springMVC 攔截器源碼解析
Spring Web MVC的處理器攔截器。類似于Servlet開發中的過濾器Filter,用于對處理器進行預處理和后處理。攔截器是面向切面編程的,依賴的技術就是Java的動態代理。
應用場景
本質是AOP(面向切面編程),符合 AOP 的所有功能都可以使用攔截器實現。
配置
在 spring-mvc.xml 中
<mvc:interceptors><!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 --><!-- <bean class="com.bybo.aca.web.interceptor.Login"/> --><mvc:interceptor><!--進行攔截的地址--><mvc:mapping path="/**"/><bean class="com.yule.common.interceptors.DemoInterceptor"/></mvc:interceptor></mvc:interceptors>執行順序
根據 xml 中的配置順序來執行。攔截器的執行順序在過濾器之間。
方法說明
- preHandle(HttpServletRequest request, HttpServletResponse response, Object handle)方法,該法在請求處理之前進行調用。SpringMVC 中的 Interceptor 是鏈式調用的,在一個應用中或者說是在一個請求中可以同時存在多個 Interceptor 。每個 Interceptor 的調用會依據它的聲明順序依次執行,而且最先執行的都是 Interceptor 中的 preHandle 方法,所以可以在這個方法中進行一些前置初始化操作或者是對當前請求做一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布爾值 Boolean 類型的,當它返回為 false 時,表示請求結束,后續的 Interceptor 和 Controller 都不會再執行;當返回值為 true 時,就會繼續調用下一個 Interceptor 的 preHandle 方法,如果已經是最后一個 Interceptor 的時候,就會是調用當前請求的 Controller 中的方法。
- postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法,通過 preHandle 方法的解釋咱們知道這個方法包括后面要說到的 afterCompletion 方法都只能在當前所屬的 Interceptor 的 preHandle 方法的返回值為 true 的時候,才能被調用。postHandle 方法在當前請求進行處理之后,也就是在 Controller 中的方法調用之后執行,但是它會在 DispatcherServlet 進行視圖返回渲染之前被調用,所以咱們可以在這個方法中對 Controller 處理之后的 ModelAndView 對象進行操作。postHandle 方法被調用的方向跟 preHandle 是相反的,也就是說,先聲明的 Interceptor 的 postHandle 方法反而會后執行。
- afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法,也是需要當前對應的 Interceptor 的 preHandle 方法的返回值為 true 時才會執行。因此,該方法將在整個請求結束之后,也就是在 DispatcherServlet 渲染了對應的視圖之后執行,這個方法的主要作用是用于進行資源清理的工作。afterCompletion 方法被調用的方向也跟 preHandle 是相反的,也就是說,先聲明的 Interceptor 的 afterCompletion 方法反而會后執行
舉個栗子
spring-mvc 中
<mvc:interceptors><!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 --><!-- <bean class="com.bybo.aca.web.interceptor.Login"/> --><mvc:interceptor><!--進行攔截的地址--><mvc:mapping path="/**"/><bean class="com.yule.common.interceptors.DemoInterceptor"/></mvc:interceptor></mvc:interceptors>Java 代碼
package com.yule.common.interceptors;import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** 自定義攔截器方式一* Created by yule on 2018/7/2 22:37.*/ public class DemoInterceptor implements HandlerInterceptor{@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {//return true 表示繼續下一個攔截器或者 control 層//return false 表示被攔截下來return false;}@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {} } package com.yule.common.interceptors;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** 自定義攔截器方式二* 一般都是通過實現HandlerInterceptor接口或者繼承HandlerInterceptorAdapter抽象類,復寫preHandle()、postHandle()和afterCompletion()這 3 個方法來對用戶的請求進行攔截處理* Created by yule on 2018/7/2 22:43.*/ public class Demo2Interceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;} }?區別
其實兩者還是有相似之處,就是都可以用作權限檢查、日志記錄等情況,但是在這些情況下如何選擇就要知道不同之處。
不同之處
使用范圍不同:Filter 只能用于 Web 程序中。而攔截器可以用于 Web 程序,Application、Swing 程序中。
規范不同:Filter 是 servlet 規范規定的,是 servlet 支持的。而攔截器是在 spring 容器內,是 spring 框架支持的。
使用資源不同:Filter 不能直接使用 spring 的資源、對象等。而攔截器是一個 spring 組件,歸 spring 管理,配置在 spring 文件中,因此能使用 spring 的任何資源、對象,例如 Service 對象、數據源、事務管理等,通過 IoC 注入到攔截器即可。也就是說在攔截器中可以注入一個 service ,用于業務邏輯或者訪問數據庫。
深度不同:Filter 只在 Servlet 前后起作用。而攔截器能夠深入到方法前后、異常拋出前后等,因此攔截器的使用具有更大的彈性。
作用范圍不同:攔截器只能對 Controller 層請求起作用,而過濾器則可以對幾乎所有的請求起作用(如 .js、.css等)。
所以,在 Spring 構架的程序中,要優先使用攔截器。
注意
攔截器是在過濾器之間運行的。
執行順序舉例
攔截器,spring-mvc.xml 中:
<mvc:interceptors><!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 --><!-- <bean class="com.bybo.aca.web.interceptor.Login"/> --><mvc:interceptor><!--進行攔截的地址--><mvc:mapping path="/**"/><bean class="com.yule.common.interceptors.DemoInterceptor"/></mvc:interceptor><mvc:interceptor><!--進行攔截的地址--><mvc:mapping path="/**"/><bean class="com.yule.common.interceptors.Demo2Interceptor"/></mvc:interceptor></mvc:interceptors>java 代碼:
package com.yule.common.interceptors;import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** 自定義攔截器方式一* Created by yule on 2018/7/2 22:37.*/ public class DemoInterceptor implements HandlerInterceptor{@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {//return true 表示繼續下一個攔截器或者 control 層//return false 表示被攔截下來System.out.println("preHandle");return true;}@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {System.out.println("postHandle");}@Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {System.out.println("afterCompletion");} } View Code package com.yule.common.interceptors;import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;/*** 自定義攔截器方式二* 一般都是通過實現HandlerInterceptor接口或者繼承HandlerInterceptorAdapter抽象類,復寫preHandle()、postHandle()和afterCompletion()這 3 個方法來對用戶的請求進行攔截處理* Created by yule on 2018/7/2 22:43.*/ public class Demo2Interceptor extends HandlerInterceptorAdapter {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle 2222222...");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle 22222222");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion 2222222");} } View Code過濾器, web.xml 中:
<!-- 定義Filter --><filter><!-- Filter的名字 --><filter-name>demoFilter</filter-name><!-- Filter的實現類 --><filter-class>com.yule.common.filters.DemoFilter</filter-class></filter><!-- 定義Filter攔截的URL地址 --><filter-mapping><!-- Filter的名字 --><filter-name>demoFilter</filter-name><!-- Filter負責攔截的URL 全部以/的請求,如果/*,將會所有的請求--><url-pattern>/*</url-pattern></filter-mapping><filter><filter-name>demo2Filter</filter-name><filter-class>com.yule.common.filters.Demo2Filter</filter-class></filter><filter-mapping><filter-name>demo2Filter</filter-name><url-pattern>/*</url-pattern></filter-mapping>java 代碼:
package com.yule.common.filters;import javax.servlet.*; import java.io.IOException;/*** 過濾器* @author yule* @date 2018/7/2 21:52*/ public class DemoFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("demo過濾器init。。。");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("demo過濾器doFilter。。。此處省略業務處理邏輯");//通過判斷是否繼續往下走 filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {System.out.println("demo過濾器destroy。。。");} } View Code package com.yule.common.filters;import javax.servlet.*; import java.io.IOException;/*** Created by yule on 2018/7/2 22:18.*/ public class Demo2Filter implements Filter{@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("demo2過濾器init 2222222");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("demo過濾器doFilter 222222");//通過判斷是否繼續往下走 filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {System.out.println("demo2過濾器destroy 22222 ");} } View Code調用 controller 打印結果:
?
轉載于:https://www.cnblogs.com/yuxiaole/p/9230742.html
總結
以上是生活随笔為你收集整理的Java Servlet 过滤器与 springmvc 拦截器的区别?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CCD和CMOS摄像头成像原理以及其他区
- 下一篇: 七大因素阻碍非标自动化行业发展,那么应对