IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Tomcat 访问静态资源html、txt等出现中文乱码及获取Request域中数据乱码解决方案 -> 正文阅读

[Java知识库]Tomcat 访问静态资源html、txt等出现中文乱码及获取Request域中数据乱码解决方案

注意: 非本人阅读请跳转到问题分析与解决一栏
分类分析:

  • 非Spring MVC项目
  • Spirng MVC项目

本文章所使用 Tomcat 版本分别为7.0.1008.5.54

注意: 本文的 html 文件均带了<meta charset="utf-8">标签如果没带此标签,解析html和解析txt效果一样!!

非Spring MVC项目

在非spring mvc项目中出现访问静态资源乱码,如 txt 文本等,一般都是文件编码为非BOM的UTF-8,将文件编码改为UTF-8 BOM格式即可。具体信息查看下面表格:

Tomcat文件类型文件编码是否正常访问
7.0.100htmlUTF-8
7.0.100htmlUTF-8 BOM
7.0.100txtUTF-8
7.0.100txtUTF-8 BOM
Tomcat文件类型文件编码是否正常访问
8.5.54htmlUTF-8
8.5.54htmlUTF-8 BOM
8.5.54txtUTF-8
8.5.54txtUTF-8 BOM

Spirng MVC项目

如果配置了CharacterEncodingFilter且初始化了参数forceResponseEncodingforceEncodingtrue,此时每次请求静态资源时,CharacterEncodingFilter都会在响应头加上charset=UTF-8。参数为false,或未设置时,情况和上面非Spring MVC情况一致。

<filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <!--初始化forceResponseEncoding为true-->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

当设置了forceResponseEncodingforceEncodingtrue时,具体显示信息如下:

Tomcat文件类型文件编码是否正常访问
7.0.100htmlUTF-8
7.0.100htmlUTF-8 BOM
7.0.100txtUTF-8
7.0.100txtUTF-8 BOM
Tomcat文件类型文件编码是否正常访问
8.5.54htmlUTF-8
8.5.54htmlUTF-8 BOM
8.5.54txtUTF-8
8.5.54txtUTF-8 BOM

问题分析与解决

解决乱码只需加入fileEncoding参数,如下所示。(前提: 你的静态资源文件编码必须是UTF-8)

<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <!--fileEncoding  
        Encoding to be used to read static resources 
        [platform default]-->
        <!--增加下面初始化参数-->
        <init-param>
        	<param-name>fileEncoding</param-name>
        	<param-value>UTF-8</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

影响DefaultServlet解析静态资源编码主要有两个重要的参数fileEncodinguseBomIfPresent

	/**
     * File encoding to be used when reading static files. If none is specified
     * the platform default is used.
     */
     //读取静态文件时要使用的文件编码,如果未指定,则使用平台默认值。
    protected String fileEncoding = null;
    private transient Charset fileEncodingCharset = null;

    /**
     * If a file has a BOM, should that be used in preference to fileEncoding?
     * Will default to {@code BomConfig.TRUE} in {@link #init()}.
     */
     //如果文件有BOM,是否应该优先使用BOM而不是fileEncoding?将在init()中默认设置为BomConfig.TRUE。
    private BomConfig useBomIfPresent = null;

init()源码:

		//获取初始化参数fileEncoding,若没有则返回null
        fileEncoding = getServletConfig().getInitParameter("fileEncoding");
        if (fileEncoding == null) {
        	//尝试输出fileEncoding得到结果为GBK----用命令行运行测试Charset.defaultCharset()
        	//IDEA或者Eclipse运行出来的结果可能是UTF-8
            fileEncodingCharset = Charset.defaultCharset();
            fileEncoding = fileEncodingCharset.name();
        } else {
            ……
        }
		//获取初始化参数useBomIfPresent,若没有则返回null
        String useBomIfPresent = getServletConfig().getInitParameter("useBomIfPresent");
        if (useBomIfPresent == null) {
            // Use default
            //使用默认值BomConfig.TRUE
            this.useBomIfPresent = BomConfig.TRUE;
        } else {
            ……
            }
           

枚举类BomConfig源码:

static enum BomConfig {
        /**
         * BoM is stripped if present and any BoM found used to determine the
         * encoding used to read the resource.
         */
         //如果存在BOM,则会将其剥离,并使用找到的BOM来确定用于读取资源的编码。
        TRUE("true", true, true),
        /**
         * BoM is stripped if present but the configured file encoding is used
         * to read the resource.
         */
         //BOM(如果存在)将被剥离,但配置的文件编码(fileEncoding)用于读取资源。
        FALSE("false", true, false),
……

综上,如果未指定fileEncoding初始化参数,Tomcat将使用平台默认编码解析静态资源,而Windows默认编码为GBK,所以解码UTF-8的文件出现乱码。为什么带BOM的文件Tomcat能正常解析,那是因为参数useBomIfPresent的默认值为BomConfig.TRUE,此情况下Tomcat解析到带有BOM的文件时BOM推断出的编码优先级高于fileEncoding属性,比如前三个字节为EF BB BF,Tomcat便知道这个静态资源是UTF-8编码,于是使用UTF-8解码(即使fileEncoding = GBK)。至于为什么html能普遍解析成功,个人猜测是因为<meta charset="utf-8">标签告诉Tomcat此文件是UTF-8编码,所以Tomcat能解析成功。

关于获取Request域中数据乱码问题

public void init() {
        messageGET = "GET-----你好";
        messagePOST = "POST-----你好";
    }
 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //request
        //默认request.getCharacterEncoding()返回null
        if (null == request.getCharacterEncoding()) {
            System.out.println("charset == null");
        }
        //tomcat7 ---解码url用ISO-8859-1  ----解决方法->使用tomcat8+或者修改server.xml
        //<Connector connectionTimeout="20000"  (URIEncoding="UTF-8") port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
        //tomcat8 ---解码url用UTF-8
        //GET请求无法提供以下方法修改获取url参数的编码方式
//        request.setCharacterEncoding("UTF-8");
        String s = request.getParameter("s");
        System.out.println("GET-----s: " + new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
        //response
        //tomcat响应默认用ISO-8859-1
        //response.getCharacterEncoding()默认返回ISO-8859-1
        System.out.println("response: " + response.getCharacterEncoding());
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html");
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + messageGET + "</h1>");
        out.println("</body></html>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //request
        //默认request.getCharacterEncoding()返回null
        if (null == req.getCharacterEncoding()) {
            System.out.println("charset == null");
        }
        //POST请求通过以下方法修改读取请求体数据的编码
        req.setCharacterEncoding("UTF-8");
        if (null != req.getCharacterEncoding()) {
            System.out.println("charset == " + req.getCharacterEncoding());
        }
        //POST读取参数默认用ISO-8859-1
        String s = req.getParameter("s");
        System.out.println("POST------s: " + s);
        //response
        //响应默认用ISO-8859-1
        //response.getCharacterEncoding()默认返回ISO-8859-1
        System.out.println("response: " + resp.getCharacterEncoding());
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + messagePOST + "</h1>");
        out.println("</body></html>");
    }

本文章仅个人学习记载,包含主观想法,并不确保正确性。如若有误,恳请指正!

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-07-30 12:36:58  更:2021-07-30 12:37:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/28 22:55:01-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码