前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于Servlet,JSP,HTML中文乱码的问题(转载自https://blog.csdn.net/qq_27368993/article/details/83616090)

关于Servlet,JSP,HTML中文乱码的问题(转载自https://blog.csdn.net/qq_27368993/article/details/83616090)

作者头像
_DIY
发布2020-05-27 10:29:43
9400
发布2020-05-27 10:29:43
举报

首先说明一点,以下的测试方法只有一个HttpServletRequest.forward,但是基于原理上的讲解,其他乱码问题应该也可以从中得到一些启示。不敢保证百分百正确,但能提供一个大致的方向。

下面为测试入口servlet的代码,其中的getWriter被注释掉,后面讲其作用。

代码语言:javascript
复制
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

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

        //PrintWriter out=resp.getWriter();

        resp.setHeader("Expires","0");
        resp.setHeader("Cache-Control","no-cache,no-store");
        resp.setHeader("Pragma","no-cache");

        req.getRequestDispatcher("/WEB-INF/jsp/in2.jsp").forward(req,resp);
    }

测试流程就是很简单的从一个servlet转到另一个jsp或者html上。

一.从servlet转到jsp页面

<1>直接转到一个jsp

首先我们应该知道,jsp页面实际上会转换成一个servlet,至于存在那个地方,可以自行百度,不同的系统以及集成开发环境会使之存在不同的地方。下面为测试的第一个jsp文件in2.jsp,很简单,直接输出一段话。

代码语言:javascript
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    out.print("我是in2.jsp文件的内容");
    //out.print("参数为:"+request.getParameter("param"));
%>
</body>
</html>

其中的page里面设置的几个UTF-8编码有必要讲下它的作用范围:

  • charset="UTF-8":它是设置的response的输出编码,其实设置的就是Content-type头字段里面的编码,是告诉浏览器以什么方式解码的。
  • pageEncoding="UTF-8":这个是指用什么编码格式打开这个文件,而不是以什么格式保存这个文件,虽然想要得到正确的内容,打开文件的格式和文件编码的格式必须一致,但这个逻辑关系必须理清楚。
  • 其实还有另外一个属性可以设置,那就是<head>标签下的<meta>标签可以设置文档的编码格式,它作用的是html文档的内容,告诉浏览器以什么编码格式来解析文档。对于jsp而言,它会被content-type的charset给覆盖掉。如果没有设置content-type,指的是<%@ page%>里设置的,生成的servlet会默认使用"text/html;charset=ISO-8859-1",<meta>标签里设置的无效,在jsp里设置和不设置影响不到浏览器以什么格式解码。但在HTML里就不一样,因为HTML不生成servlet,所以可以指定浏览器以什么格式解码。但有一点及其重要,即便HTML以UTF-8格式保存,标签告诉浏览器以UTF-8格式解码,但也可能产生乱码,那是因为,服务器在写入HTML时,是以默认的格式写入的,它没有pageEncoding指定打开写入的格式,而默认格式为ANSI,不一定为UTF-8,所以就产生了乱码!!!

下面的jsp转换成一个servlet的流程必须清楚:

  • 将指定的jsp文件以pageEncoding指定的编码格式打开,转换成一个.java文件
  • 类装载器以utf-8的格式读取.java文件,转换成一个.class文件,在将这个.class文件以Unicode编码格式载入虚拟机,现在就相当于一个servlet

上述in2.jsp文件是UTF-8格式保存的,接下来打开它转换成的servlet,片段代码如下,可以看到没有乱码

代码语言:javascript
复制
    out.write("\r\n");
      out.write("\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("    <title>Title</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");

    out.print("我是in2.jsp文件的内容");
    //out.print("参数为:"+request.getParameter("param"));

      out.write("\r\n");
      out.write("</body>\r\n");
      out.write("</html>\r\n");

浏览器端的输出也是正常的

现在我们改动pageEncoding=ISO-8859-1

再次查看jsp转换成的servlet

代码语言:javascript
复制
    out.write("\r\n");
      out.write("\r\n");
      out.write("<html>\r\n");
      out.write("<head>\r\n");
      out.write("    <title>Title</title>\r\n");
      out.write("</head>\r\n");
      out.write("<body>\r\n");

    out.print("ææ¯in2.jspæ件çå容");
    //out.print("åæ°ä¸º:"+request.getParameter("param"));

      out.write("\r\n");
      out.write("</body>\r\n");
      out.write("</html>\r\n");

可以看到已经乱码了,这就是以ISO-8859-1编码打开UTF-8编码文件时产生的乱码,网页输出端也是如此

因此,可以总结出,如果要保证不乱码,必须以文件编码的格式打开文件,而且还得指定浏览器以同样的编码格式解码。这儿并未测试response设置编码格式,但得注意这点!

<2>现在改变一下测试方式,从一个servlet转到test.jsp,然后test.jsp转到in2.jsp

test.jsp

代码语言:javascript
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>测试jsp</title>
</head>
<body>
<jsp:forward page="in2.jsp">
    <jsp:param name="param" value="data数据"/>
</jsp:forward>
</body>
</html>

in2.jsp

代码语言:javascript
复制
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="ISO-8859-1"%>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    out.print("我是in2.jsp文件的内容");
    out.print("参数为:"+request.getParameter("param"));
%>
</body>
</html>

入口servlet

代码语言:javascript
复制
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//        resp.setContentType("text/html;charset=utf-8");
//        PrintWriter out=resp.getWriter();

        resp.setHeader("Expires","0");
        resp.setHeader("Cache-Control","no-cache,no-store");
        resp.setHeader("Pragma","no-cache");

        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
    }

网页端得输出为以下情况:

in2.jsp文件的内容没问题,test.jsp中设置的参数汉字乱码,这个也可以从test_jsp.java里面看到原因,是因为这个"data数据"是更据request的编码格式来写入的,默认为ISO-8859-1,将其改变为utf-8则正常显示。在设置参数之前改变编码,不要在乱码之后改变编码,那时没用了,可以在jsp里面改变,也可以在入口servlet改变,如req.setCharacterEncoding("utf-8");。

二.从一个servlet转到一个静态HTML

静态HTML文件如下in1.html

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="content-type" content="text/html" charset="UTF-8">
    <title>Title</title>
</head>
<body>
这是in1.html里面的内容
</body>
</html>

入口servlet的代码如下:

代码语言:javascript
复制
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out=resp.getWriter();

        resp.setHeader("Expires","0");
        resp.setHeader("Cache-Control","no-cache,no-store");
        resp.setHeader("Pragma","no-cache");
        req.setCharacterEncoding("utf-8");
        req.getRequestDispatcher("/WEB-INF/jsp/in1.html").forward(req,resp);
    }

