JSP中编码问题

来源:互联网 发布:股票股软件开发 编辑:程序博客网 时间:2024/05/17 22:53

第一种解释:

JSP/Servlet web 编程时的 encoding 问题
  运行于Java 应用服务器的 JSP/Servlet 为 Browser 提供 HTML 内容,
  其中有字符编码转换的地方有:
  a.JSP 编译。Java 应用服务器将根据 JVM 的 file.encoding 值读取 JSP 源文件,并转换为内部字符编码进行 JSP 编译,生成 JAVA 源文件,根据file.encoding值写回文件系统。如

果当前系统语言支持GBK,那么这时候不会出现encoding问题。如果是英文的系统,如LANG 是 en_US的Linux,AIX或Solaris,则要将JVM的file.encoding值置成GBK。系统语言如果是GB2312,

则根据需要,确定要不要设置file.encoding,将 file.encoding 设为 GBK 可以解决潜在的 GBK 字符乱码问题
  b.Java需要被编译为.class才能在JVM中执行,这个过程存在与a.同样的file.encoding问题。从这里开始servlet和jsp的运行就类似了,只不过 Servlet 的编译不是自动进行的。
  c.Servlet需要将HTML页面内容转换为browser可接受的encoding内容发送出去。依赖于各JAVAAppServer的实现方式,有的将查询 Browser的accept-charset和accept-language参数或以

其它猜的方式确定encoding值,有的则不管。因此constant-encoding也许是最好的解决方法。对于中文网页,可在JSP或Servlet中设置contentType="text/html;charset=GB2312";如果页面

中有GBK字符,则设置为contentType="text/html; charset=GBK",由于IE 和 Netscape对GBK的支持程度不一样,作这种设置时需要测试一下。
  因为16位JAVAchar在网络传送时高8位会被丢弃,也为了确保Servlet页面中的汉字(包括内嵌的和servlet运行过程中得到的)是期望的内码,可以用PrintWriterout=res.getWriter()取

代ServletOutputStreamout=res.getOutputStream(),PrinterWriter将根据contentType中指定的charset作转换(ContentType需在此之前指定!);也可以用OutputStreamWriter封装

ServletOutputStream类并用write(String)输出汉字字符串。 对于 JSP,JAVA Application Server 应当能够确保在这个阶段将嵌入的汉字正确传送出去。
  d.这是URL字符encoding问题。如果通过get/post方式从browser返回的值中包含汉字信息,servlet将无法得到正确的值。SUN的 J2SDK 中,HttpUtils.parseName 在解析参数时根本没有

考虑 browser 的语言设置,而是将得到的值按 byte 方式解析。这是网上讨论得最多的 encoding问题。因为这是设计缺陷,只能以bin方式重新解析得到的字符串;或者以hackHttpUtils类

的方式解决。参考文章2、3均有介绍,不过最好将其中的中文 encoding GB2312、 CP1381 都改为 GBK,否则遇到 GBK 汉字时,还是会有问题。
  ServletAPI2.3提供一个新的函数HttpServeletRequest.setCharacterEncoding用于在调用request.getParameter(“param_name”) 前指定应用程序希望的 encoding,这将有助于彻底解

决这个问题。
  WebSphere Application Server 对标准的 Servlet API 2.x 作了扩展,提供较好的多语言支持。上述c,d情况,WAS 都要查询 Browser 的语言设置,在缺省状况下zh、zh-cn 等均被映

射为 JAVA encoding CP1381(注意:CP1381 只是等同于 GB2312 的一个 codepage,没有 GBK 支持)。这样做我想是因为无法确认 Browser 运行的操作系统是支持GB2312, 还是 GBK,所以

取其小。但是实际的应用
系统还是要求页面中出现 GBK 汉字,最著名的是朱总理名字中的“?”(rong2 ,0xe946,/u9555),所以有时还是需要将 Encoding/Charset 指定为 GBK。当然 WAS 中变更缺省的 encoding

没有上面说的那么麻烦,针对 a,b,参考文章 5 ),在 Application Server 的命令行参数中指定-Dfile.encoding=GBK即可;针对d,在ApplicationServer的命令行参数中指定-

Ddefault.client.encoding=GBK。如果指定了-Ddefault.client.encoding=GBK,那么c情况下可以不再指定charset。

 

第二种解释:

当请求一个JSP页面时,一般的都需要经历下面几个阶段:

1、应用服务器根据JSP页面生成一个Java文件

2、应用服务器调用java.exe将Java文件编译成一个Servlet对应的class文件

3、用户的浏览器请求JSP对应的Servlet,Web容器起一个线程执行Servlet,将数据返回给客户端浏览器

