使用HttpServletRequestWrapper在filter修改request参数

javax.servlet.ServletRequest中的
Map<String, String[]> parameterMap = request.getParameterMap();不能被修改,原因如下:
org/apache/tomcat/embed/tomcat-embed-core/8.0.32/tomcat-embed-core-8.0.32-sources.jar!/org/apache/catalina/util/ParameterMap.java
    /**
     * Associate the specified value with the specified key in this map.  If
     * the map previously contained a mapping for this key, the old value is
     * replaced.
     *
     * @param key Key with which the specified value is to be associated
     * @param value Value to be associated with the specified key
     *
     * @return The previous value associated with the specified key, or
     *  <code>null</code> if there was no mapping for key
     *
     * @exception IllegalStateException if this map is currently locked
     */
    @Override
    public V put(K key, V value) {

        if (locked)
            throw new IllegalStateException
                (sm.getString("parameterMap.locked"));
        return (super.put(key, value));

    }

https://my.oschina.net/cwalet/blog/35431

 

 

 

 
处理过程: 
(1)页面提交请求“/sa?userid=123456789&username=rensanning” 
(2)通过Filter处理加入新参数“name=newname” 
(3)sa的Servlet中forward到“/sb?myname=rensanning&mycountry=china” 
(4)sb的Servlet中生成页面输出所有参数:userid、username、myname、mycountry、name 

第一步: 
最简单,在页面上先输出一个href为改地址的链接即可。 
 
  1. <a href="<%=request.getContextPath()%>/sa?userid=123456789&username=rensanning">Click me!!!</a>  


