Loading... 问题描述: 老项目jsp中提交中文字段会出现中文乱码问题。 F12可以发现Request Headers的 `Content-Type`: `application/x-www-form-urlencoded`缺少了编码设置 `charset=UTF-8` 实际debug可知是用了 `ISO-8859-1` 尝试以下方式,未果: (1)jsp定义页面编码格式 `<meta http- equiv="Content- Type" content=" text/html; charset-utf-8"/>` (2)yml上配置HTTP编码 `spring.http.encoding.charset=UTF-8` (3)yml上配置tomcat编码 `server.tomcat.uri-encoding=UTF-8` (4)httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); (5)consumes + @RequestParam ```java @RequestMapping(value = "add",method = RequestMethod.POST ,consumes = "application/x-www-form-urlencoded;charset=UTF-8") @ResponseBody public JsonResult add(@RequestParam BanAccountConfEntity banAccountConf){ banAccountConfService.add(banAccountConf); return JsonResult.success(); } ``` (6)springmvc的ServletModelAttributeMethodProcessor解析 (7)CharacterEncodingFilter 拦截器 ```java public class CharacterEncodingFilter extends OncePerRequestFilter { private String encoding; private boolean forceEncoding = false; public CharacterEncodingFilter() { } public void setEncoding(String encoding) { this.encoding = encoding; } public void setForceEncoding(boolean forceEncoding) { this.forceEncoding = forceEncoding; } protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if(this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) { request.setCharacterEncoding(this.encoding); if(this.forceEncoding) { response.setCharacterEncoding(this.encoding); } } filterChain.doFilter(request, response); } } ``` (8)LoginFilter 拦截器 ```java public class LoginFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) servletRequest; HttpServletResponse resp = (HttpServletResponse) servletResponse; servletRequest.setCharacterEncoding("utf-8"); filterChain.doFilter(servletRequest, servletResponse); return; } ``` --- 问题主要定位到Filter是有生效的,但是再执行过程中应该是在tomcat下被覆盖回去或者说是再拦截器生效前就已经被改为 `ISO-8859-1` 唯有这种方法生效: String userName = new String(userName.getBytes("ISO-8859-1"), "UTF-8"); 目前的解决思路就是写一个拦截器拦截到所有请求,将该格式转为字节码再转到UTF-8,但是这样每次都要走这个拦截器了,而且很不优雅。目前能肯定的是到org.apache.tomcat.util.buf下还是UTF-8 最后的解决方法还是根据该出错的请求头Request Headers去实现一个底层的字节转换。 (1)构造一个包装给定请求的请求对象FormDataRequest ```java public class FormdataRequest extends HttpServletRequestWrapper { public Map<String, String[]> parameterMaps = new HashMap<>(); /** * Constructs a request object wrapping the given request. * * @param request The request to wrap * @throws IllegalArgumentException if the request is null */ public FormdataRequest(HttpServletRequest request) { super(request); request.getParameterMap().forEach((k, v) -> { List<String> lst = Lists.newArrayList(v); List<String> lstAdd = Lists.newArrayList(); lst.stream().forEach(e -> { try { lstAdd.add(new String(((String) e).getBytes("ISO-8859-1"), "utf-8")); } catch (UnsupportedEncodingException unsupportedEncodingException) { unsupportedEncodingException.printStackTrace(); } }); if (v.length > 0) { parameterMaps.put(k, lstAdd.toArray(new String[lstAdd.size()])); } else { } }); } @Override public String[] getParameterValues(String name) { return parameterMaps.get(name); } @Override public Map<String, String[]> getParameterMap() { return parameterMaps; } @Override public String getParameter(String name) { String[] obj = parameterMaps.get(name); return obj != null ? obj[0] : ""; } public Map<String, String[]> getParameterMaps() { return parameterMaps; } public void setParameterMaps(Map<String, String[]> parameterMaps) { this.parameterMaps = parameterMaps; } } ``` (2)通过拦截器FormDataFilter拦截请求 ```java public class FormDataFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // ajax request pass if (!Strings.isNullOrEmpty(request.getHeader("X-Requested-With"))) { filterChain.doFilter(request, response); } else if (!Strings.isNullOrEmpty(request.getContentType()) && request.getContentType().contains("urlencoded")) { // form data post utf-8 filterChain.doFilter(new FormdataRequest(request), response); } else { // others pass filterChain.doFilter(request, response); } } } ``` (3)注入ShrioConfiguration中注入 ```java /** * 针对application/x-www-form-urlencoded * @return */ @Bean("formdataFilter") public FormDataFilter formdataFilter() { FormDataFilter formdataFilter = new FormDataFilter(); return formdataFilter; } ``` Last modification:August 21, 2022 © Allow specification reprint Like 0 喵ฅฅ