4、用户的IE根据返回的数据,将结果显示给用户。

    第一步中应用服务器根据Jsp页面生成一个Java文件时,需要读取源Jsp页面到内存中,然后以某种编码方式生成Servlet类文件,这一读的过程会涉及到采用什么编码方式来读取的问题?

这里先看一下结论:如页面中设置了pageEncoding="XX",则服务器在读取Jsp页面时,就会使用上面设置的XX来读取,如果没有设置,再看是否设置了contentType="text/html;

charset=XXX" ,如果设置了,则用charset中指定的编码方式来读取。如果这两个都没有指定时,则使用默认的编码方式ISO8859-1来读取 。

以上是读取的过程,当把Jsp页面读取到内存后,在内存中以Unicode编码存在,这时需要根据Jsp文件生成Servlet类文件,既然要定文件,这里又会涉及到编码问题,这里该使用什么编码方

式来输出到文件呢?先看结论:Tomcact是使用UTF-8编码方式来输出的 ,这也是理所当然的,因为页面上会有不同的各种语言。

 

第三种解释:

JSP 编译。Java 应用服务器将根据 JVM 的 file.encoding 值读取 JSP 源文件,编译生成 JAVA 源文件,再根据 file.encoding 值写回文件系统。如果当前系统语言支持 GBK,那么这时候

不会出现 encoding 问题。如果是英文的系统,如 LANG 是 en_US 的 Linux, AIX 或 Solaris,则要将 JVM 的 file.encoding 值置成 GBK 。系统语言如果是 GB2312,则根据需要,确定要

不要设置 file.encoding,将 file.encoding 设为 GBK 可以解决潜在的 GBK 字符乱码问题
Java 需要被编译为 .class 才能在 JVM 中执行,这个过程存在与 a. 同样的 file.encoding 问题。从这里开始 servlet 和 jsp 的运行就类似了,只不过 Servlet 的编译不是自动进行的

。对于 JSP 程序 , 对产生的 JAVA 中间文件的编译是自动进行的 ( 在程序中直接调用 sun.tools.javac.Main 类 ). 因此如果在这一步出现问题的话 , 也要检查 encoding 和 OS 的语言

环境,或者将内嵌在 JSP JAVA Code 中的静态汉字转为 Unicode, 要么静态文本输出不要放在 JAVA code 中。 对于 Servlet, javac 编译时手工指定 -encoding 参数就可以了。
Servlet 需要将 HTML 页面内容转换为 browser 可接受的 encoding 内容发送出去。依赖于各 JAVA App Server 的实现方式,有的将查询 Browser 的 accept-charset 和 accept-language

参数或以其它猜的方式确定 encoding 值,有的则不管。因此采用固定 encoding 也许是最好的解决方法。对于中文网页,可在 JSP 或 Servlet 中设置 contentType="text/html;

charset=GB2312";如果页面中有 GBK 字符,则设置为 contentType="text/html; charset=GBK",由于 IE 和 Netscape 对 GBK 的支持程度不一样,作这种设置时需要测试一下。 因为 16

位 JAVA char 在网络传送时高 8 位会被丢弃,也为了确保 Servlet 页面中的汉字(包括内嵌的和 servlet 运行过程中得到的)是期望的内码,可以用 PrintWriter out=res.getWriter()

取代 ServletOutputStream out=res.getOutputStream(). PrinterWriter 将根据 contentType 中指定的 charset 作转换 (ContentType 需在此之前指定! ); 也可以用

OutputStreamWriter 封装 ServletOutputStream 类并用 write(String) 输出汉字字符串。 对于 JSP,JAVA Application Server 应当能够确保在这个阶段将嵌入的汉字正确传送出去。
这是解释 URL 字符 encoding 问题。如果通过 get/post 方式从 browser 返回的参数值中包含汉字信息, servlet 将无法得到正确的值。SUN 的 J2SDK 中,HttpUtils.parseName 在解析

参数时根本没有考虑 browser 的语言设置,而是将得到的值按 byte 方式解析。这是网上讨论得最多的 encoding 问题。因为这是设计缺陷,只能以 bin 方式重新解析得到的字符串;或者

以 hack HttpUtils 类的方式解决。参考文章 2 均有介绍,不过最好将其中的中文 encoding GB2312、 CP1381 都改为 GBK,否则遇到 GBK 汉字时,还是会有问题。 Servlet API 2.3 提供

一个新的函数 HttpServeletRequest.setCharacterEncoding 用于在调用 request.getParameter(“param_name”) 前指定应用程序希望的 encoding,这将有助于彻底解决这个问题。

 

原创粉丝点击