结果为如下,乱码了,归根揭底其实也是pageEncoding的原因

因为HTML文件无法设置pageEncoding,也不会生成servlet,所以我也不能确定是不是pageEncoding的原因,因此作出假设,转发到HTML后,HTML的打开方式为以下2种情况。

  1. 是以UTF-8的格式打开
  2. 不是以UTF-8的格式打开,这个格式我等下说明

以notepad++打开这个in1.html,并且将编码格式设置为ANSI,则结果如下,刚好和浏览器输出一致

因此我猜测是以ANSI的格式打开HTML,这个格式会因操作系统和地区而已,中国WINDOWS为GBK格式

下面我另存为一个in2.html格式保存为ANSI

并将servlet的转发到in2.html,输出正常

因此,我认为一个HTML文件在集成开发创建时是UTF-8的格式,这个格式在IDE上应该可以设置,但在打开时是更具默认编码格式打开的(即ANSI),因此会产生乱码,当然,这只是找到了原因。而解决的办法就是将这个HTML以我们想要的格式打开,即UTF-8,但又不能设置pageEncoding,因此我们可以将HTML当作JSP处理,静态HTML是可以转成JSP的。

这种途径可以配置XML文件,添加如下XML语句

代码语言:javascript
复制
    <jsp-config>
        <jsp-property-group>
            <url-pattern>*.html</url-pattern>
            <page-encoding>UTF-8</page-encoding>
        </jsp-property-group>
    </jsp-config>

意思是,任何以html结尾的URL请求的资源,都已UTF-8格式打开,因此在次转到in1.html则正常了。如果配置了XML就不能在访问in2.html,会乱码,因为in2.html的编码格式为ANSI,以UTF-8的格式打开会乱码。

关于最开始说的PrintWriter out=resp.getWriter的作用关于另一个知识点,对于一切没有在XML中配置的servlet,都是采用缺省servlet访问,关于缺省servlet,可以百度查看更多。如上面测试时,如果在转发之前没有使用getWriter,则缺省servlet使用的是字节流输出,如果使用了getwriter则使用字符流输出,字节流同理。关于content-type头字段的charset编码格式和字节流字符流之间又会产生多种情况,如使用字符流,但不指定charset,则默认的格式为ISO-8859-1,用来输出中文则会乱码;使用字节流时,不论是否设置为utf-8,都不会产生乱码,按理字节流使用utf-8输出中文会乱码,我没有去看这个缺省servlet的源码,只能猜测使用字节流时都采用ISO-8859-1来输出。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-05-18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一.从servlet转到jsp页面
    • <1>直接转到一个jsp
      • <2>现在改变一下测试方式,从一个servlet转到test.jsp,然后test.jsp转到in2.jsp
      • 二.从一个servlet转到一个静态HTML
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档