使用HttpServletRequestWrapper重写Request请求参数

前言

上一篇文章中讲述到,在做一个PHP语言开发的系统集成JAVA语言开发的系统功能时遇到获取传参的问题,最终是使用**request.getInputStream()**方式使问题得以解决,但是同时又带来了新的问题,request.getInputStream()本身获取到的是request请求内容的字节流,然后使用IOUtils.toString(IOUtils.toString)转为字符串,这种方式无法满足我的Controller层(springMVC)参数与实例对象的映射,增加了业务层处理参数的复杂度。

问题分析

既然request.getInputStream()获取参数无法满足Controller层需求,request.getParameter()方式可以满足但又无法获取参数,那何不先用request.getInputStream()获取到参数之后再重新设置request的参数以满足Controller层需求。但是,对于HttpServletRequest而言,貌似只有使用setAttribute(String name, Object o) 这个方法可以设置参数,经过尝试之后发现:使用 setAttribute(String name, Object o) 方法来重新设置参数不可行,因为在Controller中获取参数本质上还是调用的ServletRequest的public String getParameter(String name) 或者 public String[] getParameterValues(String name) 方法,了解一番之后,才明白需要使用装饰模式来复写这些方法才可行。因此,决定使用HttpServletRequestWrapper重写Request请求参数。

代码实现

Filter能在request到达servlet的服务方法之前拦截HttpServletRequest对象,而在服务方法转移控制后又能拦截HttpServletResponse对象,因此,可以使用filter来实现特定的任务————重写Request请求参数。

使用HttpServletRequestWrapper重写

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
/*
* Copyright (c) 2017 GRGBanking
* @File: ChangeRequestWrapper.java
* @Description:
* @Author: sunys
* @Date: 18-4-24 下午3:31
* @since:
*
*/

package com.grgbanking.framework.core.common;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;

/**
* Created by sunys on 2018/4/24.
*/
public class ChangeRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> parameterMap; // 所有参数的Map集合

public ChangeRequestWrapper(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){
return results[0];
}
return null;
}


/**
* 获取指定参数名的所有值的数组,如:checkbox的所有数据
* 接收数组变量 ,如checkobx类型
*/
@Override
public String[] getParameterValues(String name) {
return parameterMap.get(name);
}

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

public void setParameterMap(Map<String, String[]> parameterMap) {
this.parameterMap = parameterMap;
}
}

web.xml增加一个过滤器处理

web.xml
1
2
3
4
5
6
7
8
9
10
...
<filter>
<filter-name>securityAccessFilter</filter-name>
<filter-class>com.grgbanking.framework.core.common.SecurityAccessFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>securityAccessFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...

所有的请求,都会验证此filter。

新增Filter实现特定的任务

SecurityAccessFilter.java
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

/*
* Copyright (c) 2017 GRGBanking
* @File: SecurityAccessFilter.java
* @Description:
* @Author: sunys
* @Date: 18-5-4 上午9:33
* @since:
*
*/

package com.grgbanking.framework.core.common;

import com.grgbanking.framework.utils.AjaxUtils;
import net.sf.json.JSONObject;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
* 过滤器,在web.xml中配置,指定对哪些路径进行过滤。
*/
public class SecurityAccessFilter implements Filter {
private Logger logger = Logger.getLogger(SecurityAccessFilter.class);

public void destroy() {

}

public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
String uri = request.getRequestURI();
if (uri.endsWith(".php")){
//首先获取参数字符串
String json = new String(IOUtils.toString(request.getInputStream()));
ServletRequest arg_tem = changeParam(json,request,response);
if(arg_tem != null){
//使用复写后的wrapper
arg0 = arg_tem;
}
}
arg2.doFilter(arg0, arg1);
}

private ServletRequest changeParam(String json, HttpServletRequest request, HttpServletResponse response) {
try {
System.out.println(json);
// 调用ChangeRequestWrapper 改变参数
ChangeRequestWrapper changeRequestWrapper = new ChangeRequestWrapper(request);
Map<String, String[]> parameterMap = new HashMap<>(changeRequestWrapper.getParameterMap());
JSONObject jsonObject = JSONObject.fromObject(json);
String param = jsonObject.get("param").toString();
parameterMap.put("param",new String[]{param});
changeRequestWrapper.setParameterMap(parameterMap);
return changeRequestWrapper;
} catch (Exception e) {
e.printStackTrace();
AjaxUtils.renderFailureOther("解析请求参数时发生异常!", request,response);
return null;
}
}
public void init(FilterConfig arg0) throws ServletException {

}
}