• 解决乱码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()之前设置,不然就会有乱码的问题

  • 相关阅读:
    button 垂直分布
    GitHub上值得关注的iOS开源项目
    电脑连接网络(网络正常),但不能上网,登录网页提示dns_probe_finished_no_internet
    android 模拟应用因内存不足被后台杀死命令
    android 屏幕划分
    android 没有root的手机导出数据库
    移动硬盘不能识别,设备管理器中显示黄色感叹号
    低功耗蓝牙开发(BLE)
    音视频学习笔记
    Java中为什么要使用线程池?如何使用?
  • 原文地址:https://www.cnblogs.com/inkyi/p/15194653.html
Copyright © 2020-2023  润新知