責(zé)任鏈模式 責(zé)任鏈模式是一種對象的行為模式,。在責(zé)任鏈模式里,,很多對象由每一個對象對其下家的引用而連接起來形成一條鏈,。請求在這個鏈上傳遞,,直到鏈上的某一個對象決定處理此請求,。發(fā)出這個請求的客戶端并不知道鏈上的哪一個對象最終處理這個請求,,這使得系統(tǒng)可以在不影響客戶端的情況下動態(tài)地重新組織和分配責(zé)任,。Tomcat中的Filter就是使用了責(zé)任鏈模式,,創(chuàng)建一個Filter除了要在web.xml文件中做相應(yīng)配置外,,還需要實現(xiàn)javax.servlet.Filter接口,。 為了方便理解,,責(zé)任鏈模式直接用馬士兵老師中的一個例子來講解,,做下筆記也方便自己以后的復(fù)習(xí)查詢: 我們有一個字符串String msg = ":):,<script>,敏感,被就業(yè),網(wǎng)絡(luò)授課";我們希望應(yīng)用以下三個規(guī)則對字符串進(jìn)行過濾和諧處理: (1)將字符串中出現(xiàn)的"<>"符號替換成"[]" (2)處理字符串中的敏感信息,將被就業(yè)和諧成就業(yè) (3)將字符串中出現(xiàn)的":):"轉(zhuǎn)換成"^V^"; 字符串會依次運用這三條規(guī)則,,對字符串進(jìn)行處理,,每個規(guī)則都有自己需要完成的責(zé)任和任務(wù)。 第一步:定義封裝請求的類Request和封裝處理結(jié)果響應(yīng)的類Response 1 //封裝請求的類Request 2 public class Request { 3 String requestStr; 4 5 public String getRequest() { 6 return requestStr; 7 } 8 9 public void setRequest(String request) { 10 this.requestStr = request; 11 } 12 13 } 1 //封裝響應(yīng)信息的類Response 2 public class Response { 3 String responseStr; 4 5 public String getResponse() { 6 return responseStr; 7 } 8 9 public void setResponse(String response) { 10 this.responseStr = response; 11 } 12 13 } 第二步:定義具有過濾功能的接口Filter,具體的過濾規(guī)則需要實現(xiàn)該接口 1 /* 2 * 定義接口Filter,具體的過濾規(guī)則需要實現(xiàn)這個接口,最后一個參數(shù)添加的意義是我們在Main函數(shù)中: 3 * fc.doFilter(request, response,fc);執(zhí)行這一步的時候可以按照規(guī)則鏈條一次使用三個過濾規(guī)則對字符串進(jìn)行處理 4 * 因為 5 * 6 */ 7 public interface Filter { 8 void doFilter(Request request,Response response,FilterChain chain); 9 } 第三步:定義具體的過濾處理規(guī)則 規(guī)則一 1 package com.bjsxt.dp.filter; 2 3 //處理字符串中的HTML標(biāo)記 4 public class HTMLFilter implements Filter { 5 6 public void doFilter(Request request, Response response,FilterChain chain) { 7 //將字符串中出現(xiàn)的"<>"符號替換成"[]" 8 request.requestStr=request.requestStr 9 .replace('<', '[').replace('>', ']')+ 10 //后面添加的是便于我們觀察代碼執(zhí)行步驟的字符串 11 "----HTMLFilter()"; 12 chain.doFilter(request, response,chain); 13 response.responseStr+="---HTMLFilter()"; 14 } 15 16 } 規(guī)則二 1 package com.bjsxt.dp.filter; 2 3 //定義的過濾敏感字眼的過濾規(guī)則 4 public class SensitiveFilter implements Filter{ 5 6 public void doFilter(Request request, Response response,FilterChain chain) { 7 //處理字符串中的敏感信息,將被就業(yè)和諧成就業(yè) 8 request.requestStr=request.requestStr 9 .replace("被就業(yè)", "就業(yè)").replace("敏感", "")+ 10 //后面添加的是便于我們觀察代碼執(zhí)行步驟的字符串 11 " ---sensitiveFilter()"; 12 chain.doFilter(request, response,chain); 13 response.responseStr+="---sensitiveFilter()"; 14 } 15 16 } 規(guī)則三 1 package com.bjsxt.dp.filter; 2 3 //定義FaceFilter 4 public class FaceFilter implements Filter { 5 6 public void doFilter(Request request, Response response, FilterChain chain) { 7 8 //將字符串中出現(xiàn)的":):"轉(zhuǎn)換成"^V^"; 9 request.requestStr = request.requestStr.replace(":):", "^V^") 10 //后面添加的是便于我們觀察代碼執(zhí)行步驟的字符串 11 + "----FaceFilter()"; 12 chain.doFilter(request, response, chain); 13 response.responseStr += "---FaceFilter()"; 14 } 15 16 } 第四步:定義責(zé)任鏈FilterChain 1 package com.bjsxt.dp.filter; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 //過濾鏈條 7 public class FilterChain implements Filter{ 8 //用List集合來存儲過濾規(guī)則 9 List<Filter> filters = new ArrayList<Filter>(); 10 //用于標(biāo)記規(guī)則的引用順序 11 int index=0; 12 //往規(guī)則鏈條中添加規(guī)則 13 public FilterChain addFilter(Filter f) { 14 filters.add(f); 15 //代碼的設(shè)計技巧:Chain鏈添加過濾規(guī)則結(jié)束后返回添加后的Chain,方便我們下面doFilter函數(shù)的操作 16 return this; 17 } 18 public void doFilter(Request request,Response response,FilterChain chain){ 19 //index初始化為0,filters.size()為3,,不會執(zhí)行return操作 20 if(index==filters.size()){ 21 return; 22 } 23 //每添加一個過濾規(guī)則,,index自增1 24 Filter f=filters.get(index); 25 index++; 26 //根據(jù)索引值獲取對應(yīng)的規(guī)律規(guī)則對字符串進(jìn)行處理 27 f.doFilter(request, response, chain); 28 } 29 } 第五步:測試一下我們的代碼 1 package com.bjsxt.dp.filter; 2 3 /* 4 * 責(zé)任鏈模式: 5 * 數(shù)據(jù)消息在進(jìn)入數(shù)據(jù)庫之前,,要被多種過濾規(guī)則進(jìn)行處理,,多種規(guī)則形成一種鏈,依次處理 6 * 給定的數(shù)據(jù)消息 7 */ 8 public class Main { 9 public static void main(String args[]) { 10 //設(shè)定過濾規(guī)則,,對msg字符串進(jìn)行過濾處理 11 String msg = ":):,<script>,敏感,被就業(yè),網(wǎng)絡(luò)授課"; 12 //過濾請求 13 Request request=new Request(); 14 //set方法,,將待處理字符串傳遞進(jìn)去 15 request.setRequest(msg); 16 //處理過程結(jié)束,給出的響應(yīng) 17 Response response=new Response(); 18 //設(shè)置響應(yīng)信息 19 response.setResponse("response:"); 20 //FilterChain,過濾規(guī)則形成的攔截鏈條 21 FilterChain fc=new FilterChain(); 22 //規(guī)則鏈條添加過濾規(guī)則,,采用的是鏈?zhǔn)秸{(diào)用 23 fc.addFilter(new HTMLFilter()) 24 .addFilter(new SensitiveFilter()) 25 .addFilter(new FaceFilter()); 26 //按照FilterChain的規(guī)則順序,依次應(yīng)用過濾規(guī)則 27 fc.doFilter(request, response,fc); 28 //打印請求信息 29 System.out.println(request.getRequest()); 30 //打印響應(yīng)信息 31 System.out.println(response.getResponse()); 32 /* 33 * 處理器對數(shù)據(jù)進(jìn)行處理 34 * --|----|---數(shù)據(jù)--|-----|--- 35 * 規(guī)則1 規(guī)則2 規(guī)則3 規(guī)則4 36 */ 37 } 38 } 運行結(jié)果: ^V^,[script],,就業(yè),網(wǎng)絡(luò)授課----HTMLFilter() ---sensitiveFilter()----FaceFilter() response:---FaceFilter()---sensitiveFilter()---HTMLFilter() 代碼可以使用Eclipse中設(shè)置斷點,,debug單步調(diào)試去驗證,,我們下面帶著大家一塊執(zhí)行一下上面的代碼。 (2)我們點擊左上角的Step Into(F5)進(jìn)入到doFilter(request,response,fc)中 現(xiàn)在執(zhí)行位置在FilterChain.doFilter,依次執(zhí)行代碼,,因為此時的index還是0,因此不可能執(zhí)行return操作,,跳過if代碼塊,,調(diào)用索引值為0的規(guī)則HTMLFilter,index自增1,,執(zhí)行f.doFilter(request, response, chain);現(xiàn)在進(jìn)入到了HTMLFilter類中的doFilter方法中 依次執(zhí)行代碼,,對字符串請求進(jìn)行處理,,執(zhí)行到chain.doFilter(request, response,chain)這一句,會再次進(jìn)入FilterChain中的doFilter方法內(nèi) 此時的index為1,,仍然跳過if代碼塊執(zhí)行下面的步驟,,和上面一樣,用索引值為1的規(guī)則進(jìn)行處理,,index自增1現(xiàn)在變成2了,。執(zhí)行f.doFilter(request, response, chain);會進(jìn)入到SensitiveFilter中的doFilter方法執(zhí)行 第三個規(guī)則的應(yīng)用和前兩個一致,直接給出執(zhí)行到FaceFilter類中的doFilter方法的結(jié)果截圖
現(xiàn)在執(zhí)行到if判斷,,index的值為3,,滿足判斷條件返回,上圖中最上面的函數(shù)退棧,,回到FaceFilter.doFilter函數(shù)中執(zhí)行response.responseStr += "---FaceFilter()";這就是我們運行結(jié)果中response中的第一部分,。函數(shù)會依次退棧,response不斷添加已經(jīng)做過處理的規(guī)則的信息response.responseStr+="---sensitiveFilter()";response.responseStr+="---HTMLFilter()";最終回到Main.main函中打印reponse信息 運行過程用下圖表示: |
|