为什么会有这种需求?
比如:要求对xml类型的特殊字符进行值转换过滤,以防止XSS注入攻击。比如:在请求某些url时,全部需要新加入一个以前代码没有的参数项,其值可能是从cookie/xml/propertis 文件读取的。
首先,一看这个问题,会想到2个方面:
1,spring 拦截器:拦截需要的url,实现 preHandle(前置处理方法) 方法,在其中,对 request 进行处理。
2,servlet Filter过滤器:过滤需要的url,实现 doFilter 方法,在其中,对 request 进行处理。并把此 Filter 配置在 spring 的 DispatcherServlet 之前。
经过实验:方式1——spring 拦截器,实现不了题目上的功能。set设置不会报错,但是,spring自动参数绑定取不到 增加/修改 后的值。
那么,只能从 servlet Filter过滤器 入手,来解决此问题。
开始尝试模式:
1,request.setAttribute("abc", 1); 直接对 request set 一个参数项。结果,spring不鸟此值。失败!
2,request.getParameterMap().put("abc", new String[] { "1" }); 给 request 的请求参数map加入一个新值。结果,直接报错:java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap 。SB了,这就是不让人修改此map啊。
3,简单的能随便想到的,都不行,那只能百度google了。果然,干货在此:
class ParameterRequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> params;
public ParameterRequestWrapper(HttpServletRequest request, Map<String, String[]> newParams) {
super(request);
this.params = newParams;
renewParameterMap(request);
}
@Override
public String getParameter(String name) {
String result = "";
Object v = params.get(name);
if (v == null) {
result = null;
} else if (v instanceof String[]) {
String[] strArr = (String[]) v;
if (strArr.length > 0) {
result = strArr[0];
} else {
result = null;
}
} else if (v instanceof String) {
result = (String) v;
} else {
result = v.toString();
}
return result;
}
@Override
public Map<String, String[]> getParameterMap() {
return params;
}
@Override
public Enumeration<String> getParameterNames() {
return new Vector<String>(params.keySet()).elements();
}
@Override
public String[] getParameterValues(String name) {
String[] result = null;
Object v = params.get(name);
if (v == null) {
result = null;
} else if (v instanceof String[]) {
result = (String[]) v;
} else if (v instanceof String) {
result = new String[] { (String) v };
} else {
result = new String[] { v.toString() };
}
return result;
}
private void renewParameterMap(HttpServletRequest req) {
String queryString = req.getQueryString();
if (queryString != null && queryString.trim().length() > 0) {
String[] params = queryString.split("&");
for (int i = 0; i < params.length; i++) {
int splitIndex = params[i].indexOf("=");
if (splitIndex == -1) {
continue;
}
String key = params[i].substring(0, splitIndex);
if (!this.params.containsKey(key)) {
if (splitIndex < params[i].length()) {
String value = params[i].substring(splitIndex + 1);
this.params.put(key, new String[] { value });
}
}
}
}
}
}
你需要这么一个辅助类,其实就是自己定义一个request啦。然后,我要加入一个新参数,然后:
Map<String, String[]> m = new HashMap<String, String[]>(request.getParameterMap());
m.put("abc", new String[] { "1" });
request = new ParameterRequestWrapper(request, m);
到此,Filter 完成,挂在web.xml 中一测试,OK,spring成功绑定到此值。
然后,如果你要修改前台传递过来的 value 值,那么,也需要如上的辅助类,原理相通。