一文詳解JavaWeb過濾器(Filter)_第1頁
一文詳解JavaWeb過濾器(Filter)_第2頁
一文詳解JavaWeb過濾器(Filter)_第3頁
一文詳解JavaWeb過濾器(Filter)_第4頁
一文詳解JavaWeb過濾器(Filter)_第5頁
已閱讀5頁,還剩17頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第一文詳解JavaWeb過濾器(Filter)目錄基本介紹過濾器(Filter)接口使用過濾器(Filter)創(chuàng)建過濾器(Fliter)使用過濾器(Filter)配置過濾器(Filter)攔截路徑注解方式xml方式過濾器(Filter)生命周期理論說明代碼演示FilterConfig和FilterChain說明FilterConfigFilterConfig實例運用FilterChainFilterChain應用實例多個Filter的執(zhí)行順序執(zhí)行順序驗證Filter應用實例(實現敏感詞匯過濾)總結

基本介紹

過濾器,顧名思義就是對事物進行過濾的,在Web中的過濾器,當然就是對請求進行過濾,我們使用過濾器,就可以對請求進行攔截,然后做相應的處理,實現許多特殊功能。如登錄控制,權限管理,過濾敏感詞匯等.

過濾器原理

當我們使用過濾器時,過濾器會對游覽器的請求進行過濾,過濾器可以動態(tài)的分為3個部分,1.放行之前的代碼,2.放行,3.放行后的代碼,這3個部分分別會發(fā)揮不同作用。

第一部分代碼會對游覽器請求進行第一次過濾,然后繼續(xù)執(zhí)行第二部分代碼就是將游覽器請求放行,如果還有過濾器,那么就繼續(xù)交給下一個過濾器第三部分代碼就是對返回的Web資源再次進行過濾處理

我們使用過濾器,也就是說,不止請求會經過過濾器,我們的響應也會經過過濾器。

過濾器(Filter)接口

我們學習過濾器,肯定就要先看一下官方給我們提供的過濾器接口。下面我們使用Idea來查看Filter。

我們通過官方提供的過濾器可以看出過濾器(Filter)使用起來還是比較簡單的,下面我們就來學習如何使用過濾器(Filter)

使用過濾器(Filter)

我們使用過濾器肯定要導入相應的jar包才行,Filter就在servlet-api.jar中,我們將該jar包放到WEB-INF下的lib目錄下面,然后加入項目。

創(chuàng)建過濾器(Fliter)

我們創(chuàng)建Filter,只需要繼承Filter接口就行。

importjavax.servlet.*;

importjava.io.IOException;

publicclassMyFilterimplementsFilter{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

}

Filter接口有3個方法,但是只有一個方法沒有實現,我們只需要實現這個方法就行。我們可以發(fā)現,我們實現了一個doFilter方法,這個方法就是我們寫過濾代碼的地方,具體邏輯就是和上面介紹的過濾器原理一樣的。

使用過濾器(Filter)

我們先來感受一下如何使用過濾器,細節(jié)我們后面慢慢說明。我們在上面創(chuàng)建的類中寫入以下代碼,并且加一個WebFIlter注解

importjavax.servlet.*;

importjavax.servlet.annotation.WebFilter;

importjava.io.IOException;

@WebFilter("/*")

publicclassMyFilterimplementsFilter{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

System.out.println("對request進行過濾");

//下面這行代碼就是放行

filterChain.doFilter(servletRequest,servletResponse);

System.out.println("對response進行過濾");

}

