69.3. 编码问题

69.3.1. 基础知识

  • HTTP请求中,可能会出现中文的地方

    a)Path:如www.apusic.com/中国.jsp

    b)Query:如www.apusic.com/index.jsp?key1=汉字,"key1=汉字"就是Query字符串

    c)Data:如表单中<input name="test2" type="text" value="中文"/>

    [注意]注意

    同一次请求,不同地方的编码格式很有可能是不一样的。

  • HTTP请求中的编码转换

  • 一般情况下的编码

    Path:根据RFC 2732:Format for Literal IPv6 Addresses in URLs,URI(不仅Path,还包括Query)未指定特定的字符集,但实际应用中,Path部分浏览器通常是使用UTF-8编码,然后转成 application/x-www-form-urlencoded格式。并且JAVA的URI类的实现也是使用了UTF-8。

    Query:一般有两种情况:

    一是用户直接在浏览器输入URL或使用超链接方式,那么浏览器会根据它设置的语言编码,如中国一般使用的是GBK。

    另一种是用户在页面提交表单的方式,浏览器先会根据请求页面时得到的Context-Type的响应消息头中charset值(比如"text/html;charset=GBK")去编码。如果没有,则采用设置的语言编码。

    [注意]注意

    强调一下,是指http响应消息头的Context-Type,而不是在网页中meta中的Context-Type。后者通常情况是不起任何作用的。

    Data:一般采用于Query相同的编码

  • 非一般情况下的编码

    这种特殊情况的出现一般在以下场景:

    a)用户自己为汉字编码。那么可能出现Path使用GBK编码,Query与Data编码不一致等各种情况。

    b)用户自己编写客户端,并且不遵循规范或惯例

    c)浏览器不遵循规范或惯例

69.3.2. 常见编码问题解析

  • JSP/servlet中解析form提交的汉字得到的是乱码

    原因:

    这种情况出现的可能性很多,如用户自己加了编码过滤器等,但根本原因是服务器解析Query和Data的参数时,没有指定对编码。

    解决方法:

    a)使用request.getParameter()前,先用request.setCharacterEncoding()指定编码,Apusic会根据设定的编码格式去编码Query 和Data,(Tomcat默认只是将这个值作为Query的编码)。最佳实践为写一个SerlvetFilter用这个方法统一设置编码格式。

    b)new String("中文".getBytes("ISO-8859-1"),YOUR_ENCODING);

    Tips:这里使用ISO-8859-1,并不是因为HTTP协议采用ISO-8859-1,而是因为ISO-8859-1是单字节编码,用它去getBtyes(),可以将不进行编码地将字节取出。

    c)Apusic特有设置:见Apusic的解决方案一节

  • 浏览器中看到的 Jsp/Servlet 页面出现乱码

    原因:

    可能有几种情况:

    a)request.getParameter()获得的值本身就没正确编码。

    b)使用了不合适的编码,如用ISO-8859-1去编码汉字。

    c)响应头中没有Context-Type或Context-Type没有指定编码,浏览器不知道用何种编码显示页面。

    解决方法:

    a)response.setContentType("text/html;GBK"); response.setCharacterEncoding ("UTF-8"); response.setLocale(Locale.CHINESE);这三个方法可以设置Context-Type中的编码。

    b)Apusic特有设置:见Apusic的解决方案一节

  • 中文路径无法访问

    原因:

    应用服务器没有判断对Path的编码。如果Path采用UTF-8一般不会出现这种情况,而如果是其他编码格式,比如用户自己编码了,那么就可能出现找不到路径的情况。

    解决方法:

    a)采用英文路径。

    b)Apusic特有设置:见Apusic的解决方案一节

  • JSP源代码中的中文,编译后显示成乱码

    原因:

    JSP源文件采用的GBK编码,而编码时却指定UTF-8编码去编译。

    解决方法:

    a)指定编译使用的编码。指定的方式有两种,一种是在JSP页面的首行,加上<%@ page contentType="text/html;charset=GBK" pageEncoding="GBK"%>,其中pageEncoding指定的就是编码时采用的编码。另一种是在web.xml设置,类似于

    <jsp-config>
        <jsp-property-group>
            <url-pattern>/*</url-pattern>
            <page-encoding>GBK</page-encoding>
        </jsp-property-group>
    </jsp-config> 

69.3.3. Apusic的解决方案

  • Path和Query出现乱码

    可以设置apusic.conf 下的webservice服务,增加属性URIEncoding,取值根据实际情况选择。如下选择了GBK的配置:

    <ATTRIBUTE NAME="URIEncoding" VALUE="GBK"/>
  • 响应的设置

    如果表单中通过Post方式提交的中文数据存在乱码,则可以在应用的web.xml里设置参数request.charsetencoding,取值根据实际情况选择。例子如下:

    <context-param>
    <param-name>request.charsetencoding</param-name>
    <param-value>GBK</param-value>
    </context-param> 

    如果表单数据通过get方式提交,则其内容的编码和Path及Query内容编码处理一致。