Servlet中的過濾器Filter是實現了javax.servlet.Filter接口的服務器端程序,主要的用途是設置字符集、控制權限、控制轉向、作一些業務邏輯判斷等。其工做原理是,只要你在web.xml文件配置好要攔截的客戶端請求,它都會幫你攔截到請求,此時你就能夠對請求或響應(Request、Response)統一設置編碼,簡化操做;同時還可進行邏輯判斷,如用戶是否已經登錄、有沒有權限訪問該頁面等等工做。它是隨你的web應用啓動而啓動的,只初始化一次,之後就能夠攔截相關請求,只有當你的web應用中止或從新部署的時候才銷燬。java
Filter能夠認爲是Servlet的一種「增強版」,它主要用於對用戶請求進行預處理,也能夠對HttpServletResponse進行後處理,是個典型的處理鏈。Filter也能夠對用戶請求生成響應,這一點與Servlet相同,但實際上不多會使用Filter向用戶請求生成響應。使用Filter完整的流程是:Filter對用戶請求進行預處理,接着將請求交給Servlet進行處理並生成響應,最後Filter再對服務器響應進行後處理。git
Filter有以下幾個用處。github
Filter有以下幾個種類。web
建立一個Filter只需兩個步驟spring
建立Filter必須實現javax.servlet.Filter接口,在該接口中定義了以下三個方法。apache
攔截器是在面向切面編程中應用的,就是在你的service或者一個方法前調用一個方法,或者在方法後調用一個方法。是基於JAVA的反射機制。攔截器不是在web.xml,好比struts在struts.xml中配置。編程
攔截器,在AOP(Aspect-Oriented Programming)中用於在某個方法或字段被訪問以前,進行攔截,而後在以前或以後加入某些操做。攔截是AOP的一種實現策略。安全
在WebWork的中文文檔的解釋爲—攔截器是動態攔截Action調用的對象。它提供了一種機制使開發者能夠定義在一個Action執行的先後執行的代碼,也能夠在一個Action執行前阻止其執行。同時也提供了一種能夠提取Action中可重用的部分的方式。服務器
攔截器將Action共用的行爲獨立出來,在Action執行先後執行。這也就是咱們所說的AOP,它是分散關注的編程方法,它將通用需求功能從不相關類之中分離出來;同時,可以共享一個行爲,一旦行爲發生變化,沒必要修改不少類,只要修改這個行爲就能夠。
攔截器將不少功能從咱們的Action中獨立出來,大量減小了咱們Action的代碼,獨立出來的行爲就有很好的重用性。
當你提交對Action(默認是.action結尾的url)的請求時,ServletDispatcher會根據你的請求,去調度並執行相應的Action。在Action執行以前,調用被Interceptor截取,Interceptor在Action執行先後執行。
SpringMVC 中的Interceptor 攔截請求是經過HandlerInterceptor 來實現的。在SpringMVC 中定義一個Interceptor 很是簡單,主要有兩種方式,第一種方式是要定義的Interceptor類要實現了Spring 的HandlerInterceptor 接口,或者是這個類繼承實現了HandlerInterceptor 接口的類,好比Spring 已經提供的實現了HandlerInterceptor 接口的抽象類HandlerInterceptorAdapter ;第二種方式是實現Spring的WebRequestInterceptor接口,或者是繼承實現了WebRequestInterceptor的類。
(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顧名思義,該方法將在請求處理以前進行調用。SpringMVC 中的Interceptor 是鏈式的調用的,在一個應用中或者說是在一個請求中能夠同時存在多個Interceptor 。每一個Interceptor 的調用會依據它的聲明順序依次執行,並且最早執行的都是Interceptor 中的preHandle 方法,因此能夠在這個方法中進行一些前置初始化操做或者是對當前請求的一個預處理,也能夠在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布爾值Boolean類型的,當它返回爲false 時,表示請求結束,後續的Interceptor 和Controller 都不會再執行;當返回值爲true 時就會繼續調用下一個Interceptor 的preHandle 方法,若是已是最後一個Interceptor 的時候就會是調用當前請求的Controller 方法。
(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解釋咱們知道這個方法包括後面要說到的afterCompletion 方法都只能是在當前所屬的Interceptor 的preHandle 方法的返回值爲true 時才能被調用。postHandle 方法,顧名思義就是在當前請求進行處理以後,也就是Controller 方法調用以後執行,可是它會在DispatcherServlet 進行視圖返回渲染以前被調用,因此咱們能夠在這個方法中對Controller 處理以後的ModelAndView 對象進行操做。postHandle 方法被調用的方向跟preHandle 是相反的,也就是說先聲明的Interceptor 的postHandle 方法反而會後執行,這和Struts2 裏面的Interceptor 的執行過程有點類型。Struts2 裏面的Interceptor 的執行過程也是鏈式的,只是在Struts2 裏面須要手動調用ActionInvocation 的invoke 方法來觸發對下一個Interceptor 或者是Action 的調用,而後每個Interceptor 中在invoke 方法調用以前的內容都是按照聲明順序執行的,而invoke 方法以後的內容就是反向的。
(3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,該方法也是須要當前對應的Interceptor 的preHandle 方法的返回值爲true 時纔會執行。顧名思義,該方法將在整個請求結束以後,也就是在DispatcherServlet 渲染了對應的視圖以後執行。這個方法的主要做用是用於進行資源清理工做的。
Spring的Interceptor(攔截器)與Servlet的Filter有類似之處,好比兩者都是AOP編程思想的體現,都能實現權限檢查、日誌記錄等。不一樣的是:
過濾前-攔截前-Action處理-攔截後-過濾後
interceptor 的執行順序大體爲:
Spring 中主要經過 HandlerInterceptor 接口來實現請求的攔截,實現 HandlerInterceptor 接口須要實現下面三個方法:
統計請求耗時
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class ExecuteTimeInterceptor extends HandlerInterceptorAdapter{ private static final Logger logger = Logger.getLogger(ExecuteTimeInterceptor.class); //before the actual handler will be executed public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { long startTime = System.currentTimeMillis(); request.setAttribute("startTime", startTime); return true; } //after the handler is executed public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { long startTime = (Long)request.getAttribute("startTime"); long endTime = System.currentTimeMillis(); long executeTime = endTime - startTime; //modified the exisitng modelAndView modelAndView.addObject("executeTime",executeTime); //log it if(logger.isDebugEnabled()){ logger.debug("[" + handler + "] executeTime : " + executeTime + "ms"); } } }
使用mvc:interceptors標籤來聲明須要加入到SpringMVC攔截器鏈中的攔截器
<mvc:interceptors> <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截全部的請求 --> <bean class="com.company.app.web.interceptor.AllInterceptor"/> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/parent/**"/> <bean class="com.company.authorization.interceptor.SecurityInterceptor" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/parent/**"/> <bean class="com.company.authorization.interceptor.SecuritySystemInterceptor" /> </mvc:interceptor> </mvc:interceptors>
能夠利用mvc:interceptors標籤聲明一系列的攔截器,而後它們就能夠造成一個攔截器鏈,攔截器的執行順序是按聲明的前後順序執行的,先聲明的攔截器中的preHandle方法會先執行,然而它的postHandle方法和afterCompletion方法卻會後執行。
在mvc:interceptors標籤下聲明interceptor主要有兩種方式:
通過上述兩步以後,定義的攔截器就會發生做用對特定的請求進行攔截了。
Servlet 的 Filter 接口須要實現以下方法:
void init(FilterConfig paramFilterConfig)
– 當容器初始化 Filter 時調用,該方法在 Filter 的生命週期只會被調用一次,通常在該方法中初始化一些資源,FilterConfig 是容器提供給 Filter 的初始化參數,在該方法中能夠拋出 ServletException 。init 方法必須執行成功,不然 Filter 可能不起做用,出現如下兩種狀況時,web 容器中 Filter 可能無效: 1)拋出 ServletException 2)超過 web 容器定義的執行時間。doFilter(ServletRequest paramServletRequest, ServletResponse paramServletResponse, FilterChain paramFilterChain)
– Web 容器每一次請求都會調用該方法。該方法將容器的請求和響應做爲參數傳遞進來, FilterChain 用來調用下一個 Filter。void destroy()
– 當容器銷燬 Filter 實例時調用該方法,能夠在方法中銷燬資源,該方法在 Filter 的生命週期只會被調用一次。
Request Filters 能夠:
Response Filters 能夠:
過濾器(Filter):
<filter> <description>字符集過濾器</description> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <description>字符集編碼</description> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
1.過濾器:所謂過濾器顧名思義是用來過濾的,在java web中,你傳入的request,response提早過濾掉一些信息,或者提早設置一些參數,而後再傳入servlet或者struts的action進行業務邏輯,好比過濾掉非法url(不是login.do的地址請求,若是用戶沒有登錄都過濾掉),或者在傳入servlet或者struts的action前統一設置字符集,或者去除掉一些非法字符(聊天室常常用到的,一些罵人的話)。filter 流程是線性的, url傳來以後,檢查以後,可保持原來的流程繼續向下執行,被下一個filter, servlet接收等.
2.java的攔截器 主要是用在插件上,擴展件上好比 hibernate spring struts2等 有點相似面向切片的技術,在用以前先要在配置文件即xml文件裏聲明一段的那個東西。
http://blog.csdn.net/heyeqingquan/article/details/71482169
http://einverne.github.io/post/2017/08/spring-interceptor-vs-filter.html
http://blog.csdn.net/xiaodanjava/article/details/32125687