Tomcat Filter 自己动手实现
Filter 簡介
Filter也稱之為過濾器,它是Servlet技術(shù)中最實(shí)用的技術(shù),Web開發(fā)人員通過Filter技術(shù),對web服務(wù)器管理的所有web資源:例如Jsp, Servlet, 靜態(tài)圖片文件或靜態(tài) html 文件等進(jìn)行攔截,從而實(shí)現(xiàn)一些特殊的功能。例如實(shí)現(xiàn)URL級(jí)別的權(quán)限訪問控制、過濾敏感詞匯、壓縮響應(yīng)信息等一些高級(jí)功能。
它主要用于對用戶請求進(jìn)行預(yù)處理,也可以對HttpServletResponse進(jìn)行后處理。使用Filter的完整流程:Filter對用戶請求進(jìn)行預(yù)處理,接著將請求交給Servlet進(jìn)行處理并生成響應(yīng),最后Filter再對服務(wù)器響應(yīng)進(jìn)行后處理。
Filter功能
在HttpServletRequest到達(dá) Servlet 之前,攔截客戶的HttpServletRequest 。根據(jù)需要檢查HttpServletRequest,也可以修改HttpServletRequest 頭和數(shù)據(jù)。在HttpServletResponse到達(dá)客戶端之前,攔截HttpServletResponse 。根據(jù)需要檢查HttpServletResponse,也可以修改HttpServletResponse頭和數(shù)據(jù)。
如何借助Filter實(shí)現(xiàn)攔截功能
Filter接口中有一個(gè)doFilter方法,當(dāng)開發(fā)人員編寫好Filter,并配置對哪個(gè)web資源進(jìn)行攔截后,Web服務(wù)器每次在調(diào)用web資源的service方法之前,都會(huì)先調(diào)用一下filter的doFilter方法,因此,在該方法內(nèi)編寫代碼可達(dá)到如下目的:
調(diào)用目標(biāo)資源之前,讓一段代碼執(zhí)行。是否調(diào)用目標(biāo)資源(即是否讓用戶訪問web資源)。web服務(wù)器在調(diào)用doFilter方法時(shí),會(huì)傳遞一個(gè)filterChain對象進(jìn)來,filterChain對象是filter接口中最重要的一個(gè)對象,它也提供了一個(gè)doFilter方法,開發(fā)人員可以根據(jù)需求決定是否調(diào)用此方法,調(diào)用該方法,則web服務(wù)器就會(huì)調(diào)用web資源的service方法,即web資源就會(huì)被訪問,否則web資源不會(huì)被訪問。
**下面根據(jù)tomcat中的 filter 自己實(shí)現(xiàn)一個(gè)Filter
參考:Tomcat Filter 源碼分析
Filter使用設(shè)計(jì)模式中的責(zé)任鏈設(shè)計(jì)模式**
手寫 Filter過濾器 源碼實(shí)現(xiàn)
先看下有哪些類,如下圖:
1. Filter 接口
Filter.java
public interface Filter {public void doFilter(Request req, Response res, FilterChain filterChain); }2. 過濾鏈實(shí)現(xiàn)類
FilterChain.java
這個(gè)類是過濾器鏈的核心類
import java.util.ArrayList; import java.util.List;public class FilterChain{//目標(biāo)servletprivate Servlet servlet;//將要執(zhí)行的過濾器下標(biāo)(過濾器鏈)private int pos = 0;//存儲(chǔ)過濾器的容器(tomcat中使用的是一個(gè)數(shù)組進(jìn)行存儲(chǔ)的)private List<Filter> list = new ArrayList<>();public void doFilter(Request req, Response res) {//判斷是否還有要執(zhí)行的filterif(pos<list.size()){//每次調(diào)用過濾器鏈的doFilter時(shí),都要將pos坐標(biāo)+1//注意pos++的位置,如果調(diào)用完doFilter在pos++ 就出現(xiàn)死循環(huán)了list.get(pos++).doFilter(req, res, this);}else{//如果所有的過濾器都執(zhí)行完成則執(zhí)行servletgetServlet().service(req, res);}}//向過濾器鏈中添加過濾器public void addFilter(Filter filter){list.add(filter);}//設(shè)置servletpublic void setServlet(Servlet servlet) {this.servlet = servlet;}public Servlet getServlet() {return servlet;} }3. 模擬 web 中的 Servlet
Servlet.java
public class Servlet {public void service(Request req, Response res){System.out.println("service ok----------");} }4. 自定義的過濾器
EncodeFilter.java
模擬實(shí)現(xiàn)編碼轉(zhuǎn)換過濾器
public class EncodeFilter implements Filter{@Overridepublic void doFilter(Request req, Response res, FilterChain chain) {//在 servlet 之前執(zhí)行System.out.println("encode start ...");chain.doFilter(req, res);//在 servlet 之后執(zhí)行System.out.println("encode end ...");}}LogFilter.java
模擬實(shí)現(xiàn)日志過濾器
public class LogFilter implements Filter{@Overridepublic void doFilter(Request req, Response res, FilterChain chain) {//在 servlet 之前執(zhí)行System.out.println("log start ...");chain.doFilter(req, res);//在 servlet 之后執(zhí)行System.out.println("log end ...");}}5. 模擬 servlet 中 request 和 response 對象
這里Request類和Response類,沒有實(shí)現(xiàn)任何方法,只是為模擬Servlet中的參數(shù)而創(chuàng)建的類。
Request.java
public class Request {}Response.java
public class Response {}6. 啟動(dòng)方法
Main.java
public class Main {public static void main(String[] args) {FilterChain chain = new FilterChain();//設(shè)置要執(zhí)行的Servletchain.setServlet(new Servlet());//根據(jù)url-pattern的匹配規(guī)則 向 FilterChain中添加過濾器//這些Filterchain.addFilter(new LogFilter());chain.addFilter(new EncodeFilter());//執(zhí)行chain.doFilter(new Request(), new Response());} }本人簡書blog地址:http://www.jianshu.com/u/1f0067e24ff8????
點(diǎn)擊這里快速進(jìn)入簡書
GIT地址:http://git.oschina.net/brucekankan/
點(diǎn)擊這里快速進(jìn)入GIT
總結(jié)
以上是生活随笔為你收集整理的Tomcat Filter 自己动手实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用DelayQueue 和 Futur
- 下一篇: Servlet 是线程安全的吗?