過濾器之雙向過濾? 在WEB應用中無非就是一個request,response.
怎么樣定義過濾器進行雙向攔截呢?即在request過去的時候進行一系列的攔截,在response回來的時候也進行一系列的攔截。
說代碼:
定義兩個的JavaBean :Request,Response
package cn.asto.filter; public class Request { private String requestStr; public String getRequestStr() { return requestStr; } public void setRequestStr(String requestStr) { this.requestStr = requestStr; } }
package cn.asto.filter; public class Resopnse { private String requestStr; public String getRequestStr() { return requestStr; } public void setRequestStr(String requestStr) { this.requestStr = requestStr; } }
定義一個Filter接口:
package cn.asto.filter; public interface Filter { public void doFilter(Request req,Response res); }
實現此接口,寫兩個過濾器,完成對request和response的過濾
HtmlFilter類(對一些標簽過濾):
package cn.asto.filter; public class HtmlFilter implements Filter{ @Override public void doFilter(Request req, Response res) { String newReqStr = req.getRequestStr().replace("<", "[").replace(">", "]")+"request被HTMLFilter處理"; req.setRequestStr(newReqStr); System.out.println(newReqStr); String newResStr = res.getRequestStr().replace("<", "[").replace(">", "]")+"response被HTMLFilter處理"; res.setRequestStr(newResStr);
System.out.println(newResStr); } }
SensitiveFilter(對敏感詞匯的過濾):
package cn.asto.filter; public class SensitiveFilter implements Filter{ @Override public void doFilter(Request req, Response res) { String newReqStr = req.getRequestStr().replace("敏感詞匯", "根據法律,相關內容不能顯示")+"request被SensitiveFitler處理"; req.setRequestStr(newReqStr);
System.out.println(newReqStr);
String newResStr = res.getRequestStr().replace("敏感詞匯", "根據法律,相關內容不能顯示")+"response被SensitiveFitler處理"; res.setRequestStr(newResStr); System.out.println(newResStr); } }
在定義一個Chain來對過濾器進行遍歷:
package cn.asto.filter; import java.util.ArrayList; import java.util.List; public class FilterChain implements Filter{ List<Filter> filters = new ArrayList<Filter>(); public FilterChain addFilter(Filter filter){ filters.add(filter); return this ; } @Override public void doFilter(Request req, Response res) { for(Filter filter:filters){ filter.doFilter(req, res); } } }
寫一個Test類:
package cn.asto.filter; public class Test { public static void main(String args[]){ Request req = new Request(); req.setRequestStr("<script>,hello,敏感詞匯!"); Response res = new Response(); res.setRequestStr("<script>,hello,敏感詞匯!"); FilterChain chain = new FilterChain(); chain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()); chain.doFilter(req, res); } }
輸出結果:
[script],hello,敏感詞匯!request被HTMLFilter處理
[script],hello,敏感詞匯!response被HTMLFilter處理
[script],hello,根據法律,相關內容不能顯示!request被HTMLFilter處理request被SensitiveFitler處理
[script],hello,根據法律,相關內容不能顯示!response被HTMLFilter處理response被SensitiveFitler處理
從結果上分析好像沒什么問題了,request和response分別都經過了HTMLFilter和SensitiveFilter的的過濾。但是你有見過把request過濾到一半,然后開始過濾response的嗎?
只有當且僅當request經過的所有的過濾器,response才能開始工作,而且是倒敘經過過濾器.上個圖:

