java中的過濾器 Filter應(yīng)用小結(jié)
1.過濾器 Filter
1.1.初識過濾器
1.1.1.過濾器概念
過濾器JavaWeb三大組件之一,它與Servlet很相似!過濾器是用來攔截請求的,而不是處理請求的。
當(dāng)用戶請求某個(gè)Servlet時(shí),會先執(zhí)行部署在這個(gè)請求上的Filter,如果Filter“放行”,那么會繼承執(zhí)行用戶請求的Servlet;如果Filter不“放行”,那么就不會執(zhí)行用戶請求的Servlet。
其實(shí)可以這樣理解,當(dāng)用戶請求某個(gè)Servlet時(shí),Tomcat會去執(zhí)行注冊在這個(gè)請求上的Filter,然后是否“放行”由Filter來決定??梢岳斫鉃椋現(xiàn)ilter來決定是否調(diào)用Servlet!當(dāng)執(zhí)行完成Servlet的代碼后,還會執(zhí)行Filter后面的代碼。
單個(gè)過濾器示意圖:
多個(gè)過濾器示意圖:
1前 2前 2后 1后
1.1.2.過濾器例子
創(chuàng)建一個(gè)類,實(shí)現(xiàn)javax.servlet.Filter接口,并實(shí)現(xiàn)它的三個(gè)方法:
public class MyFilter implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("Hello Filter!!!"); } @Override public void destroy() { } }
在web.xml中進(jìn)行Filter配置:
<filter> <filter-name>firstFilter</filter-name> <filter-class>cn.tx.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>firstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
url-pattern和Servlet的url-pattern的匹配規(guī)則一模一樣
1.完全路徑匹配 以/開頭 例如 /aaa /aaa/bbb
2.目錄匹配 以/開頭 例如 /aaa/* /*
3.擴(kuò)展名匹配 不能以/開頭 例如 *.do *.action …
OK了,現(xiàn)在可以嘗試去訪問index.jsp頁面了,看看是什么效果!
當(dāng)用戶訪問index.jsp頁面時(shí),會執(zhí)行HelloFilter的doFilter()方法!在我們的示例中,index.jsp頁面是不會被執(zhí)行的,如果想執(zhí)行index.jsp頁面,那么我們需要放行!
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter 被執(zhí)行了!"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("filter 執(zhí)行完畢了!"); }
有很多同學(xué)總是錯(cuò)誤的認(rèn)為,一個(gè)請求在給客戶端輸出之后就算是結(jié)束了,這是不對的!其實(shí)很多事情都需要在給客戶端響應(yīng)之后才能完成!
1.2.過濾器詳解
1.2.1.過濾器生命周期
我們已經(jīng)學(xué)習(xí)過Servlet的生命周期,那么Filter的生命周期也就沒有什么難度了!
init(FilterConfig):在服務(wù)器啟動時(shí)會創(chuàng)建Filter實(shí)例,并且每個(gè)類型的Filter只創(chuàng)建一個(gè)實(shí)例,從此不再創(chuàng)建!在創(chuàng)建完Filter實(shí)例后,會馬上調(diào)用init()方法完成初始化工作,這個(gè)方法只會被執(zhí)行一次;
doFilter(ServletRequest req,ServletResponse res,FilterChain chain):這個(gè)方法會在用戶每次訪問“目標(biāo)資源(index.jsp)”時(shí)執(zhí)行,如果需要“放行”,那么需要調(diào)用FilterChain的doFilter(ServletRequest,ServletResponse)方法,如果不調(diào)用FilterChain的doFilter()方法,那么目標(biāo)資源將無法執(zhí)行;
destroy():服務(wù)器會在創(chuàng)建Filter對象之后,把Filter放到緩存中一直使用,通常不會銷毀它。一般會在服務(wù)器關(guān)閉時(shí)銷毀Filter對象,在銷毀Filter對象之前,服務(wù)器會調(diào)用Filter對象的destory()方法。
1.2.2.FilterConfig
你已經(jīng)看到了吧,F(xiàn)ilter接口中的init()方法的參數(shù)類型為FilterConfig類型。它的功能與ServletConfig相似,與web.xml文件中的配置信息對應(yīng)。下面是FilterConfig的功能介紹:
ServletContext getServletContext():獲取ServletContext的方法;
String getFilterName():獲取Filter的配置名稱;與元素對應(yīng);
String getInitParameter(String name):獲取Filter的初始化配置,與元素對應(yīng);
Ø Enumeration getInitParameterNames():獲取所有初始化參數(shù)的名稱。
Web.xml配置:
<filter> <filter-name>firstFilter</filter-name> <filter-class>cn.tx.filter.MyFilter</filter-class> <init-param> <param-name>encode</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>company</param-name> <param-value>txjava</param-value> </init-param> </filter>
Filter讀取:
String filterName = filterConfig.getFilterName(); String company = filterConfig.getInitParameter("company"); Enumeration<String> names = filterConfig.getInitParameterNames(); while (names.hasMoreElements()){ String name = names.nextElement(); String value = filterConfig.getInitParameter(name); }
1.2.3.FilterChain
doFilter()方法的參數(shù)中有一個(gè)類型為FilterChain的參數(shù),它只有一個(gè)方法:doFilter(ServletRequest,ServletResponse)。
前面我們說doFilter()方法的放行,讓請求流訪問目標(biāo)資源!但這么說不嚴(yán)密,其實(shí)調(diào)用該方法的意思是,“我(當(dāng)前Filter)”放行了,但不代表其他人(其他過濾器)也放行。
也就是說,一個(gè)目標(biāo)資源上,可能部署了多個(gè)過濾器,就好比在你去北京的路上有多個(gè)打劫的匪人(過濾器),而其中第一伙匪人放行了,但不代表第二伙匪人也放行了,所以調(diào)用FilterChain類的doFilter()方法表示的是執(zhí)行下一個(gè)過濾器的doFilter()方法,或者是執(zhí)行目標(biāo)資源!
如果當(dāng)前過濾器是最后一個(gè)過濾器,那么調(diào)用chain.doFilter()方法表示執(zhí)行目標(biāo)資源,而不是最后一個(gè)過濾器,那么chain.doFilter()表示執(zhí)行下一個(gè)過濾器的doFilter()方法。
1.2.4.過濾器執(zhí)行順序
一個(gè)目標(biāo)資源可以指定多個(gè)過濾器,過濾器的執(zhí)行順序是在web.xml文件中的部署順序:
<filter> <filter-name>filterA</filter-name> <filter-class>cn.tx.filter.FilterA</filter-class> </filter> <filter-mapping> <filter-name>filterA</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>filterB</filter-name> <filter-class>cn.tx.filter.FilterB</filter-class> </filter> <filter-mapping> <filter-name>filterB</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
FilterA:
public class FilterA implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter A 被執(zhí)行了!"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("filter A 執(zhí)行完畢了!"); } @Override public void destroy() { }
FilterB:
public class FilterB implements Filter{ @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter B 被執(zhí)行了!"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("filter B 執(zhí)行完畢了!"); } @Override public void destroy() { } }
執(zhí)行結(jié)果:
filter A 被執(zhí)行了!
filter B 被執(zhí)行了!
servlet 被執(zhí)行了!!!
filter B 執(zhí)行完畢了!
filter A 執(zhí)行完畢了!
1.2.5.過濾器應(yīng)用場景
執(zhí)行目標(biāo)資源之前做預(yù)處理工作,例如設(shè)置編碼,這種試通常都會放行,只是在目標(biāo)資源執(zhí)行之前做一些準(zhǔn)備工作;
通過條件判斷是否放行,例如校驗(yàn)當(dāng)前用戶是否已經(jīng)登錄,或者用戶IP是否已經(jīng)被禁用;
在目標(biāo)資源執(zhí)行后,做一些后續(xù)的特殊處理工作,例如把目標(biāo)資源輸出的數(shù)據(jù)進(jìn)行處理;
1.2.6.過濾器設(shè)置目標(biāo)資源
在web.xml文件中部署Filter時(shí),可以通過“*”來執(zhí)行目標(biāo)資源:
<filter-mapping> <filter-name>myfilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
這一特性與Servlet完全相同!通過這一特性,我們可以在用戶訪問敏感資源時(shí),執(zhí)行過濾器,例如:/admin/*,可以把所有管理員才能訪問的資源放到/admin路徑下,這時(shí)可以通過過濾器來校驗(yàn)用戶身份。
還可以為指定目標(biāo)資源為某個(gè)Servlet,例如:
<servlet> <servlet-name>myservlet</servlet-name> <servlet-class>cn.tx.servlet.TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>myservlet</servlet-name> <url-pattern>/abc</url-pattern> </servlet-mapping> <filter> <filter-name>myfilter</filter-name> <filter-class>cn.tx.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myfilter</filter-name> <servlet-name>myservlet</servlet-name> </filter-mapping>
當(dāng)用戶訪問http://localhost:8080/filtertest/abc時(shí),會執(zhí)行名字為myservlet的Servlet,這時(shí)會執(zhí)行過濾器。
1.2.7.過濾器總結(jié)
Filter的三個(gè)方法:
void init(FilterConfig):在Tomcat啟動時(shí)被調(diào)用;
void destroy():在Tomcat關(guān)閉時(shí)被調(diào)用;
void doFilter(ServletRequest,ServletResponse,FilterChain):每次有請求時(shí)都調(diào)用該方法;
FilterConfig類:與ServletConfig相似,用來獲取Filter的初始化參數(shù)
ServletContext getServletContext():獲取ServletContext的方法;
String getFilterName():獲取Filter的配置名稱;
String getInitParameter(String name):獲取Filter的初始化配置,與元素對應(yīng);
Enumeration getInitParameterNames():獲取所有初始化參數(shù)的名稱。
FilterChain類:
ü void doFilter(ServletRequest,ServletResponse):放行!表示執(zhí)行下一個(gè)過濾器,或者執(zhí)行目標(biāo)資源??梢栽谡{(diào)用FilterChain的doFilter()方法的前后添加語句,在FilterChain的doFilter()方法之前的語句會在目標(biāo)資源執(zhí)行之前執(zhí)行,在FilterChain的doFilter()方法之后的語句會在目標(biāo)資源執(zhí)行之后執(zhí)行。
1.3.過濾器應(yīng)用
過濾器解決POST中文亂碼
前臺頁面:
<form action="/filter_demo/test/post" method="post"> 姓名:<input type="text" name="name"/><br> <input type="submit" value="提交"> </form>
Web.xml配置
<filter> <filter-name>encodeFilter</filter-name> <filter-class>cn.tx.filter.EncodeFilter</filter-class> <init-param> <param-name>encode</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodeFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Filter代碼:
public class EncodeFilter implements Filter{ private String encode; @Override public void init(FilterConfig filterConfig) throws ServletException { this.encode = filterConfig.getInitParameter("encode"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding(encode); servletResponse.setContentType("text/html;charSet="+this.encode); servletResponse.setCharacterEncoding(this.encode); filterChain.doFilter(servletRequest,servletResponse); } @Override public void destroy() { } }
Servlet代碼:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("name"); System.out.println(name); response.getWriter().write("測試中文亂碼"); }
到此這篇關(guān)于java中的過濾器 Filter應(yīng)用小結(jié)的文章就介紹到這了,更多相關(guān)java 過濾器 Filter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- JAVA三種攔截方式詳解(原生過濾器Filter、springMVC攔截器、aop切面)
- Java過濾器@WebFilter用法詳解
- 詳解Java中布隆過濾器(Bloom Filter)原理及其使用場景
- Java微服務(wù)Filter過濾器集成Sentinel實(shí)現(xiàn)網(wǎng)關(guān)限流過程詳解
- Java過濾器doFilter里chain.doFilter()函數(shù)的理解
- Java過濾器Filter詳解
- Java中使用Filter過濾器的方法
- Java中過濾器 (Filter) 和 攔截器 (Interceptor)的使用
- java過濾器中Filter的ChainFilter過濾鏈
相關(guān)文章
SpringMVC Controller解析ajax參數(shù)過程詳解
這篇文章主要介紹了SpringMVC Controller解析ajax參數(shù)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07攔截Druid數(shù)據(jù)源自動注入帳密解密實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了攔截Druid數(shù)據(jù)源自動注入帳密解密實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11Maven中exec插件執(zhí)行Java程序的實(shí)現(xiàn)
在Maven項(xiàng)目中,可以使用Maven的插件來執(zhí)行Java程序,本文主要介紹了Maven中exec插件執(zhí)行Java程序的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12Java數(shù)據(jù)結(jié)構(gòu)之有向圖設(shè)計(jì)與實(shí)現(xiàn)詳解
有向圖是具有方向性的圖,由一組頂點(diǎn)和一組有方向的邊組成,每條方向的邊都連著一對有序的頂點(diǎn)。本文為大家介紹的是有向圖的設(shè)計(jì)與實(shí)現(xiàn),需要的可以參考一下2022-11-11Java隨機(jī)值設(shè)置(java.util.Random類或Math.random方法)
在編程中有時(shí)我們需要生成一些隨機(jī)的字符串作為授權(quán)碼、驗(yàn)證碼等,以確保數(shù)據(jù)的安全性和唯一性,這篇文章主要給大家介紹了關(guān)于Java隨機(jī)值設(shè)置的相關(guān)資料,主要用的是java.util.Random類或Math.random()方法,需要的朋友可以參考下2024-08-08MyBatis傳入?yún)?shù)為List對象的實(shí)現(xiàn)
這篇文章主要介紹了MyBatis傳入?yún)?shù)為List對象的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03