Servlet技术疑问:获取请求参数后能否设置字符编码?
这个问题我太熟了!核心原因是你在设置字符编码之前就已经获取了请求参数——Servlet容器有个关键规则:一旦调用了getParameter()、getParameterMap()这类参数获取方法,容器就会立即用默认编码(通常是ISO-8859-1)解析请求参数,之后再调用setCharacterEncoding()根本不会生效。
看你的代码片段,doFilter里先调用了getParams(request),这个方法里肯定是执行了参数获取操作对吧?这直接导致后续的编码设置完全无效。
修复方案:调整执行顺序+正确处理请求包装
1. 把编码设置放在最前面
必须在所有参数读取操作之前设置字符编码,这是最核心的修复点:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; // 第一步:先设置编码,一定要在获取参数之前! httpRequest.setCharacterEncoding("UTF-8"); // 第二步:再执行你的参数检查/特殊字符移除逻辑 getParams(httpRequest); // 第三步:传递经过处理的请求(如果用Wrapper,基于已设置编码的request初始化) chain.doFilter(new RequestWrapper(httpRequest), response); }
2. 确保RequestWrapper正确处理编码(如果需要自定义参数逻辑)
如果你的RequestWrapper是用来修改参数值(比如移除特殊字符),要基于已经设置好编码的原始请求来读取参数,避免二次解析时编码混乱:
public class RequestWrapper extends HttpServletRequestWrapper { private Map<String, String[]> sanitizedParams; public RequestWrapper(HttpServletRequest request) { super(request); // 基于已设置UTF-8编码的request读取原始参数 sanitizedParams = new HashMap<>(request.getParameterMap()); // 在这里执行特殊字符移除逻辑 removeSpecialCharacters(sanitizedParams); } private void removeSpecialCharacters(Map<String, String[]> params) { for (Map.Entry<String, String[]> entry : params.entrySet()) { String[] values = entry.getValue(); for (int i = 0; i < values.length; i++) { // 示例:移除HTML危险字符,你可以替换成自己的规则 values[i] = values[i].replaceAll("[<>&\"']", ""); } } } // 重写参数获取方法,返回处理后的参数 @Override public String getParameter(String name) { String[] values = sanitizedParams.get(name); return values != null && values.length > 0 ? values[0] : null; } @Override public Map<String, String[]> getParameterMap() { return Collections.unmodifiableMap(sanitizedParams); } @Override public String[] getParameterValues(String name) { return sanitizedParams.get(name); } }
额外注意点
- 如果是GET请求,仅设置
setCharacterEncoding()可能不够,因为GET参数是通过URL传递的,Tomcat等容器默认用ISO-8859-1解析URL编码。需要在容器配置(比如Tomcat的server.xml)里的Connector标签添加URIEncoding="UTF-8":<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8"/> - 永远不要在读取参数后再尝试设置编码,这个顺序错误是编码问题的高频坑点。
内容的提问来源于stack exchange,提问作者Bala
相关产品推荐
相关产品推荐

