您的位置:首页 > 运维架构 > Tomcat

解决Spring MVC中get请求参数乱码的一种不改tomcat配置解决方法

2017-03-06 11:28 567 查看
解决Spring MVC中get请求参数乱码有很多种方式,常见的有这些:

1.如果使用tomcat作为服务器,那么修改tomcat配置文件conf/server.xml中,在  <Connector port="8082" protocol="HTTP/1.1"  中加入  URIEncoding="utf-8"的编码集

2.在使用的地方转换一次String XXX= new String(request.getParameter("XXX").getBytes("ISO-8859-1"), "UTF-8");

这里提供一种不想改tomcat配置又不想像方法2中那么麻烦,想要一劳永逸,可以看看下面的方式.

经过Spring mvc的源码分析,得知了Spring mvc在获取request中的参数自动填充到我们controller中的方法时,是通过request.getParameterValues()方法获取的参数,如下:

org.springframework.web.method.annotation.RequestParamMethodArgumentResolver

@Override
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest webRequest) throws Exception {
Object arg;

HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
MultipartHttpServletRequest multipartRequest =
WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);

if (MultipartFile.class.equals(parameter.getParameterType())) {
assertIsMultipartRequest(servletRequest);
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
arg = multipartRequest.getFile(name);
}
else if (isMultipartFileCollection(parameter)) {
assertIsMultipartRequest(servletRequest);
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
arg = multipartRequest.getFiles(name);
}
else if(isMultipartFileArray(parameter)) {
assertIsMultipartRequest(servletRequest);
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
arg = multipartRequest.getFiles(name).toArray(new MultipartFile[0]);
}
else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
assertIsMultipartRequest(servletRequest);
arg = servletRequest.getPart(name);
}
else if (isPartCollection(parameter)) {
assertIsMultipartRequest(servletRequest);
arg = new ArrayList<Object>(servletRequest.getParts());
}
else if (isPartArray(parameter)) {
assertIsMultipartRequest(servletRequest);
arg = RequestPartResolver.resolvePart(servletRequest);
}
else {
arg = null;
if (multipartRequest != null) {
List<MultipartFile> files = multipartRequest.getFiles(name);
if (!files.isEmpty()) {
arg = (files.size() == 1 ? files.get(0) : files);
}
}
if (arg == null) {
String[] paramValues = webRequest.getParameterValues(name);//看这里
if (paramValues != null) {
arg = paramValues.length == 1 ? paramValues[0] : paramValues;
}
}
}

return arg;
}


知道Spring mvc怎么做的了,那就简单了,我们只需要包装一下request即可,然spring mvc在调用这个getParameterValues方法时得到的是正确的编码过后的值即可

提供了两种方式,一种是静态代理,另一种是动态代理

注释很明了,也就不做过多的叙说了

方式一(静态代理):

public class EncodingFilter extends OncePerRequestFilter {
private String encoding;

public void setEncoding(String encoding) {
this.encoding = encoding;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
// 设置请求响应字符编码
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
// 新增加的代码
HttpServletRequest req = new GetHttpServletRequestWrapper(request, encoding);
// 传递给目标servlet或jsp的实际上时包装器对象的引用,而不是原始的HttpServletRequest对象
chain.doFilter(req, response);
}

class GetHttpServletRequestWrapper extends HttpServletRequestWrapper {

private String charset = "UTF-8";

public GetHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}

/**
* 获得被装饰对象的引用和采用的字符编码
*
* @param request
* @param charset
*/
public GetHttpServletRequestWrapper(HttpServletRequest request, String charset) {
super(request);
this.charset = charset;
}

/**
* 获取单个参数也复写
*/
public String getParameter(String name) {
String value = super.getParameter(name);
try {
if(value != null){
value=new String(value.getBytes("ISO-8859-1"),charset);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return value;
}

/*
* Spring MVC方法参数自动注入调用的是这个方法
* {@link RequestParamMethodArgumentResolver}
*/
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
values[i] = new String(values[i].getBytes("ISO-8859-1"),charset);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
return values;
}
}

}

方式二(动态代理):

public class EncodingFilter extends OncePerRequestFilter {
private String encoding;

public void setEncoding(String encoding) {
this.encoding = encoding;
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
// 设置请求响应字符编码
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);

// 传递给目标servlet或jsp的实际上是动态代理的对象,而不是原始的HttpServletRequest对象
request = (HttpServletRequest) Proxy.newProxyInstance(request.getClass().getClassLoader(), request.getClass().getInterfaces(), new MyInvacationHandler(request));
chain.doFilter(request, response);
}

class MyInvacationHandler implements InvocationHandler{
private HttpServletRequest request;
MyInvacationHandler(HttpServletRequest request){
this.request=request;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
switch (method.getName()) {
case "getParameter":
String value = request.getParameter((String)args[0]);
try {
if(value != null){
value=new String(value.getBytes("ISO-8859-1"),encoding);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return value;
case "getParameterValues":
String[] values = request.getParameterValues((String)args[0]);
if (values != null) {
for (int i = 0; i < values.length; i++) {
try {
values[i] = new String(values[i].getBytes("ISO-8859-1"),encoding);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
return values;
default:
return method.invoke(request, args);
}
}

}
}


为什么继承OncePerRequestFilter?点击打开链接

web.xml中加入

<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>XXXXXX.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息