javaweb Filter过滤器设置编码,导致html乱码

提出问题

当访问 .html 文件时,经过下面字符过滤器,会出现乱码

@WebFilter(urlPatterns = {"/*"})
public class CharacterFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        HttpServletResponse response = (HttpServletResponse) resp;
        HttpServletRequest request = (HttpServletRequest) req;


        request.setCharacterEncoding("UTF-8");
        // 访问html时,也经过此过滤器,由于先执行 resp.setContentType 设置编码,后执行 chain.doFilter(),导致 html 页面乱码
        resp.setContentType("text/html; charset=UTF-8");

        chain.doFilter(req, resp);
    }
}

分析

访问html时,也经过此过滤器,由于先执行下面代码:

resp.setContentType("text/html; charset=UTF-8");

或者

resp.setCharacterEncoding(charset);

然后执行下面代码:

chain.doFilter(req, resp);

所以,将 html 页面返回给浏览器时,会携带下面请求头:

Content-Type: text/html; charset=UTF-8

由于有 charset=UTF-8 ,所以导致 html 乱码

不会乱码的请求头: Content-Type: text/html

解决(有bug)

@WebFilter(urlPatterns = {"/*"})
public class CharacterFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        HttpServletResponse response = (HttpServletResponse) resp;
        HttpServletRequest request = (HttpServletRequest) req;


        request.setCharacterEncoding("UTF-8");

        chain.doFilter(req, resp);
        /* 移到 chain.doFilter() 下面,html可以正常显示
         *
        */
        resp.setContentType("text/html; charset=UTF-8");
    }
}

缺点: 由于先执行 chain.doFilter(),也就是说,当访问 Servlet 时,也就先执行 serlvet ,后执行 resp.setContentType 设置编码,导致输出 json 乱码

完美解决

在过滤器中,判断访问 .html 文件,就不经过此过滤器,参看 javaweb Filter过滤器-设置字符集(可指定不过滤路径、文件)


原文出处:/show_1IX40jhUXbpE.html