使用Filter解决请求参数乱码问题
首先,要知道Tomcat将接收到浏览器传过来的请求头或者请求体中的请求参数解析出来并且使用ISO8859-1进行解码后放在了ParameterMap里面。
由于我们无法在Tomcat写入Map之前就将请求参数乱码问题解决,所以只能替换掉请求对象,这里使用到了装饰者设计模式,自己创建一个请求对象,这个请求对象中的Map的数据就来自于原始请求对象的Map进行乱码解决之后的数据。那么,上代码。
/*the decorator make HttpServletRequest more strong ,you should know the parameter in Method
* doFilter bottom is HttpServletRequest
* */
public class EncodingDecorator extends HttpServletRequestWrapper {
private Map<String,String[]> map;
//因为ServletRequestWrapper中没有无参构造器,所以这里的子类也不能有无参构造器
public EncodingDecorator(HttpServletRequest request) {
super(request);
map = this.getParameterMap();
}
@Override
public Map<String, String[]> getParameterMap() {
//java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap
//这个原来获取到的ParameterMap是不可修改的,所以只能建立一个新的Map
//获取乱码数据
Map<String, String[]> originalMap = super.getParameterMap();
Map<String, String[]> newMap = new HashMap<>();
//遍历map,把其中的每一个数据都给取出来一个一个的解决乱码问题
for(String key:originalMap.keySet()){
//使用每一个key,取出相应的value
String[] values = originalMap.get(key);
//遍历values,取出每一个数据进行打散重装
for(int i = 0;i < values.length;i++){
try {
//打散(编码)重装(解码)
values[i] = new String(values[i].getBytes("ISO8859-1"), StandardCharsets.UTF_8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
//把打散重装好的字符数组给装到咱们创建的新map中,实现了map的乱码解决
newMap.put(key,values);
}
return newMap;
}
@Override
public String getParameter(String name) {
//取出这个类实例对象的map,然后根据key取出value
return this.getParameterValues(name)[0];
}
@Override
public Enumeration<String> getParameterNames() {
Set<String> set = map.keySet();
Vector vector = (Vector)set;
return vector.elements();
}
@Override
public String[] getParameterValues(String name) {
return map.get(name);
}
}
注意:getParameterMap方法每次请求只需要调用一次,因为一开始Tomcat使用的是ISO8859-1进行解码,所以我们要以相同的字符集再次将字符串给变成字符序列,也就是要进行编码。而编码完成之后,我们使用的是UTF-8来进行的解码,若是重复调用的话又会出现乱码了。所以我就定义了一个成员变量map,当类实例化时调用getParameterMap方法初始化map,这样子其它方法调用的时候只需要使用这个map就可以了。
上面就是咱们重新造出来的request请求对象了,接下来就到Filter中狸猫换太子咯
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//这里的req底层实际上是HttpServletRequest
//解决中文乱码问题思路,替换掉存储数据的Map,使得乱码修正
//但是后面的Servlet是通过request来获取Map的,所以要替换掉request
//解决请求乱码问题,创建自定义的请求对象
req = new EncodingDecorator((HttpServletRequest)req);
chain.doFilter(req,resp);
}
这样子就解决了请求参数的中文乱码问题了。