第二步: 
新作Filter类:ParameterFilter,配置web.xml 
 
  1. <filter-mapping>  
  2.     <filter-name>ParameterFilter</filter-name>  
  3.     <url-pattern>/*</url-pattern>  
  4. </filter-mapping>  


在doFilter方法中包装request,设置新参数值。 
 
  1. Map<String,String[]> m = new HashMap<String,String[]>(req.getParameterMap());  
  2. m.put("name", new String[]{"newname"});  
  3. req = new ParameterRequestWrapper((HttpServletRequest)req, m);  
  4.   
  5. chain.doFilter(req, res);  


包装类代码如下: 
 
  1. class ParameterRequestWrapper extends HttpServletRequestWrapper {  
  2.   
  3.     private Map<String, String[]> params;  
  4.   
  5.     public ParameterRequestWrapper(HttpServletRequest request,  
  6.             Map<String, String[]> newParams) {  
  7.         super(request);  
  8.           
  9.         this.params = newParams;  
  10.     }  
  11.   
  12.     @Override  
  13.     public String getParameter(String name) {  
  14.         String result = "";  
  15.           
  16.         Object v = params.get(name);  
  17.         if (v == null) {  
  18.             result = null;  
  19.         } else if (v instanceof String[]) {  
  20.             String[] strArr = (String[]) v;  
  21.             if (strArr.length > 0) {  
  22.                 result =  strArr[0];  
  23.             } else {  
  24.                 result = null;  
  25.             }  
  26.         } else if (v instanceof String) {  
  27.             result = (String) v;  
  28.         } else {  
  29.             result =  v.toString();  
  30.         }  
  31.           
  32.         return result;  
  33.     }  
  34.   
  35.     @Override  
  36.     public Map getParameterMap() {  
  37.         return params;  
  38.     }  
  39.   
  40.     @Override  
  41.     public Enumeration getParameterNames() {  
  42.         return new Vector(params.keySet()).elements();  
  43.     }  
  44.   
  45.     @Override  
  46.     public String[] getParameterValues(String name) {  
  47.         String[] result = null;  
  48.           
  49.         Object v = params.get(name);  
  50.         if (v == null) {  
  51.             result =  null;  
  52.         } else if (v instanceof String[]) {  
  53.             result =  (String[]) v;  
  54.         } else if (v instanceof String) {  
  55.             result =  new String[] { (String) v };  
  56.         } else {  
  57.             result =  new String[] { v.toString() };  
  58.         }  
  59.           
  60.         return result;  
  61.     }  
  62.   
  63. }  


第三步: 
sa的Servlet中,doGet()方法做forward跳转。 
Java代码  收藏代码
  1. RequestDispatcher rd = getServletContext().getRequestDispatcher("/sb?myname=rensanning&mycountry=china");  
  2.   
  3. rd.forward(request, response);  


第四步: 
sb的Servlet中生成页面输出所有QueryString和ParameterMap的参数。(代码略) 

问题: 
(1)Filter也只执行了一次 

由于RequestDispatcher.forward是Servlet之间的跳转,所以默认不走Filter。在Servlet2.4规范中定义了可以在web.xml中配置: 
Xml代码  收藏代码
  1. <filter-mapping>  
  2.     <filter-name>ParameterFilter</filter-name>  
  3.     <url-pattern>/*</url-pattern>  
  4.     <dispatcher>REQUEST</dispatcher>  
  5.     <dispatcher>FORWARD</dispatcher>  
  6. </filter-mapping>  


(2)结果的QueryString中存在forward时URL的两个参数(myname、mycountry),而ParameterMap中没有。

forward时QueryString中的参数未被放入ParameterMap??? 

如下修改wrapper类: 
Java代码  收藏代码
  1. class ParameterRequestWrapper extends HttpServletRequestWrapper {  
  2.   
  3.     private Map<String, String[]> params;  
  4.   
  5.     public ParameterRequestWrapper(HttpServletRequest request,  
  6.             Map<String, String[]> newParams) {  
  7.         super(request);  
  8.           
  9.         this.params = newParams;  
  10.   
  11.         // RequestDispatcher.forward parameter  
  12.         renewParameterMap(request);  
  13.     }  
  14.   
  15.     @Override  
  16.     public String getParameter(String name) {  
  17.         String result = "";  
  18.           
  19.         Object v = params.get(name);  
  20.         if (v == null) {  
  21.             result = null;  
  22.         } else if (v instanceof String[]) {  
  23.             String[] strArr = (String[]) v;  
  24.             if (strArr.length > 0) {  
  25.                 result =  strArr[0];  
  26.             } else {  
  27.                 result = null;  
  28.             }  
  29.         } else if (v instanceof String) {  
  30.             result = (String) v;  
  31.         } else {  
  32.             result =  v.toString();  
  33.         }  
  34.           
  35.         return result;  
  36.     }  
  37.   
  38.     @Override  
  39.     public Map getParameterMap() {  
  40.         return params;  
  41.     }  
  42.   
  43.     @Override  
  44.     public Enumeration getParameterNames() {  
  45.         return new Vector(params.keySet()).elements();  
  46.     }  
  47.   
  48.     @Override  
  49.     public String[] getParameterValues(String name) {  
  50.         String[] result = null;  
  51.           
  52.         Object v = params.get(name);  
  53.         if (v == null) {  
  54.             result =  null;  
  55.         } else if (v instanceof String[]) {  
  56.             result =  (String[]) v;  
  57.         } else if (v instanceof String) {  
  58.             result =  new String[] { (String) v };  
  59.         } else {  
  60.             result =  new String[] { v.toString() };  
  61.         }  
  62.           
  63.         return result;  
  64.     }  
  65.   
  66.     private void renewParameterMap(HttpServletRequest req) {  
  67.   
  68.         String queryString = req.getQueryString();  
  69.   
  70.         if (queryString != null && queryString.trim().length() > 0) {  
  71.             String[] params = queryString.split("&");  
  72.   
  73.             for (int i = 0; i < params.length; i++) {  
  74.                 int splitIndex = params[i].indexOf("=");  
  75.                 if (splitIndex == -1) {  
  76.                     continue;  
  77.                 }  
  78.                   
  79.                 String key = params[i].substring(0, splitIndex);  
  80.   
  81.                 if (!this.params.containsKey(key)) {  
  82.                     if (splitIndex < params[i].length()) {  
  83.                         String value = params[i].substring(splitIndex + 1);  
  84.                         this.params.put(key, new String[] { value });  
  85.                     }  
  86.                 }  
  87.             }  
  88.         }  
  89.     }  
  90.   
  91. }  
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

/**
 * Created by MyWorld on 2016/9/25.
 */
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
    /**
     * Constructs a request object wrapping the given request.
     *
     * @param request The request to wrap
     * @throws IllegalArgumentException if the request is null
     * http://www.cnblogs.com/softidea/p/5903873.html
     *
     */
    private Map<String, String[]> params;

    public ParameterRequestWrapper(HttpServletRequest request, Map<String, String[]> params) {
        super(request);
        this.params = params;
        addHeaderInfoToParams(request);
    }

    private void addHeaderInfoToParams(HttpServletRequest request) {
        request.getHeader("_pid");

    }

    @Override
    public String getParameter(String name) {
        String[] values = getParameterValues(name);
        if (values == null || values.length == 0) {
            return null;
        } else {
            return values[0];
        }
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return params;
    }

    @Override
    public Enumeration<String> getParameterNames() {
        return new Vector(params.keySet()).elements();
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] values = params.get(name);
        if (values == null) {
            return null;
        } else {
            return values;
        }
    }


}
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by MyWorld on 2016/9/25.
 */
public class AddExtraToParamsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        Map<String, String[]> params = new HashMap<>(request.getParameterMap());

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String pid = httpServletRequest.getHeader("_pid");
        if (pid != null) {
            params.put("pid", new String[]{pid});
        }
        request = new ParameterRequestWrapper(httpServletRequest, params);
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
    }
}

 

 

再次运行代码: 
(1)Filter进入两次: 
引用
URL:http://localhost:8080/t/sa 
***-----From QueryString-----*** 
userid=123456789 
username=rensanning 
***-----From ParameterMap-----*** 
username=rensanning, 
userid=123456789,


引用
URL:http://localhost:8080/t/sb 
***-----From QueryString-----*** 
myname=rensanning 
mycountry=china 
***-----From ParameterMap-----*** 
username=rensanning, 
name=newname, 
userid=123456789,


(2)最终页面结果: 
引用

***-----From QueryString-----*** 

myname=rensanning 

mycountry=china 




***-----From ParameterMap-----*** 

username=rensanning, 

name=newname, 

userid=123456789, 

mycountry=china, 

myname=rensanning, 

 

http://rensanning.iteye.com/blog/1706208

 

posted @ 2016-09-25 04:30  沧海一滴  阅读(5844)  评论(0编辑  收藏  举报