<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      設計模式——責任鏈(結合Tomcat中Filter機制)

      設計模式匯總目錄

      設計模式:責任鏈模式

      說責任鏈之前,先引入一個場景,假如規(guī)定學生請假小于或等于 2 天,班主任可以批準;小于或等于 7 天,系主任可以批準;小于或等于 10 天,院長可以批準;其他情況不予批準;以此為需求,寫一個程序,你會怎么做?按著過程思維方式,最快最直白的就是,if else嘛,配合java,無非多追加學生類和各個角色的類。下面介紹的設計模式或許會給我們一些啟發(fā)。

      責任鏈模式

      責任鏈又叫做職責鏈,是屬于行為型設計模式,它的初衷是為了解決一個事件需要經(jīng)過多個對象處理是很常見的場景。責任鏈的運作流程是將所有請求的處理者通過前一對象記住其下一個對象的引用而連成一條鏈;當有請求發(fā)生時,可將請求沿著這條鏈傳遞,直到有對象處理它為止。

      在責任鏈模式中,客戶只需要將請求發(fā)送到責任鏈上即可,無須關心請求的處理細節(jié)和請求的傳遞過程,請求會自動進行傳遞。所以責任鏈將請求的發(fā)送者和請求的處理者解耦了。

      責任鏈的實現(xiàn)

      責任鏈的設計源于數(shù)據(jù)結構中的鏈表,從模式的定義中就能看出,它需要一串走下去,而每一個處理請求的對象,都需要記錄下一個處理請求的對象,即標準的數(shù)據(jù)鏈表方式。

      職責鏈模式的實現(xiàn)主要包含以下角色。

        1. 抽象處理者(Handler)角色:定義一個處理請求的接口,包含抽象處理方法和一個后繼連接。
        2. 具體處理者(Concrete Handler)角色:實現(xiàn)抽象處理者的處理方法,判斷能否處理本次請求,如果可以處理請求則處理,否則將該請求轉給它的后繼者。
        3. 客戶類(Client)角色:創(chuàng)建處理鏈,并向鏈頭的具體處理者對象提交請求,它不關心處理細節(jié)和請求的傳遞過程。


      責任鏈模式的本質是解耦請求與處理,讓請求在處理鏈中能進行傳遞與被處理;理解責任鏈模式應當理解其模式,而不是其具體實現(xiàn)。責任鏈模式的獨到之處是將其節(jié)點處理者組合成了鏈式結構,并允許節(jié)點自身決定是否進行請求處理或轉發(fā),相當于讓請求流動起來。

      UML類圖如下:

       

      模式的實現(xiàn)例子:

      參照以上的思想,我們針對一開始的場景編寫請假的程序:

      public class LeaveApprovalTest {
          public static void main(String[] args) {
              //組裝責任鏈
              Leader teacher1 = new ClassAdviser();
              Leader teacher2 = new DepartmentHead();
              Leader teacher3 = new Dean();
              //Leader teacher4=new DeanOfStudies();
              teacher1.setNext(teacher2);
              teacher2.setNext(teacher3);
              //teacher3.setNext(teacher4);
              //提交請求
              teacher1.handleRequest(8);
          }
      }
      //抽象處理者:領導類
      abstract class Leader {
          private Leader next;
          public void setNext(Leader next) {
              this.next = next;
          }
          public Leader getNext() {
              return next;
          }
          //處理請求的方法
          public abstract void handleRequest(int LeaveDays);
      }
      //具體處理者1:班主任類
      class ClassAdviser extends Leader {
          public void handleRequest(int LeaveDays) {
              if (LeaveDays <= 2) {
                  System.out.println("班主任批準您請假" + LeaveDays + "天。");
              } else {
                  if (getNext() != null) {
                      getNext().handleRequest(LeaveDays);
                  } else {
                      System.out.println("請假天數(shù)太多,沒有人批準該假條!");
                  }
              }
          }
      }
      //具體處理者2:系主任類
      class DepartmentHead extends Leader {
          public void handleRequest(int LeaveDays) {
              if (LeaveDays <= 7) {
                  System.out.println("系主任批準您請假" + LeaveDays + "天。");
              } else {
                  if (getNext() != null) {
                      getNext().handleRequest(LeaveDays);
                  } else {
                      System.out.println("請假天數(shù)太多,沒有人批準該假條!");
                  }
              }
          }
      }
      //具體處理者3:院長類
      class Dean extends Leader {
          public void handleRequest(int LeaveDays) {
              if (LeaveDays <= 10) {
                  System.out.println("院長批準您請假" + LeaveDays + "天。");
              } else {
                  if (getNext() != null) {
                      getNext().handleRequest(LeaveDays);
                  } else {
                      System.out.println("請假天數(shù)太多,沒有人批準該假條!");
                  }
              }
          }
      }
      //具體處理者4:教務處長類
      class DeanOfStudies extends Leader {
          public void handleRequest(int LeaveDays) {
              if (LeaveDays <= 20) {
                  System.out.println("教務處長批準您請假" + LeaveDays + "天。");
              } else {
                  if (getNext() != null) {
                      getNext().handleRequest(LeaveDays);
                  } else {
                      System.out.println("請假天數(shù)太多,沒有人批準該假條!");
                  }
              }
          }
      }

       

       

      Tomcat中Filter的執(zhí)行過程

       前邊已經(jīng)講述了關于責任鏈模式的結構與特點,下面介紹其應用場景,責任鏈模式通常在以下幾種情況使用。

        • 多個對象可以處理一個請求,但具體由哪個對象處理該請求在運行時自動確定。
        • 可動態(tài)指定一組對象處理請求,或添加新的處理者。
        • 需要在不明確指定請求處理者的情況下,向多個處理者中的一個提交請求。

      說完了責任鏈的靈活應用,下面結合tomcat中Filter的例子,進行一個標準責任鏈的解析,先來看以下Tomcat的過濾器機制:

       這是一個tomcat處理請求的過程,即它會有多個過濾器,這里的過濾器串聯(lián)起來,形成一條過濾鏈,前端或者瀏覽器發(fā)來了request,會經(jīng)過這條鏈,順著鏈依次經(jīng)過每個過濾器,最終由servlet處理后,再逐一返回。這有點像棧結構,但是這其中逐一處理,構成一條鏈,又符合責任鏈的設計規(guī)則。

      查看一下Tomcat中Filter接口的源碼:

      public interface Filter {
          void init(FilterConfig var1) throws ServletException;
          //熟悉的doFilter(), 熟悉的3個參數(shù)request, reponse, filterChain.
          void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
      
          void destroy();
      }

      下面是過濾鏈的接口源碼:

      public interface FilterChain {
          void doFilter(ServletRequest var1, ServletResponse var2) throws IOException, ServletException;
      }

        具體的過濾鏈的實現(xiàn),都會帶有一個容器,來存放該鏈中的Filter,即過濾鏈中包含一個個的過濾器。

      做一個簡化版的過濾機制

      下面我們簡化模擬一下Tomcat處理Filter的過程,

      首先定義簡易版的request和response對象

      public class Request{
          String msg;
          public void setMsg(String msg){
               this.msg=msg;
         }
      }
      
      
      public class Response{
      
        public void deal(){
         System.out.println();
      }
      }

      定義Filter接口及兩個實現(xiàn)(http校驗,消息敏感字符校驗)

      public interface Filter{
          void doFilter(Request req,Response rep,Filter filer);
      }
      
      public HttpFilter implements Filter{
          void doFilter(Request req,Response rep,Filter filer){
                System.out.println("處理了http驗證"+req.getMsg());
                filter.doFilter(req,rep,filter);
         }
      }
      
      public SensitiveFilter implements Filter{
          void doFilter(Request req,Response rep,Filter filer){
                System.out.println("處理了敏感字符替換"+req.getMsg());
                filter.doFilter(req,rep,filter);
         }
      }

      定義過濾鏈:

      public class FilterChain implements Filter{
        
          List<Filter> filterlist = new Arrary<>();
          private int index;  
      
          public FilterChain addFilter(Filter filter){
                  filterlist.add(filter);
                  return this;
          }
      
          void doFilter(Request req,Response res,Filter filter){
                if(index == filterlist.size()){
                  return;//這里是逆序處理響應的關鍵, 當index為容器大小時, 證明對request的處理已經(jīng)完成, 下面進入對response的處理.
              }
              Filter f = filterlist.get(index);//過濾器鏈按index的順序拿到filter
              index++;
              f.doFilter(request, response, filter);
         }
      }

      測試代碼:

      public class DemoBox {
          public static void main(String[] args) {
              String msg = "大家好 ";//以下三行模擬一個請求
              Request request = new Request();
              request.setMsg(msg);
      
              Response response = new Response();//響應
      
              FilterChain fc = new FilterChain();//過濾器鏈
              HttpFilter f1 = new HttpFilter();//創(chuàng)建過濾器
              SensitiveFilter f2 = new SensitiveFilter();//創(chuàng)建過濾器
             
              fc.add(f1);//把過濾器添加到過濾器鏈中
              fc.add(f2);
              fc.doFilter(request, response, fc);//直接調(diào)用過濾器鏈的doFilter()方法進行處理
      
          }
      }

         下面按著步驟,詳細解釋一下上面的代碼

      • 首先我們分別創(chuàng)建一個RequestResponse對象. Request在傳入進后端時需要依次被過濾器進行處理, Response對象在輸出時要依次被過濾器處理.
      • 我們定義了一個Filter接口,它包含處理請求的方法doFilter,這里的Filter可以理解為責任鏈中的抽象處理者
      • 依次實現(xiàn)了兩個攔截器,HttpFilter,SensitiveFilter,做具體的過濾處理,可以理解為責任鏈中具體處理者的角色
      • 實現(xiàn)一個Filter接口,做一個過濾鏈的類FilterChain,它除了基本的處理功能,還包含了一個過濾器容器FilterList,用它還存放整條鏈的Filter。
      • 接著我們調(diào)用過濾器鏈的doFilter()方法對request對象進行處理
      • 這時過濾器鏈中的index值為0, 通過index我們找到第一個過濾器并調(diào)用它的doFilter()方法
      • 進入doFilter()方法后, 首先會對request請求進行處理, 然后又調(diào)用了過濾器鏈的doFilter()方法. 這就是整個責任鏈模式的精妙之處, 它解釋了為什么要給doFilter()加上一個過濾器鏈參數(shù), 就是為了讓每個過濾器可以調(diào)用過濾器鏈本身執(zhí)行下一個過濾器。
      • 為什么要調(diào)用過濾器鏈本身? 因為當調(diào)用過濾器本身后, 程序將跳轉回到過濾器鏈的doFilter方法執(zhí)行, 這時index為1, 也就是拿到第二個過濾器, 然后繼續(xù)處理。
      • 正是由于這個跳轉, 使得過濾器中對response的處理暫時無法執(zhí)行, 它必須等待上面的對過濾器鏈的方法返回才能被執(zhí)行.
      posted @ 2020-12-23 09:56  糖拌西紅柿  閱讀(2473)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 丁香五月亚洲综合深深爱| 亚洲国产中文字幕在线视频综合 | 亚洲爆乳WWW无码专区| 亚洲高清 一区二区三区| 中文字幕在线日韩| 天津市| 黑人巨大粗物挺进了少妇| 色五开心五月五月深深爱| 宅男噜噜噜66网站高清| 曰韩无码二三区中文字幕| 亚洲一区二区偷拍精品| 亚洲区成人综合一区二区| 中国少妇人妻xxxxx| 青青青爽在线视频观看| 亚洲综合色婷婷中文字幕| 国产一级r片内射免费视频| 久久大香萑太香蕉av黄软件| 3d无码纯肉动漫在线观看| 夜鲁鲁鲁夜夜综合视频| 疯狂做受XXXX高潮国产| 久久免费偷拍视频有没有| 视频一区视频二区中文字幕| 日本A级视频在线播放| 亚洲日韩日本中文在线| 天堂mv在线mv免费mv香蕉| 天堂中文8资源在线8| 亚洲精品一二三伦理中文| 国产精品久久人人做人人爽| 亚洲午夜成人精品电影在线观看 | 狠狠色噜噜狠狠狠狠2021| 美女一区二区三区亚洲麻豆| 四虎永久在线精品免费看| 国产亚洲综合欧美视频| 亚洲国产欧美在线观看| 日韩秘 无码一区二区三区 | 无码日韩精品一区二区三区免费| 97精品伊人久久久大香线蕉| 人妻日韩人妻中文字幕| 熟女人妇 成熟妇女系列视频| 国模少妇无码一区二区三区| 久热这里只有精品视频六|