Servlet技术疑问:默认字符编码设置后能否修改?
嘿,这个问题我太熟了——你踩了Servlet字符编码处理里最常见的一个坑!
为什么你的设置没生效?
Servlet规范里有个关键规则:request.setCharacterEncoding()必须在第一次获取请求参数(比如getParameter()、getParameterMap())之前调用。
原因很简单:当你第一次调用任何获取参数的方法时,Servlet容器就已经开始用默认编码(通常是ISO-8859-1)解析请求体里的参数了。一旦解析完成,后续再设置字符编码根本不会触发重新解析,所以你的request.setCharacterEncoding("UTF-8")相当于白写了——参数已经用旧编码解析完存在内存里了。
看你的代码,你先调用了request.getParameter("name"),之后才设置编码,这顺序完全搞反了,自然不会生效。
修正方案
1. 调整代码顺序(针对POST请求)
把设置编码的代码移到获取参数的前面,这是最核心的修复:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { final HttpServletRequest request = (HttpServletRequest) servletRequest; final HttpServletResponse response = (HttpServletResponse) servletResponse; // 先设置请求编码,这一步必须在getParameter之前! request.setCharacterEncoding("UTF-8"); // 现在再获取参数,就会用UTF-8解析了 final String name = request.getParameter("name"); // 顺便建议设置响应编码,避免返回内容乱码 response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); chain.doFilter(request, response); }
2. GET请求的额外处理
如果你的请求是GET方式,上面的方法可能还是不生效——因为GET参数是放在URL里的,不是请求体,request.setCharacterEncoding()只对请求体(POST参数)生效。这时候需要修改容器的配置:
比如Tomcat,找到conf/server.xml里的Connector节点,添加URIEncoding="UTF-8"属性:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/>
这样Tomcat就会用UTF-8解析GET请求的URL参数了。
总结
核心原则就是:编码设置要抢在参数解析之前执行,顺序绝对不能错。POST和GET请求的编码处理逻辑略有不同,根据你的实际场景调整即可。
内容的提问来源于stack exchange,提问作者Bala