大概就這么個意思吧。下面的代碼寫起來很簡單,但是設計起來有點精髓了。
我准備把FilterChain作為參數傳遞下去。
修改那么幾個類:
Filter:
package cn.asto.filter; public interface Filter { public void doFilter(Request req,Response res,FilterChain chain); }
HtmlFilter:
package cn.asto.filter; public class HtmlFilter implements Filter{ @Override public void doFilter(Request req, Response res,FilterChain chain) { String newReqStr = req.getRequestStr().replace("<", "[").replace(">", "]")+"request被HTMLFilter處理"; req.setRequestStr(newReqStr); System.out.println(newReqStr); chain.doFilter(req, res,chain); String newResStr = res.getRequestStr().replace("<", "[").replace(">", "]")+"response被HTMLFilter處理"; res.setRequestStr(newResStr); System.out.println(newResStr); } }
SensitiveFilter:
package cn.asto.filter; public class SensitiveFilter implements Filter{ @Override public void doFilter(Request req, Response res,FilterChain chain) { String newReqStr = req.getRequestStr().replace("敏感詞匯", "根據法律,相關內容不能顯示")+"request被SensitiveFitler處理"; req.setRequestStr(newReqStr); System.out.println(newReqStr); chain.doFilter(req, res,chain); String newResStr = res.getRequestStr().replace("敏感詞匯", "根據法律,相關內容不能顯示")+"response被SensitiveFitler處理"; res.setRequestStr(newResStr);
System.out.println(newResStr);
} }
FilterChain:
package cn.asto.filter; import java.util.ArrayList; import java.util.List; public class FilterChain implements Filter{ List<Filter> filters = new ArrayList<Filter>(); public FilterChain addFilter(Filter filter){ filters.add(filter); return this ; } private int index = -1; @Override public void doFilter(Request req, Response res,FilterChain chain) { index++; if(index==filters.size()) return ; filters.get(index).doFilter(req, res, chain); } }
測試一下:
package cn.asto.filter; public class Test { public static void main(String args[]){ Request req = new Request(); req.setRequestStr("<script>,hello,敏感詞匯!"); Response res = new Response(); res.setRequestStr("<script>,hello,敏感詞匯!"); FilterChain chain = new FilterChain(); chain.addFilter(new HtmlFilter()) .addFilter(new SensitiveFilter()); chain.doFilter(req, res,chain); } }
輸出結果:
[script],hello,敏感詞匯!request被HTMLFilter處理
[script],hello,根據法律,相關內容不能顯示!request被HTMLFilter處理request被SensitiveFitler處理
<script>,hello,根據法律,相關內容不能顯示!response被SensitiveFitler處理
[script],hello,根據法律,相關內容不能顯示!response被SensitiveFitler處理response被HTMLFilter處理
嗯 ,真的先把request處理完了之后,再去處理response,且處理順序變成了倒敘了,大家發現了沒有?
不知道大家看懂沒有。我是把這個FilterChain作為參數一直傳遞下去,
1.先調用FilterChain的doFilter,
2.調用HtmlFilter的doFilter(處f理request)
3.回來繼續調用FilterChain的doFilter
4調用SensitiveFilter的doFilter(處理request)
5.先調用FilterChain的doFilter,(index==filters.size()成立,return;)
6.返回到SenvitiveFilter中,往下走,處理response,返回
7.返回到FilterChain中,下面沒有執行語句了,直接返回
8.返回到HtmlFilter中往下走,處理resopnse.返回
9.返回到FilterChain,還是一樣直接返回。
有點繞~,估計第一次看不太懂,建議在eclipse下面debug下 你就明白怎么回事了。
總結一下:
責任鏈模式,實現的關鍵就是把FilterChain作為參數傳遞下去。得到的效果就是先處理完一個對象,緊接着倒敘處理另一個對象。上面的那幅圖就很好的說明了這個問題。
專業術語:責任鏈模式是一種對象的行為模式。在責任鏈模式里,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈。請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求。發出這個請求的客戶端並不知道鏈上的哪一個對象最終處理這個請求,這使得系統可以在不影響客戶端的情況下動態地重新組織和分配責任。
要滿足這個專業術語的話,估計要做一些改動,請求在這個鏈上傳遞,直到鏈上的某一個對象決定處理此請求.
稍微修改一下兩個Filter實現類就可以,給出某種條件下,filter才去處理對象,不然繼續往下走。當filter決定處理此對象后,處理完成后直接return不再往下走即可。