我簡單介紹下上面的代碼,WebFilter(/*)表示對所有請求進行過濾,而在doFilter中的放行代碼,也就是filterChain.doFilter(servletRequest,servletResponse);這行代碼就是對攔截進行放行,細節(jié)我們后面講,現在先怎么理解就行。

啟動服務器,然后我們在游覽器中輸入http://localhost:8080/filter/abc,注意,filter是我們自己配置的web工程路徑,后面的abc隨便輸入的。我們下面來查看游覽器后控制臺輸出。

游覽器輸出

控制臺輸出

現在,我們就已經可以得出兩個結論了,過濾器并不會管資源是否存在,而只會對配置的攔截路徑進行攔截。攔截不僅會對請求進行攔截,而且還會對相應進行攔截。

配置過濾器(Filter)攔截路徑

配置Filter的攔截路徑有2種方式,一種是注解,一種是xml方式,我們分別進行講解。

注解方式

我們如果使用注解來進行配置,那么我們就需要使用@WebFilter,我們不說廢話,直接看該注解的源碼。

里面的配置項還是有很多的,下面我對常用配置項進行說明:

filterName:該filter的名字initParams:初始化參數displayName:filter顯示名稱servletNames:指定對哪些servlet進行過濾asyncSupported:是否支持異步模式urlPatterns:指定攔截路徑value:指定攔截路徑

注意:urlPatterns和value是一樣的。urlPatterns和value只能配置一個,不能兩個都配置,兩個都配置就會報錯。

對于使用@WebFilter,里面的多個參數用,進行分隔。

說明:如果我們僅僅需要配置一個攔截路徑,那么我們可以直接簡寫@WebLister(攔截路徑),如@WebFilter(/*)就是攔截所有請求。

xml方式

xml方式可以說是和Servlet使用xml配置方式一樣了,這里就不廢話,直接配置一個。

filter

filter-namemyFilter/filter-name

filter-classcom.clucky.filter.MyFilter/filter-class

/filter

filter-mapping

filter-namemyFilter/filter-name

url-pattern/*/url-pattern

/filter-mapping

這個就是xml配置方式,只不過把注解換成了xml標簽來配置,里面屬性都是一樣的,這個和Servlet的配置方式基本一樣,這里就不再贅述了。

過濾器(Filter)生命周期

我們都知道Servlet有一個生命周期,當然Filter也有一個生命周期,下面我們就來探討一下Filter的生命周期。

Filter的生命周期和Servlet也十分相似,如果大家對Servlet的生命周期不怎么熟悉,那么可以看一下這篇文章Servlet生命周期。

我們創(chuàng)建一個類,實現Filter的所有方法。

importjavax.servlet.*;

importjava.io.IOException;

publicclassLifeCycleFilterimplementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

@Override

publicvoiddestroy(){

}

理論說明

Filter有3個階段,分別是初始化,攔截和過濾,銷毀。

初始化階段:當服務器啟動時,我們的服務器(Tomcat)就會讀取配置文件,掃描注解,然后來創(chuàng)建我們的Filter。攔截和過濾階段:只要請求資源的路徑和攔截的路徑相同,那么過濾器就會對請求進行過濾,這個階段在服務器運行過程中會一直循環(huán)。銷毀階段:當服務器(Tomcat)關閉時,服務器創(chuàng)建的Filter也會隨之銷毀。

代碼演示

Filter的三個階段就對應著Filter的3個方法,init方法會在Filter創(chuàng)建時調用,doFilter方法會在請求和攔截匹配時調用,destroy方法會在Filter銷毀時調用。我們來對這些方法進行編寫驗證。

importjavax.servlet.*;

importjavax.servlet.annotation.WebFilter;

importjava.io.IOException;

@WebFilter("/*")

publicclassLifeCycleFilterimplementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

//這個方法就是初始化方法,在Filter創(chuàng)建時調用

System.out.println("調用了init()方法");

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

//這個方法就是過濾和攔截的方法,當請求和攔截匹配時調用

System.out.println("調用了doFilter()方法");

@Override

publicvoiddestroy(){

//這個方法就是銷毀方法,在Filter銷毀前調用

System.out.println("調用了destroy()方法");

}

啟動服務器控制臺輸出

進行攔截時控制臺輸出

關閉服務器控制臺輸出

都和我們預想的一樣,到此,我們就成功驗證了Filter的生命周期。

FilterConfig和FilterChain說明

FilterConfig和FilterConfig這2個對象是由服務器(Tomcat)在創(chuàng)建和調用Filter對象時所傳入的,這2個對象十分有用,FilterConfig對象可以讀取我們配置的初始參數,FilterChain可以實現多個Filter之間的連接。

FilterConfig

老規(guī)矩,我們要學習一個對象,首先查看類圖和源代碼

里面的方法就4個,下面我們分別進行講解

getFilterName():獲取filter的名稱getServletContext():獲取ServletContextgetInitparamter(Stringvar1):獲取配置的初始參數的值getInitParamterNames():獲取配置的所有參數名稱

FilterConfig實例運用

我們在init方法中使用FilterConfig來讀取配置的數據庫的信息,然后輸出。

java代碼

importjavax.servlet.*;

importjava.io.IOException;

importjava.util.Enumeration;

publicclassMyFilterConfigimplementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

System.out.println("獲取全部key:value");

//得到所有配置參數的名字

EnumerationStringnames=filterConfig.getInitParameterNames();

while(names.hasMoreElements()){

//得到每一個名字

Stringname=names.nextElement();

System.out.println(name+"="+filterConfig.getInitParameter(name));

System.out.println("end");

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

@Override

publicvoiddestroy(){

}

xml配置

filter

filter-namemyFilterConfig/filter-name

filter-classcom.clucky.filter.MyFilterConfig/filter-class

init-param

param-namedriver/param-name

param-valuecom.mysql.jdbc.Driver/param-value

/init-param

init-param

param-nameurl/param-name

param-valuejdbc:mysql://localhost:3306/equip_employ_manageserverTimezone=GMT/param-value

/init-param

init-param

param-nameusername/param-name

param-valueroot/param-value

/init-param

init-param

param-namepassword/param-name

param-valueroot/param-value

/init-param

/filter

filter-mapping

filter-namemyFilterConfig/filter-name

url-pattern/*/url-pattern

/filter-mapping

啟動服務器,控制臺輸出

我們使用FilterConfig提供的方法就成功實現了功能,FilterConfig就是用來讀取配置文件的。

FilterChain

一樣,我們還是先來查看源代碼以及類圖

我們查看類圖,可以發(fā)現FilterChain就只有一個方法,其實這個方法就是用來對攔截進行放行的,如果有多個攔截器,那么就會繼續(xù)調用下一個Filter進行攔截。doFilter方法需要傳入個參數,一個是ServletRequest,一個是ServletResponse參數,這個直接傳入進行。

Tomcat在調用過濾器時,默認就會傳入Request和Response,這個參數封裝了請求和響應,我們直接使用就行。ServletResquest和ServletResponse可以直接強轉成HttpServletRequest和HttpServletResponse,然后使用相應的方法。

將ServletRequest轉成HttpServletRequest

FilterChain應用實例

我們前面一直都是一個Filter,現在我們來配置2個Filter,通過FilterChain來進行多個過濾。

第一個Filter

importjavax.servlet.*;

importjavax.servlet.annotation.WebFilter;

importjava.io.IOException;

@WebFilter("/*")

publicclassFilter01implementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

System.out.println("調用過濾器01對請求進行過濾~~~~");

//放行,如果還有過濾器,那么就執(zhí)行下一個過濾器

filterChain.doFilter(servletRequest,servletResponse);

System.out.println("調用過濾器01對響應進行過濾~~~~");

@Override

publicvoiddestroy(){

}

第二個過濾器

importjavax.servlet.*;

importjavax.servlet.annotation.WebFilter;

importjava.io.IOException;

@WebFilter("/*")

publicclassFilter02implementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

System.out.println("調用過濾器02對請求進行過濾~~~~");

//放行,如果還有過濾器,那么就執(zhí)行下一個過濾器

filterChain.doFilter(servletRequest,servletResponse);

System.out.println("調用過濾器02對響應進行過濾~~~~");

@Override

publicvoiddestroy(){

}

啟動服務器,然后我們游覽器輸入http://localhost:8080/filter/abc(filter是我配置的web工程路徑)來進行訪問,查看控制臺輸出。

我們可以看見Filter01先進行過濾,然后交給Filter02,然后訪問資源,然后Filter02對響應進行過濾,然后Filter01對響應進行過濾。圖示如下:

我們先使用Filter01對請求進行過濾,那么很自然的,我們就是使用Filter02先對響應進行過濾。

多個Filter的執(zhí)行順序

上面我們配置了2個過濾器,那么我們怎么知道那個過濾器先執(zhí)行呢?其實大家可以直接使用代碼進行驗證,培養(yǎng)獨立思考的習慣,這里我就直接給出答案了。

如果我們是在web.xml中配置的過濾器,那么過濾器的執(zhí)行順序就是filter-mapping在web配置的順序,配置在上面那么就會先執(zhí)行。如果我們是使用@WebFilter進行配置的,那么執(zhí)行順序就是字符比較順序來執(zhí)行,例如有2個過濾器,一個是AFilter,一個是BFilter,那么AFilter就會先執(zhí)行。如果注解和xml混用,那么在web.xml中配置的會先執(zhí)行。

執(zhí)行順序驗證

我這里就驗證第一條,也就是web.xml中配置的順序和filter-mapping順序一樣,其他大家感興趣自己驗證。

xml配置順序3-1-2

filter

filter-namefilter03/filter-name

filter-classcom.clucky.filter.Filter03/filter-class

/filter

filter-mapping

filter-namefilter03/filter-name

url-pattern/*/url-pattern

/filter-mapping

filter

filter-namefilter01/filter-name

filter-classcom.clucky.filter.Filter01/filter-class

/filter

filter-mapping

filter-namefilter01/filter-name

url-pattern/*/url-pattern

/filter-mapping

filter

filter-namefilter02/filter-name

filter-classcom.clucky.filter.Filter02/filter-class

/filter

filter-mapping

filter-namefilter02/filter-name

url-pattern/*/url-pattern

/filter-mapping

Filter01

importjavax.servlet.*;

importjava.io.IOException;

publicclassFilter01implementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

System.out.println("調用過濾器01對請求進行過濾~~~~");

//放行,如果還有過濾器,那么就執(zhí)行下一個過濾器

filterChain.doFilter(servletRequest,servletResponse);

System.out.println("調用過濾器01對響應進行過濾~~~~");

@Override

publicvoiddestroy(){

}

Filter02

importjavax.servlet.*;

importjava.io.IOException;

publicclassFilter02implementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

System.out.println("調用過濾器02對請求進行過濾~~~~");

//放行,如果還有過濾器,那么就執(zhí)行下一個過濾器

filterChain.doFilter(servletRequest,servletResponse);

System.out.println("調用過濾器02對響應進行過濾~~~~");

@Override

publicvoiddestroy(){

}

Filter03

importjavax.servlet.*;

importjava.io.IOException;

publicclassFilter03implementsFilter{

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

System.out.println("調用過濾器03對請求進行過濾~~~~");

//放行,如果還有過濾器,那么就執(zhí)行下一個過濾器

filterChain.doFilter(servletRequest,servletResponse);

System.out.println("調用過濾器03對響應進行過濾~~~~");

@Override

publicvoiddestroy(){

}

我們啟動服務器,游覽器訪問,然后查看控制臺輸出是不是我們配置的3-1-2的順序

發(fā)現執(zhí)行順序果然是這樣,另外2個的驗證大家感興趣可以自己驗證,我這里就不驗證了,如果嫌麻煩,那么記住就行了。

Filter應用實例(實現敏感詞匯過濾)

我們學了那么多,現在來做一個實例,我們寫一個評論頁面,可以進行評論,如果評論中含有我們定義的敏感詞匯,那么我們就進行過濾,使用**來進行代替。

代碼實現

jsp頁面

%@pagecontentType="text/html;charset=UTF-8"language="java"%

html

head

title評論/title

/head

body

h1輸入評論內容/h1

formaction="${pageContext.request.contextPath}/comment"method="post"

textareaname="message"cols="30"rows="10"/textarea

inputtype="submit"value="提交"

/form

p${requestScope.get("name")}span${requestScope.get("comment")}/span/p

/body

/html

Filter代碼

importjavax.servlet.*;

importjavax.servlet.annotation.WebFilter;

importjavax.servlet.annotation.WebInitParam;

importjava.io.IOException;

importjava.util.ArrayList;

importjava.util.List;

@WebFilter(servletNames={"comment"},initParams={@WebInitParam(name="sensitiveWord",value="zz")})

publicclassCommentFilterimplementsFilter{

privateListStringsensitiveWords=newArrayList();

@Override

publicvoidinit(FilterConfigfilterConfig)throwsServletException{

//得到敏感詞匯

Stringword=filterConfig.getInitParameter("sensitiveWord");

//加入集合

sensitiveWords.add(word);

@Override

publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{

//設置編碼

servletRequest.setCharacterEncoding("utf-8");

servletResponse.setContentType("text/html;charset=utf-8");

//得到評論

Stringmessage=servletRequest.getParameter("message");

for(StringsensitiveWord:sensitiveWords){

//對所有敏感詞匯進行過濾

if(message.contains(sensitiveWord)){

//替換敏感詞匯

message=message.replace(sensitiveWord,"**");

//存入request域

servletRequest.setAttribute("comment",message);

//放行

filterChain.doFilter

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論