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

一 簡介

如題所示,有時候我們需要在一個請求到達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中看,它們之間的層次關係是這樣的:

20160924212148

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

20160924212657710

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

如果學過“裝飾模式”的童鞋可能已經發現了,上面這個關係毫無疑問是一個很標準的裝飾模式

  • ServletRequest    抽象組件
  • HttpServletRequest    抽象組件的一個子類,它的實例被稱作“被裝飾者”
  • ServletRequestWrapper    一個基本的裝飾類,這裏是非抽象的
  • HttpServletRequestWrapper    一個具體的裝飾者,當然這裏也繼承了HttpServletRequest這個接口,是爲了獲取一些在ServletRequest中沒有的方法
  • ModifyParametersWrapper    同樣是 一個具體的裝飾者(PS:我自定義的一個類)

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

 

 

26160050

那麼問題來了,如何在Filter中修改後臺Controller中獲取到的HttpServletRequest中的參數?

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

二 代碼實現

(1)自定義的過濾器ModifyParametersFilter.java:

上面的代碼很簡單,就是添加了一個內部類:ModifyParametersWrapper,然後複寫了ServletRequest中的幾個方法,具體來說就是將原來的每個參數的值的前面加上了“Modified: ”這個字符串

(2)在web.xml中註冊該過濾器:

(3)添加一個測試使用的Controller,即:TestModifyController.java:

這裏沒有處理複雜的邏輯,僅僅只是簡單地輸出

(4)測試:

啓動項目之後訪問:http://localhost:9180/FilterDemo/param/modify.html?name=abc

可以發現,在控制檯中輸出如下:

這就表明了我們前面自定義的過濾器已經將HttpServletRequest中原來的參數成功修改了。同時,還說明SpringMVC的@RequestParam註解本質上調用的是ServletRequest中的 getParameterValues(String name) 方法而不是 getParameter(String name) 方法

注:tomcat-8.5.5源碼下載地址:http://pan.baidu.com/s/1skWOso9

參考文章:

發佈了103 篇原創文章 · 獲贊 193 · 訪問量 44萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章