购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 字符编码

Java Web开发中最容易出现的问题是中文字符乱码问题,只有弄清楚产生中文字符乱码问题的原因,才能“对症下药”,彻底解决中文字符乱码问题。

2.2.1 JSP文件的字符编码与pageEncoding

前面提到,相同的JSP文件,文件的字符编码不同,结果可能不同。可见,使用正确的JSP文件字符编码很重要。

使用Eclipse创建JSP文件后,JSP文件中的字符会以某种字符编码存在。在Eclipse中查看JSP文件的字符编码,方法如下(以abc.jsp为例)。

打开Project Explorer视图→展开get项目→展开WebContent目录→右击abc.jsp→选择Properties,就可以看到JSP文件的字符编码为UTF-8,如图2-22所示。

图2-22 查看JSP文件的字符编码

JSP文件的字符编码的主要作用是告诉操作系统的文件系统,文件中的字符采用何种字节序列存储在硬盘上。而JSP文件的字符编码与pageEncoding之间存在怎样的关系呢?

事实上,JSP文件的字符编码与pageEncoding之间并不存在直接关联关系。只不过Eclipse过于“智能”,Eclipse中的JSP文件的字符编码继承了pageEncoding值。例如,在Eclipse中修改了JSP文件的pageEncoding值后,保存JSP文件时,Eclipse会随之更改JSP文件的字符编码。因为ISO-8859-1并不支持中文字符,所以在使用Eclipse编写JSP程序后,如果将pageEncoding设置为ISO-8859-1,且JSP文件中包含中文字符时,则无法保存JSP文件。这就是2.1.9节中无法保存JSP文件的原因。

记事本并没有那么智能,如果使用记事本开发JSP程序,修改了JSP文件中的pageEncoding后,保存JSP文件时,记事本开发的程序不会随之更改JSP文件的字符编码。如图2-23所示,也就是说,使用Eclipse开发JSP程序时,JSP程序中的pageEncoding自动和JSP文件的字符编码保持一致;使用记事本开发JSP程序时,JSP程序中的pageEncoding可以与JSP文件的字符编码不相同。

图2-23 使用Eclipse和记事本开发JSP程序的区别

运行JSP程序时,JSP程序首先要被翻译成Servlet源程序(.java程序)。pageEncoding的主要作用就是:告知Tomcat中的JSP引擎,按照pageEncoding指定的字符编码读取JSP文件,并翻译成Servlet源程序(.java程序)。

如果JSP程序中pageEncoding指定的字符编码与JSP文件的字符编码不兼容,将会导致JSP程序无法被翻译成Servlet源程序(.java程序)。因此,JSP程序的pageEncoding值必须和JSP文件的字符编码兼容(建议相同)。

2.2.2 MIME和字符编码

MIME(Multipurpose Internet Mail Extensions)是描述消息内容类型的因特网标准,描述了互联网上数据(包括文件)的内容格式。MIME的语法格式是“type/subtype”,斜杠前面的是类型(type),斜杠后面的是子类型(subtype),中间不能有空格符。MIME不仅可以描述HTTP请求数据的内容格式,还可以描述HTTP响应数据的内容格式,如图2-24所示。

图2-24 HTTP请求数据和HTTP响应数据的MIME

1.HTTP请求数据的内容格式

浏览器向Web服务器发送的超文本数据称为HTTP请求数据。HTTP请求数据的内容格式有两种,即application/x-www-form-urlencoded和multipart/form-data,更多知识参考第3章内容。

2.HTTP响应数据的内容格式

MIME更为重要的用途在于描述HTTP响应数据,HTTP响应数据是指Web服务器返回给浏览器的数据。假设Web服务器向浏览器返回的HTTP响应数据是音频数据(不是文本型数据),由于浏览器默认采用text/html格式(HTML格式的文本型数据)解析HTTP响应数据,此时音频数据将以乱码形式显示在浏览器页面上。

如果Web服务器向浏览器返回HTTP响应数据时,指定了HTTP响应数据的内容格式是“audio/mpeg”,浏览器接收到HTTP响应数据后,将调用本地的音频播放软件解析其内容,浏览器用户就可以听到来自网页的声音了。

audio/mpeg表示支持.mp3类型的数据。

