繼承HttpServletRequestWrapper以實現在Filter中修改HttpServletRequest的參數

來源:互聯網
上載者:User
一 簡介

如題所示,有時候我們需要在一個請求到達Controller之前能夠截獲其請求,並且根據其具體情況對 HttpServletRequest 中的參數進行過濾或者修改。這時,有的同學可能會想:我們是否可以在一個Filter中將 HttpServletRequest 裡的所有參數都取出來分別進行過濾然後再放回到該HttpServletRequest 中呢。

很顯然,在 HttpServletRequest 貌似只有 setAttribute(String name, Object o) 這個方法可以設定參數,但是我們經過嘗試之後可以發現:使用 setAttribute(String name, Object o) 方法來重新設定參數顯然是不行的,因為在Controller中擷取參數本質上還是調用的ServletRequest的public String getParameter(String name) 或者 public String[] getParameterValues(String name) 方法,因此想要達到“在Filter中修改HttpServletRequest的參數”的目的,顯然是需要使用裝飾模式來複寫這些方法才行的

在正式代碼之前,我還是先簡單介紹下ServletRequest、HttpServletRequest、ServletRequestWrapper以及HttpServletRequestWrapper這幾個介面或者類之間的層次關係,並說明“繼承HttpServletRequestWrapper類以實現在Filter中修改HttpServletRequest的參數”這種方式的原理是什麼

如果我們從網上下載tomcat的原始碼並查看的話,就可以很清楚地看到這幾個類之間的層次關係了,在eclipse中看,它們之間的層次關係是這樣的:

如果這個圖表還不夠清楚地話,我還畫了一個簡單的UML結構圖:

註:因為我現在沒有下載專門的UML建模工具,因此就使用“畫圖”工具簡單地畫了一下類圖,同時這裡的ModifyParametersWrapper 是我後面舉例用到的的一個自訂的類

如果學過“裝飾模式”的童鞋可能已經發現了,上面這個關係毫無疑問是一個很標準的裝飾模式: ServletRequest    抽象組件 HttpServletRequest    抽象組件的一個子類,它的執行個體被稱作“被裝飾者” ServletRequestWrapper    一個基本的裝飾類,這裡是非抽象的 HttpServletRequestWrapper    一個具體的裝飾者,當然這裡也繼承了HttpServletRequest這個介面,是為了擷取一些在ServletRequest中沒有的方法 ModifyParametersWrapper    同樣是 一個具體的裝飾者(PS:我自訂的一個類)

註:一個標準的裝飾模式的UML類圖是這樣的:

 

 

那麼問題來了,如何在Filter中修改後台Controller中擷取到的HttpServletRequest中的參數。

答:很簡單,只需要在Filter中自訂一個類繼承於HttpServletRequestWrapper,並複寫getParameterNames、getParameter、getParameterValues等方法即可 二 代碼實現

(1)自訂的過濾器ModifyParametersFilter.java: package cn.zifangsky.filter; import java.io.IOException; import java.util.Enumeration; import java.util.Map; import java.util.Vector; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import org.springframework.web.filter.OncePerRequestFilter; public class ModifyParametersFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { ModifyParametersWrapper mParametersWrapper = new ModifyParametersWrapper(request); filterChain.doFilter(mParametersWrapper, response); } /** * 繼承HttpServletRequestWrapper,建立裝飾類,以達到修改HttpServletRequest參數的目的 */ private class ModifyParametersWrapper extends HttpServletRequestWrapper { private Map<String, String[]> parameterMap; // 所有參數的Map集合 public ModifyParametersWrapper(HttpServletRequest request) { super(request); parameterMap = request.getParameterMap(); } // 重寫幾個HttpServletRequestWrapper中的方法 /** * 擷取所有參數名 * * @return 返回所有參數名 */ @Override public Enumeration<String> getParameterNames() { Vector<String> vector = new Vector<String>(parameterMap.keySet()); return vector.elements(); } /** * 擷取指定參數名的值,如果有重複的參數名,則返回第一個的值 接收一般變數 ,如text類型 * * @param name * 指定參數名 * @return 指定參數名的值 */ @Override public String getParameter(String name) { String[] results = parameterMap.get(name); if (results == null || results.length <= 0) return null; else { System.out.println("修改之前: " + results[0]); return modify(results[0]); } } /** * 擷取指定參數名的所有值的數組,如:checkbox的所有資料 * 接收陣列變數 ,如checkobx類型 */ @Override public String[] getParameterValues(String name) { String[] results = parameterMap.get(name); if (results == null || results.length <= 0) return null; else { int length = results.length; for (int i = 0; i < length; i++) { System.out.println("修改之前2: " + results[i]); results[i] = modify(results[i]); } return results; } } /** * 自訂的一個簡單修改原參數的方法,即:給原來的參數值前面添加了一個修改標誌的字串 * * @param string * 原參數值 * @return 修改之後的值 */ private String modify(String string) { return "Modified: " + string; } } }

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 package cn . zifangsky . filter ;   import java . io . IOException ; import java . util . Enumeration ; import java . util . Map ; import java . util . Vector ;   import javax . servlet . FilterChain ; import javax . servlet . ServletException ; import javax . servlet . http . HttpServletRequest ; import javax . servlet . http . HttpServletRequestWrapper ; import javax . servlet . http . HttpServletResponse ;   import org . springframework . web . filter . OncePerRequestFilter ;   public class ModifyParametersFilter extends OncePerRequestFilter {        @Override      protected void doFilterInternal ( HttpServletRequest request , HttpServletResponse response , FilterChain filterChain )              throws ServletException , IOException {          ModifyParametersWrapper mParametersWrapper = new ModifyParametersWrapper ( request ) ;          filterChain . doFilter ( mParametersWrapper , response ) ;      }        /**      * 繼承HttpServletRequestWrapper,建立裝飾類,以達到修改HttpServletRequest參數的目的      */      private class ModifyParametersWrapper extends HttpServletRequestWrapper {          private Map < String , String [ ] > parameterMap ; // 所有參數的Map集合            public ModifyParametersWrapper ( HttpServletRequest request ) {              super ( request ) ;              parameterMap = request . getParameterMap ( ) ;          }            // 重寫幾個HttpServletRequestWrapper中的方法          /**          * 擷取所有參數名          *          * @return 返回所有參數名          */          @Override          public Enumeration <String> getParameterNames ( ) {              Vector <String> vector = new Vector <String> ( parameterMap . keySet ( ) ) ;              return vector . elements (

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.