解决乱码setCharacterEncoding("UTF-8")不生效的问题

今天在写拦截器的时候,如果判断用户未登录,直接返回一个错误码,提醒用户登录。

但是在前端接收的提示信息中,结果是

{code: "58888", msg: "???"}

这里的???应该是请登录

检查一下工具类,发现工具类里面是设置过编码

 public static void writeJson(HttpServletResponse response , Object content ) throws IOException {
     try(PrintWriter out = response.getWriter()){
         response.setContentType(MediaType.APPLICATION_JSON_VALUE);
         response.setCharacterEncoding("UTF-8");
         String returnText = JSONObject.toJSONString(content, SerializerFeature.DisableCircularReferenceDetect);
         out.write(returnText);
         out.flush();
     }
}

然后又检查了一下,页面上的response headers的信息

编码集变成了 ISO-8859-1

说明代码里,设置编码集的代码没有生效。

点进源码看看到底为啥没生效。

public void setCharacterEncoding(final String charset) {
    // writer != null , 就不会再设置编码集了
    if (insideInclude || responseStarted() || writer != null || isCommitted()) {
        return;
    }
    charsetSet = charset != null;
    this.charset = charset;
    if (contentType != null) {
        exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, getContentType());
    }
}

如果writer对象不是空,就不会再设置编码集。

所以response.setCharacterEncoding("UTF-8");代码要在response.getWriter()之前调用,不然编码不会生效。

顺便再看一下getWriter() 方法都干了啥?

public PrintWriter getWriter() throws IOException {
    if (writer == null) {
        // 如果编码没有set,设置编码
        // getCharacterEncoding() 如果web-app,container都没有设置编码集,就默认ISO_8859_1
        if (!charsetSet) {
            //servet 5.5
            setCharacterEncoding(getCharacterEncoding());
        }
        if (responseState == ResponseState.STREAM) {
            throw UndertowServletMessages.MESSAGES.getOutputStreamAlreadyCalled();
        }
        responseState = ResponseState.WRITER;
        createOutputStream();
        final ServletPrintWriter servletPrintWriter = new ServletPrintWriter(servletOutputStream, getCharacterEncoding());
        writer = ServletPrintWriterDelegate.newInstance(servletPrintWriter);
    }
    return writer;
}

public String getCharacterEncoding() {
    if (charset != null) {
        return charset;
    }
    // first check, web-app context level default response encoding
    if (servletContext.getDeployment().getDeploymentInfo().getDefaultResponseEncoding() != null) {
        return servletContext.getDeployment().getDeploymentInfo().getDefaultResponseEncoding();
    }
    // now check the container level default encoding
    if (servletContext.getDeployment().getDeploymentInfo().getDefaultEncoding() != null) {
        return servletContext.getDeployment().getDeploymentInfo().getDefaultEncoding();
    }
    // if no explicit encoding is specified, this method is supposed to return ISO-8859-1 as per the
    // expectation of this API
    return StandardCharsets.ISO_8859_1.name();
}

综上所述,编码集要在getWriter()之前设置,不然就会有乱码的问题

原文地址:https://www.cnblogs.com/inkyi/p/15194653.html