继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
2017-07-24 21:01
561 查看
一 简介
如题所示,有时候我们需要在一个请求到达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:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 | 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 | <filter> <filter-name>ModifyParametersFilter</filter-name> <filter-class>cn.zifangsky.filter.ModifyParametersFilter</filter-class> </filter> <filter-mapping> <filter-name>ModifyParametersFilter</filter-name> <url-pattern>/param/*</url-pattern> <!-- 直接从客户端过来的请求以及通过forward过来的请求都要经过该过滤器 --> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> |
1234567891011121314 | package cn.zifangsky.controller; import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam; @Controllerpublic class TestModifyController { @RequestMapping("/param/modify.html") public void modify(@RequestParam("name") String name){ System.out.println("修改之后: " + name); }} |
1 2 | 修改之前2: abc 修改之后: Modified: abc |
注:tomcat-8.5.5源码下载地址:http://pan.baidu.com/s/1skWOso9
相关文章推荐
- 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
- 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
- 继承HttpServletRequestWrapper以实现在Filter中修改HttpServletRequest的参数
- 使用HttpServletRequestWrapper在filter修改request参数
- SpringBoot拦截Request修改里面参数内容(HttpServletRequestWrapper)
- 继承HttpServletRequestWrapper 实现request中流的重复获取
- HttpServletRequestWrapper,HttpServletResponseWrapper在过滤器Filter中的使用
- HttpServletRequestWrapper 实现xss注入(2)
- jsp转html静态化(二)继承HttpServletResponseWrapper 实现自己的response包装
- HttpServletRequestWrapper重新并修改http请求信息
- 利用HttpServletRequestWrapper和filter改变request的getParameter方法
- CAS-Client客户端研究(四)-HttpServletRequestWrapperFilter
- 利用Filter及HttpServletResponseWrapper修改Response的内容(内容更改利用正则表达式)
- 【转】HttpServletRequestWrapper 实现xss注入
- HttpServletRequest和HttpServletResponse实现登录(附乱码处理代码)(2017.9.28第一次修改版)
- Struts2 Filter 和 HttpServletRequestWrapper出现的问题
- 修改HttpServletRequest的参数【转】
- CAS-Client客户端研究--HttpServletRequestWrapperFilter
- HttpServletRequestWrapper 实现xss注入
- HttpServletRequestWrapper采用装饰模式重新封装request,并打印request请求相关参数。