Servlet处理get请求时的中文乱码问题
来源:http://mycloudream.github.io
我们都知道,使用Servlet处理get请求时,如果get请求的参数中有中文,直接接收会是乱码,这个时候我们使用类似下面的语句来处理乱码:
1 String name = request.getParameter("name"); 2 System.out.prinlnt(name); // 乱码 3 // 处理乱码 4 name = new String(name.getBytes("ISO8859-1"),"UTF-8"); 5 System.out.println(name);// 乱码问题解决
这时候每次中文都要处理,比较麻烦,我们可能会使用过滤器,使用类型下面的代码处理乱码问题:
1 public String getParameter(String name) { 2 String value = super.getParameter(name); 3 if (value == null) 4 return null; 5 String method = request.getMethod(); 6 if ("get".equalsIgnoreCase(method)) { 7 try { 8 value = new String(value.getBytes("ISO8859-1"),"UTF-8"); 9 } catch (UnsupportedEncodingException e) { 10 e.printStackTrace(); 11 } 12 } 13 return value; 14 }
但是,这是为什么呢?为什么我们需要将ISO8859-1转为UTF-8?为什么我们接收到的参数是ISO8859-1这种编码方式的?
其实很简单,只是个配置问题:
在tomcat安装目录下的conf/server.xml中,有如下的配置:
1 <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
我们可能改动过这里的port为9999,8888等自己喜欢的端口号,这里呢,也可以设置另外一个跟上述编码问题有关的参数信息:URIEncoding,该配置决定了使用get请求通过浏览器地址栏访问tomcat时的编码方式,默认的编码方式使ISO8859-1,这一点我们可以从官网文档(https://tomcat.apache.org/tomcat-7.0-doc/config/http.html) 获悉:
URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
知道了这点,接下来就简单了,我们可以这样配置,则上述代码中,就不需要再从ISO8859-1转为UTF-8了:
1 URIEncoding="UTF-8"
这显然比上述两种方式简单多了。
值得注意的是,从tomcat8.0开始,URIEncoding默认值不再是ISO8859-1,而变成了UTF-8
官方文档 (https://tomcat.apache.org/tomcat-8.0-doc/config/http.html) 中是这么说的:
URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, UTF-8 will be used unless the org.apache.catalina.STRICT_SERVLET_COMPLIANCE system property is set to true in which case ISO-8859-1 will be used.
那么也就意味着,从tomcat8.0开始,get请求中的中文参数,不需要特殊处理了。而如果是tomcat8之前的项目要迁移到tomcat8上面来,则也需要特殊注意这个问题,可能要删减代码中响应乱码的处理模块了。
Servlet中统一处理各版本tomcat的get和post请求的乱码问题
Filter是这样一种Java类:
在request到达servlet的服务方法之前拦截HttpServletRequest对象
在服务方法转移控制后又能拦截HttpServletResponse对象,处理这些响应
它功能非常强大,一般Servlet中的乱码问题也使用它来解决。
1 package cn.ucai.superwechat.filter; 2 import java.io.IOException; 3 import java.io.UnsupportedEncodingException; 4 import javax.servlet.Filter; 5 import javax.servlet.FilterChain; 6 import javax.servlet.FilterConfig; 7 import javax.servlet.ServletContext; 8 import javax.servlet.ServletException; 9 import javax.servlet.ServletRequest; 10 import javax.servlet.ServletResponse; 11 import javax.servlet.annotation.WebFilter; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletRequestWrapper; 14 import javax.servlet.http.HttpServletResponse; 15 @WebFilter(filterName = "characterEncodingFilter", urlPatterns = "/*") 16 public class CharacterEncodingFilter implements Filter { 17 private String encode = "UTF-8";// 默认UTF-8编码 18 public void init(FilterConfig filterConfig) throws ServletException { 19 String encoding = filterConfig.getInitParameter("encode"); 20 if (encoding != null) { 21 encode = encoding; 22 } 23 } 24 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) 25 throws IOException, ServletException { 26 HttpServletRequest request = (HttpServletRequest) req; 27 HttpServletResponse response = (HttpServletResponse) resp; 28 // 设置request编码 29 request.setCharacterEncoding(encode); 30 int serverVision = getServerVision(request); 31 // 设置相应信息 32 response.setContentType("text/html;charset=" + encode); 33 response.setCharacterEncoding(encode); 34 if (serverVision <= 7) { 35 chain.doFilter(new CharacterEncodingRequest(request), response); 36 } else { 37 chain.doFilter(request, response); 38 } 39 } 40 /** 41 * 得到当前运行tomcat的版本信息 42 * 43 * @param request 44 * @return 45 */ 46 private int getServerVision(HttpServletRequest request) { 47 ServletContext context = request.getServletContext(); 48 String serverInfo = context.getServerInfo();// 得到服务器信息,例如:Apache 49 // Tomcat/7.0.39 50 int serverVision = Integer.parseInt(serverInfo.substring(serverInfo.indexOf("/") + 1, serverInfo.indexOf("."))); 51 return serverVision; 52 } 53 public void destroy() { 54 System.out.println("destroy"); 55 } 56 } 57 /** 58 * 对Get方式传递的请求参数进行编码 59 */ 60 class CharacterEncodingRequest extends HttpServletRequestWrapper { 61 private HttpServletRequest request = null; 62 public CharacterEncodingRequest(HttpServletRequest request) { 63 super(request); 64 this.request = request; 65 } 66 /** 67 * 对参数重新编码 68 */ 69 @Override 70 public String getParameter(String name) { 71 String value = super.getParameter(name); 72 if (value == null) 73 return null; 74 String method = request.getMethod(); 75 if ("get".equalsIgnoreCase(method)) { 76 try { 77 value = new String(value.getBytes("ISO8859-1"), request.getCharacterEncoding()); 78 } catch (UnsupportedEncodingException e) { 79 e.printStackTrace(); 80 } 81 } 82 return value; 83 } 84 }