深入剖析JSP和Servlet对中文的处理过程2

开发者在线 Builder.com.cn 更新时间:2008-05-09作者:执木 来源:IT专家网

本文关键词: 中文 Servlet JSP JAVA

JSP:从源文件到Class的过程

  Jsp的源文件是以“.jsp”结尾的文本文件。在本节中,将阐述JSP文件的解释和编译过程,并跟踪其中的中文变化。

  1、JSP/Servlet引擎提供的JSP转换工具(jspc)搜索JSP文件中用中指定的charset。如果在JSP文件中未指定,则取JVM中的默认设置file.encoding,一般情况下,这个值是ISO8859-1;

  2、jspc用相当于“javac –encoding ”的命令解释JSP文件中出现的所有字符,包括中文字符和ASCII字符,然后把这些字符转换成Unicode字符,再转化成UTF格式,存为JAVA文件。ASCII码字符转化为Unicode字符时只是简单地在前面加“00”,如“A”,转化为“u0041”(不需要理由,Unicode的码表就是这么编的)。然后,经过到UTF的转换,又变回“41”了!这也就是可以使用普通文本编辑器查看由JSP生成的JAVA文件的原因;

  3、引擎用相当于“javac –encoding UNICODE”的命令,把JAVA文件编译成CLASS文件;

  先看一下这些过程中中文字符的转换情况。有如下源代码:

  这段代码是在UltraEdit for Windows上编写的。保存后,“中文”两个字的16进制编码为“D6 D0 CE C4”(GB2312编码)。经查表,“中文”两字的Unicode编码为“u4E2Du6587”,用 UTF表示就是“E4 B8 AD E6 96 87”。打开引擎生成的由JSP文件转变而成的JAVA文件,发现其中的“中文”两个字确实被“E4 B8 AD E6 96 87”替代了,再查看由JAVA文件编译生成的CLASS文件,发现结果与JAVA文件中的完全一样。

  再看JSP中指定的CharSet为ISO-8859-1的情况。

  同样,该文件是用UltraEdit编写的,“中文”这两个字也是存为GB2312编码“D6 D0 CE C4”。先模拟一下生成的JAVA文件和CLASS文件的过程:jspc用ISO-8859-1来解释“中文”,并把它映射到Unicode。由于ISO-8859-1是8位的,且是拉丁语系,其映射规则就是在每个字节前加“00”,所以,映射后的Unicode编码应为“u00D6u00D0u00CEu00C4”,转化成UTF后应该是“C3 96 C3 90 C3 8E C3 84”。好,打开文件看一下,JAVA文件和CLASS文件中,“中文”果然都表示为“C3 96 C3 90 C3 8E C3 84”。

  如果上述代码中不指定,即把第一行写成“”,JSPC会使用file.encoding的设置来解释JSP文件。在RedHat 6.2上,其处理结果与指定为ISO-8859-1是完全相同的。

  到现在为止,已经解释了从JSP文件到CLASS文件的转变过程中中文字符的映射过程。一句话:从“JspCharSet到Unicode再到UTF”。下表总结了这个过程:

  表2 “中文”从JSP到CLASS的转化过程  

Jsp-CharSet
  JSP文件中
  JAVA文件中
  CLASS文件中
  GB2312
  D6 D0 CE C4
  (GB2312)
  从u4E2Du6587(Unicode)到
  E4 B8 AD E6 96 87 (UTF)
  E4 B8 AD E6 96 87 (UTF)
  ISO-8859-1
  D6 D0 CE C4
  (GB2312)
  从u00D6u00D0u00CEu00C4 (Unicode)到C3 96 C3 90 C3 8E C3 84 (UTF)
  C3 96 C3 90 C3 8E C3 84 (UTF)
  无(默认=file.encoding)
  同ISO-8859-1
  同ISO-8859-1
  同ISO-8859-1
  下节先讨论Servlet从JAVA文件到CLASS文件的转化过程,然后再解释从CLASS文件如何输出到客户端。之所以这样安排,是因为JSP和Servlet在输出时处理方法是一样的。

  Servlet:从源文件到Class的过程

  Servlet源文件是以“.java”结尾的文本文件。本节将讨论Servlet的编译过程并跟踪其中的中文变化。

用“javac”编译Servlet源文件。javac可以带“-encoding ”参数,意思是“用< Compile-charset >中指定的编码来解释Serlvet源文件”。

  源文件在编译时,用来解释所有字符,包括中文字符和ASCII字符。然后把字符常量转变成Unicode字符,最后,把Unicode转变成UTF。

  在Servlet中,还有一个地方设置输出流的CharSet。通常在输出结果前,调用HttpServletResponse的setContentType方法来达到与在JSP中设置一样的效果,称之为。

  注意,文中一共提到了三个变量:、和。其中,JSP文件只与有关,而和只与Servlet有关。

  看下例: 

 import javax.servlet.*;
  import javax.servlet.http.*;
  class testServlet extends HttpServlet
  {
  public void doGet(HttpServletRequest req,HttpServletResponse resp)
  throws ServletException,java.io.IOException
  {
  resp.setContentType("text/html; charset=GB2312");
  java.io.PrintWriter out=resp.getWriter();
  out.println("");
  out.println("#中文#");
  out.println("");
  }
  }
  该文件也是用UltraEdit for Windows编写的,其中的“中文”两个字保存为“D6 D0 CE C4”(GB2312编码)。

  开始编译。下表是不同时,CLASS文件中“中文”两字的十六进制码。在编译过程中,不起任何作用。只对CLASS文件的输出产生影响,实际上是和一起,达到与JSP文件中的相同的效果,因为对编译和CLASS文件的输出都会产生影响。

  表3 “中文”从Servlet源文件到Class的转变过程 

 Compile-charset
  Servlet源文件中
  Class文件中
  等效的Unicode码
  GB2312
  D6 D0 CE C4
  (GB2312)
  E4 B8 AD E6 96 87 (UTF)
  u4E2Du6587 (在Unicode中=“中文”)
  ISO-8859-1
  D6 D0 CE C4
  (GB2312)
  C3 96 C3 90 C3 8E C3 84 (UTF)
  u00D6 u00D0 u00CE u00C4 (在D6 D0 CE C4前面各加了一个00)
  无(默认)
  D6 D0 CE C4
  (GB2312)
  同ISO-8859-1
  同ISO-8859-1
  普通Java程序的编译过程与Servlet完全一样。

  CLASS文件中的中文表示法是不是昭然若揭了?OK,接下来看看CLASS又是怎样输出中文的呢?

用户评论

  • 用户名
  • 评论内容