1. 程式人生 > >設計模式(24)-----責任鏈模式-----攔截器設計模式

設計模式(24)-----責任鏈模式-----攔截器設計模式

谷歌

 一,一個初步的責任鏈模式的攔截器

攔截器介面

package com.DesignPatterns.an.Responsibility1;

public interface Filter {
    String doFilter(String str);
}

 

攔截器實現

package com.DesignPatterns.an.Responsibility1;

public class HTMLFilter implements Filter {

    @Override
    public String doFilter(String str) {
        
//process the html tag <> String r = str.replace('<', '[') .replace('>', ']'); return r; } }

 

 

package com.DesignPatterns.an.Responsibility1;

public class SesitiveFilter implements Filter {

    @Override
    public String doFilter(String str) {
        String r 
= str.replace("被就業", "就業") .replace("敏感", ""); return r; } }

 

 

package com.DesignPatterns.an.Responsibility1;

public class FaceFilter implements Filter {

    @Override
    public String doFilter(String str) {
        return str.replace(":)", "
^V^"); } }

 

攔截器程式碼

 

package com.DesignPatterns.an.Responsibility1;

public class MsgProcessor {
    private String msg;
    
    Filter[] filters = {new HTMLFilter(), new SesitiveFilter(), new FaceFilter()};

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String process() {
        String r=msg;
        for(Filter f:filters) {
            f.doFilter(r);
        }
        return r;
        
        
    }
}
package com.DesignPatterns.an.Responsibility1;
/**
 * 這個是責任鏈設計模式(攔截器設計模式)的入門
 * @author qingruihappy
 * @data   2018年11月5日 下午11:48:05
 * @說明:主要設計思路就是讓所有的攔截器都實現同樣的介面,讓後把所有的攔截器都放在一個list集合中來。
 * 假如在加一個攔截器的話就會攔截器的process方法是不用變的,只需要在Filter[] filters的陣列中把已經實現了
 * Filter介面的實現類加進來就行了。
 * 
 * 但是現在假如我們在攔截器的中間在加一組攔截器怎麼辦呢?
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String msg = "大家好:),<script>,敏感,被就業,網路授課沒感覺,因為看不見大家夥兒";
        MsgProcessor mp = new MsgProcessor();
        mp.setMsg(msg);
        
        String result = mp.process();
        System.out.println(result);
    }

}

 

大家好^V^,[script],,就業,網路授課沒感覺,因為看不見大家夥兒

 

二,平常我們看到的責任鏈的開發 

package com.DesignPatterns.an.Responsibility2;

public interface Filter {
    String doFilter(String str);
}

 

 

package com.DesignPatterns.an.Responsibility2;

public class HTMLFilter implements Filter {

    @Override
    public String doFilter(String str) {
        //process the html tag <>
        String r = str.replace('<', '[')
                   .replace('>', ']');
        return r;
    }

}
package com.DesignPatterns.an.Responsibility2;

public class SesitiveFilter implements Filter {

    @Override
    public String doFilter(String str) {
        //process the sensitive words
        String r = str.replace("被就業", "就業")
             .replace("敏感", "");
        
        return r;
    }

}
package com.DesignPatterns.an.Responsibility2;

public class FaceFilter implements Filter {

    @Override
    public String doFilter(String str) {
        return str.replace(":)", "^V^");
    }

}

 

責任鏈模式的工具類

package com.DesignPatterns.an.Responsibility2;

import java.util.ArrayList;
import java.util.List;
/**
 * 
 * @author qingruihappy
 * @data   2018年11月6日 上午12:10:42
 * @說明:這個類主要是用來新增過濾器及其便利過濾器的
 */
public class FilterChain {
    List<Filter> filters = new ArrayList<Filter>();
    /*注意這裡的用法,我們返回的是類本身,這樣我們就可以用fc.addFilter(new HTMLFilter())
      .addFilter(new SesitiveFilter())這種責任鏈的編碼方式了。
      ;*/
    public FilterChain addFilter(Filter f) {
        this.filters.add(f);
        return this;
    }
    
    public String doFilter(String str) {
        String r = str;
        for(Filter f: filters) {
            r = f.doFilter(r);
        }
        return r;
    }
}
package com.DesignPatterns.an.Responsibility2;
/**
 * 這個類主要是用來呼叫FilterChain的
 * @author qingruihappy
 * @data   2018年11月6日 上午12:11:34
 * @說明:
 */
public class MsgProcessor {
    private String msg;
    
    FilterChain fc;
    
    public FilterChain getFc() {
        return fc;
    }

    public void setFc(FilterChain fc) {
        this.fc = fc;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String process() {
        
        
        return fc.doFilter(msg);
        
        
    }
}
package com.DesignPatterns.an.Responsibility2;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String msg = "大家好:),<script>,敏感,被就業,網路授課沒感覺,因為看不見大家夥兒";
        MsgProcessor mp = new MsgProcessor();
        mp.setMsg(msg);
        FilterChain fc = new FilterChain();
        fc.addFilter(new HTMLFilter())
          .addFilter(new SesitiveFilter())
          .addFilter(new FaceFilter());
        mp.setFc(fc);
        String result = mp.process();
        System.out.println(result);
    }

}
大家好^V^,[script],,就業,網路授課沒感覺,因為看不見大家夥兒

 

 

 三,在一組責任鏈中加入另一組責任鏈

package com.DesignPatterns.an.Responsibility3;

public interface Filter {
    String doFilter(String str);
}
package com.DesignPatterns.an.Responsibility3;

public class HTMLFilter implements Filter {

    @Override
    public String doFilter(String str) {
        //process the html tag <>
        String r = str.replace('<', '[')
                   .replace('>', ']');
        return r;
    }

}
package com.DesignPatterns.an.Responsibility3;

public class SesitiveFilter implements Filter {

    @Override
    public String doFilter(String str) {
        //process the sensitive words
        String r = str.replace("被就業", "就業")
             .replace("敏感", "");
        
        return r;
    }

}
package com.DesignPatterns.an.Responsibility3;

public class FaceFilter implements Filter {

    @Override
    public String doFilter(String str) {
        return str.replace(":)", "^V^");
    }

}

 

 

package com.DesignPatterns.an.Responsibility3;

import java.util.ArrayList;
import java.util.List;

public class FilterChain implements Filter {
    List<Filter> filters = new ArrayList<Filter>();
    /*注意這裡的用法,我們返回的是類本身,這樣我們就可以用fc.addFilter(new HTMLFilter())
      .addFilter(new SesitiveFilter())這種責任鏈的編碼方式了。
      ;*/
    public FilterChain addFilter(Filter f) {
        this.filters.add(f);
        return this;
    }
    
    public String doFilter(String str) {
        String r = str;
        for(Filter f: filters) {
            r = f.doFilter(r);
        }
        return r;
    }
}
package com.DesignPatterns.an.Responsibility3;

public class MsgProcessor {
    private String msg;
    
    FilterChain fc;
    
    public FilterChain getFc() {
        return fc;
    }

    public void setFc(FilterChain fc) {
        this.fc = fc;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String process() {
        
        
        return fc.doFilter(msg);
        
        
    }
}
package com.DesignPatterns.an.Responsibility3;
/**
 * 這裡主要注意的是在一組攔截器中加入另一組攔截器的
 * @author qingruihappy
 * @data   2018年11月6日 上午12:15:36
 * @說明:
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String msg = "大家好:),<script>,敏感,被就業,網路授課沒感覺,因為看不見大家夥兒";
        MsgProcessor mp = new MsgProcessor();
        mp.setMsg(msg);
        FilterChain fc = new FilterChain();
        fc.addFilter(new HTMLFilter())
          .addFilter(new SesitiveFilter())
          ;
        //注意在這裡讓FilterChain也去實現Filter介面,它按照黑盒的思路來看的話其實就是
        //另一個數組,直接在原來的陣列中加入另一個數組就行了。看下面的實現。
        FilterChain fc2 = new FilterChain();
        fc2.addFilter(new FaceFilter());
        
        fc.addFilter(fc2);
        mp.setFc(fc);
        String result = mp.process();
        System.out.println(result);
    }

}

 

 

 四,請求責任鏈攔截,返回責任鏈攔截,並且是先進後出的堆疊模式

package com.DesignPatterns.an.Responsibility4;

public class Request {
    String requestStr;

    public String getRequestStr() {
        return requestStr;
    }

    public void setRequestStr(String requestStr) {
        this.requestStr = requestStr;
    }
}
package com.DesignPatterns.an.Responsibility4;

public class Response {
    String responseStr;

    public String getResponseStr() {
        return responseStr;
    }

    public void setResponseStr(String responseStr) {
        this.responseStr = responseStr;
    }
    
}

 

 

 

 

package com.DesignPatterns.an.Responsibility4;

public interface Filter {
    void doFilter(Request request, Response response, FilterChain chain);
}

 

 

package com.DesignPatterns.an.Responsibility4;

public class HTMLFilter implements Filter {

    

    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        //process the html tag <>
        request.requestStr = request.requestStr.replace('<', '[')
                   .replace('>', ']') + "---HTMLFilter()";
        chain.doFilter(request, response, chain);
        response.responseStr += "---HTMLFilter()";
    }

}

 

 

 

package com.DesignPatterns.an.Responsibility4;

public class SesitiveFilter implements Filter {

    

    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        request.requestStr = request.requestStr.replace("被就業", "就業")
         .replace("敏感", "") + "---SesitiveFilter()";
        chain.doFilter(request, response, chain);
        response.responseStr += "---SesitiveFilter()";
    
    }
    
    

}

 

 

 

package com.DesignPatterns.an.Responsibility4;

import java.util.ArrayList;
import java.util.List;

public class FilterChain implements Filter {
    List<Filter> filters = new ArrayList<Filter>();
    int index = 0;
    
    public FilterChain addFilter(Filter f) {
        this.filters.add(f);
        return this;
    }
    
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        if(index == filters.size()) return ;
        
        Filter f = filters.get(index);
        index ++;
        f.doFilter(request, response, chain);
    }
}

 

 

 

package com.DesignPatterns.an.Responsibility4;
/**
 * 
 * @author qingruihappy
 * @data   2018年11月6日 上午12:23:38
 * @說明:這個主要處理的就是有請求有返回的,而且要遵循先進後出的邏輯堆疊的邏輯
 * 這裡主要用到了遞迴的方法。其實也簡單
 * 我們來寫一下它的思路
 * 1:我們先把HTMLFilter,SesitiveFilter兩個過濾器載入到過濾器鏈中。
 * 2:呼叫FilterChain的doFilter方法,我們初始化index的索引是0,這個時候index++之後就會變成1,而現在我們get(0)的時候就會獲取到
 * HTMLFilter的doFilter方法,執行HTMLFilter裡面的替換的方法。
 * 3,當在HTMLFilter執行完之後會執行FilterChain裡面的doFilter的方法,因為這個時候index是1了,這個時候會把index++後設置成2,讓後執行
 * SesitiveFilter裡面的doFilter方法,在執行完SesitiveFilter裡面的替換的方法之後。
 * 4,接著呼叫FilterChain裡面的doFilter的方法,這個時候發現index是2了就會返回
 * 5,首先它會遵循方法堆疊中的先進後出的原則,回到SesitiveFilter類中執行response的相關程式碼
 * 6,然後在回到HTMLFilter類中執行response的方法
 */
public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String msg = "大家好:),<script>,敏感,被就業,網路授課沒感覺,因為看不見大家夥兒";
        Request request = new Request();
        request.setRequestStr(msg);
        Response response = new Response();
        response.setResponseStr("response");
        FilterChain fc = new FilterChain();
        fc.addFilter(new HTMLFilter())
          .addFilter(new SesitiveFilter())
          ;
        
        fc.doFilter(request, response, fc);
        System.out.println(request.getRequestStr());
        System.out.println(response.getResponseStr());
    }

}
大家好:),[script],,就業,網路授課沒感覺,因為看不見大家夥兒---HTMLFilter()---SesitiveFilter()
response---SesitiveFilter()---HTMLFilter()

 

五,servlet過濾器的一覽

 

 

 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /* 在訪問的時候執行 */
        System.out.println("======= 開始執行doFilter ========");
        // 轉發到下一個元件,進行後續的處理(元件可以是一個過濾器,也可以是一個servlet)
        chain.doFilter(request, response);
        System.out.println("======= 結束執行doFilter ========");
        
    }

 

是不是很像啊,假如有多個過濾器的話那麼我們就在xml檔案中進行多個配置

如下面的。

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class BasicsFilter implements Filter {

    public BasicsFilter() {
        // 容器(伺服器)啟動時執行
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        /* 容器(伺服器)時執行 */
        System.out.println("======== 初始化方法 ========");
        // 獲取的是web.xml中配置Filter時設定的值,引數為設定值得名稱,若引數不存在,則返回空
        String initParam = fConfig.getInitParameter("param");
        System.out.println("param ========" + initParam);
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /* 在訪問的時候執行 */
        System.out.println("======= 開始執行doFilter ========");
        // 轉發到下一個元件,進行後續的處理(元件可以是一個過濾器,也可以是一個servlet)
        chain.doFilter(request, response);
        System.out.println("======= 結束執行doFilter ========");
        
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }
}

 

 

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class otherFilter implements Filter {

    public otherFilter() {
        // 容器(伺服器)啟動時執行
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        /* 容器(伺服器)時執行 */
        System.out.println("======== 初始化方法 ========");
        // 獲取的是web.xml中配置Filter時設定的值,引數為設定值得名稱,若引數不存在,則返回空
        String initParam = fConfig.getInitParameter("param");
        System.out.println("param ========" + initParam);
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /* 在訪問的時候執行 */
        System.out.println("======= 開始執行doFilter ========");
        // 轉發到下一個元件,進行後續的處理(元件可以是一個過濾器,也可以是一個servlet)
        chain.doFilter(request, response);
        System.out.println("======= 結束執行doFilter ========");
        
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }
}

 

在下面的xml中有兩個攔截器,它是按照在xml中的順序執行的。從這裡我們不難看出,誰在前面就會先通過xml的解析jar包把誰載入到list或者陣列中來,這樣的話就會先執行誰,是不是和我們上面4的案例很像呢。

 

 

<filter>
    <filter-name>basicsFilter</filter-name>
    <filter-class>com.hudongwu.filter.BasicsFilter</filter-class>
    <init-param><!-- 設定在過濾器中執行初始化方法時,獲取的值 -->
        <param-name>param</param-name>
        <param-value>studyFilter</param-value>
    </init-param>
</filter>

<filter>
    <filter-name>otherFilter</filter-name>
    <filter-class>com.hudongwu.filter.otherFilter</filter-class>
    <init-param><!-- 設定在過濾器中執行初始化方法時,獲取的值 -->
        <param-name>param</param-name>
        <param-value>otherFilter</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>basicsFilter</filter-name>
    <!-- 設定為訪問該網站所有地址都需要通過該過濾器 -->
    <url-pattern>/*</url-pattern>
    <!-- 設定為只有訪問該網站的/Helloword地址時才通過該過濾器 -->
    <url-pattern>/Helloword</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>otherFilter</filter-name>
    <!-- 設定為訪問該網站所有地址都需要通過該過濾器 -->
    <url-pattern>/*</url-pattern>
    <!-- 設定為只有訪問該網站的/otherFilter地址時才通過該過濾器 -->
    <url-pattern>/otherFilter</url-pattern>
</filter-mapping>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ll