因此,HTTP响应数据的内容格式的作用是:控制浏览器使用正确的格式解析HTTP响应数据,防止浏览器“曲解”HTTP响应数据的内容。

HTTP响应数据的内容格式种类繁多,限于篇幅,本书只介绍其中三大类,如图2-25所示。更多的MIME,读者可以参考Tomcat安装目录下conf目录下的web.xml配置文件。

图2-25 HTTP响应数据的内容格式

(1)文本数据,类型是text,其子类型可以是.html、.plain、.csv、.css等。

(2)图片数据,类型是image,其子类型可以是.png、.jpeg、.bmp、.gif等。

(3)应用程序数据,类型是application,其子类型可以是msword、vnd.ms-excel、vnd.ms powerpoint、octet-stream、x-rar-compressed等。

说明1:通过向HTTP响应头列表中添加“Content-Type”响应头,就可以设置HTTP响应数据的内容格式。

说明2:JSP程序page指令<%@ page contentType="text/html; charset=UTF-8" %>中的contentType的主要功能是,向HTTP响应头列表中添加“Content-Type”响应头。

3.HTTP文本型响应数据的字符编码

JSP程序page指令中的contentType设置了HTTP响应数据的内容格式。当HTTP响应数据的内容格式是text类型时,对于浏览器而言,字符编码的设置就显得格外重要,否则中文字符可能以乱码方式显示在浏览器页面上。

假设某JSP程序page指令中的contentType设置为"text/html; charset=ISO-8859-1",contentType有如下两个作用。

(1)text/html:设置了HTTP响应数据是文本型数据,并且子类型是.html,表示文本型数据采用HTML格式。此时,浏览器接收到<br/>后,<br/>将被解析为换行符,而不会被解析成普通文本。

(2)charset=ISO-8859-1:有两个作用,一是将HTTP响应数据按照ISO-8859-1字符集进行编码;二是告知浏览器,按照ISO-8859-1字符集解码HTTP响应数据。

由于ISO-8859-1是单字节字符集,不支持中文字符,这就是2.1.9节中将contentType中的charset设置为ISO-8859-1后,浏览器页面出现中文字符乱码问题的原因。

某些应用程序格式(例如JSON)的数据也需要设置内容格式的字符编码。以JSON为例,可以这样指定:response.setContentType("application/json;charset=UTF-8")。

2.2.3 JSP文件、pageEncoding和charset的字符编码之间的关系

JSP文件、pageEncoding和charset的字符编码之间的关系如图2-26所示。

图2-26 以时间为维度的字符编码的运作流程

以时间为维度(从下到上),字符编码的运作流程大致如下。

(1)编写JSP程序时,第一件事情就是要确定JSP文件的字符编码。如果采用记事本编写JSP程序,默认的字符编码是ANSI(不是标准字符集);如果采用Eclipse编写JSP程序,默认的字符编码是UTF-8。

(2)运行JSP程序时,Tomcat的JSP引擎按照pageEncoding指定的字符集读取JSP文件,将其翻译成Servlet源程序(.java程序)。

pageEncoding的值与JSP文件的字符编码必须兼容(建议相同),否则Tomcat的JSP引擎无法将JSP程序翻译成Servlet源程序(.java程序),无法进行接下来的步骤(3)和步骤(4)。

(3)Tomcat将Servlet源程序(.java程序)翻译成Servlet字节码文件(.class文件)。

(4)加载Servlet字节码文件(.class文件)到Web服务器内存。contentType中的charset有两个作用,前面已经讲过,这里不再重复。

说明1:步骤(4)中的charset指定的字符集只要支持中文字符即可,无须与JSP文件的字符编码、pageEncoding编码相同。

说明2:如果JSP程序中没有在contentType设置charset,JSP引擎自动将charset值设置为pageEncoding的值;如果JSP程序中没有指定pageEncoding,JSP引擎自动将pageEncoding设置为JSP文件的字符编码;如果JSP文件的字符编码未知(例如ANSI),则JSP引擎自动使用Tomcat默认的ISO-8859-1解析JSP程序。 opCJFziEa4F3IYlXWJmqk8x9i/SPuzLFLPVl2g4t5cipkWXAYEKLVPZygHtWAplT

点击中间区域
呼出菜单
上一章
目录
下一章
×