1.問題的來源html
項目中使用了Filter,進行白名單的控制,同時使用了Filter進行了跨域請求的控制,使用了Interceptor對用戶請求的攔截,這兩個到底啥區別呢?java
Filter的使用,如下代碼是從網上拷貝過來的,同時在web.xml進行配置:web
public class requestFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) resp; response.setHeader("Access-Control-Allow-Origin", "*"); //解決跨域訪問報錯 response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE"); response.setHeader("Access-Control-Max-Age", "3600"); //設置過時時間 response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, client_id, uuid, Authorization,token"); response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // 支持HTTP 1.1. response.setHeader("Pragma", "no-cache"); // 支持HTTP 1.0. response.setHeader("Expires", "0"); response.setContentType("application/json;charset=UTF-8"); response.setContentType("application/x-www-form-urlencoded;charset=UTF-8"); response.setContentType("text/html;charset=UTF-8"); chain.doFilter(request, response); } @Override public void destroy() { }
注意:response.setHeader("Access-Control-Allow-Origin", "*"); //解決跨域訪問報錯 ;這句話的有問題,若是在生產環境中,什麼地址都是訪問的,因此在生產環境中,咱們通常是不會這樣作的。json
二、什麼是Filter跨域
Servlet做爲Java Web的基礎,它的一個比較核心也被普遍應用的功能就是Filter,又叫攔截器。顧名思義,攔截器就是起到攔截做用的。通常狀況下,用戶從客戶端發出請求到服務器後,整個的流程是:服務器
//HttpRequest --> Filter --> Servlet --> Controller/Action/... --> Filter --> HttpResponse
根據上面的流程能夠看出,Filter的做用就是在用戶請求到達Servlet以前,進行攔截。在攔截到用戶的請求後,咱們能夠實現一些自定義的業務邏輯,例如白名單的設置,跨域的設置。Filter還能夠在服務器響應到達客戶端以前對響應的數據進行修改。app
三、Filter的工做原理框架
Filter跟Servlet同樣都是由服務器負責建立和銷燬的,在web應用程序啓動時,服務器會根據應用程序的web.xml文件中的配置信息調用public void init(FilterConfig filterConfig) throws ServletException方法來初始化Filter,在web應用程序被移除或者是服務器關閉時,會調用public void destroy()來銷燬Filter。在一個應用程序中一個Filter只會被建立和銷燬一次,在進行完初始化以後,Filter中聲明瞭public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException方法,用來實現一些須要在攔截完成以後的業務邏輯。
注意:上面的doFilter()
方法的參數中,有chain
這個參數,它是傳遞過來的攔截鏈對象,裏面包含了用戶定義的一系列的攔截器,這些攔截器根據其在web.xml中定義的順序依次被執行。當用戶的信息驗證經過或者當前攔截器不起做用時,咱們能夠執行chain.doFilter()
方法來跳過當前攔截器來執行攔截器鏈中的下一個攔截器。同時,web.xml中<init-param>標籤被用來配置Filter的初始化時使用的參數,其中<param-name>標籤表示參數的名字,能夠是本身定義的任何名字,<param-value>標籤表示對應的初始化參數的值。上面的初始化參數中,redirectPath定義了當驗證不成功時頁面重定向的的路徑,logonString定義了攔截器攔截的指定URL。<filter-mapping>標籤訂義了攔截器的攔截模式,在<url-pattern>標籤訂義了攔截模式,上面的/*表示攔截全部。它和以前定義的指定攔截的URL標籤結合起來使用。ide
4.Interceptorui
以前提到的Filter是Servlet層面的攔截器,在許多的Java Web框架中,都實現了本身的攔截器Interceptor。例如Struts2中的Interceptor、Spring MVC中的HandlerInterceptor等。相比於Filter,框架中的Interceptor的產生做用的時間和位置不同,下面描述了應用了Spring MVC中的HandlerInterceptor的web請求流程:
HttpRequest ----> DispactherServlet ----> HandlerInterceptor ---->Controller----> HandlerInterceptor ----> HttpResponse
二者的主要區別在於Filter起做用的時機是在請求到達Servlet以前,二HandlerInterceptor其做用的時機是在DispactherServlet接收到用戶請求完成請求到相應的Handler映射以後。雖然都先於在具體的業務邏輯執行,可是仍是存在一些差別。Filter面對的是全部的請求,而HandlerInterceptor是面對具體的Controller。Filter老是先於HandlerInterceptor發揮做用,在Filter中甚至能夠中斷請求,從而使它沒法到達相應的Servlet。並且二者的配置也不同,Filter是在web.xml中進行配置,HandlerInterceptor是在具體的applicationContext.xml中進行配置。DispactherServlet是實現了Servlet接口的。