JAVA技术探索

统计

最新评论

JSP,SERVLET,STRUTS等的汉字问题的原理和解决方案

Java中文问题一直困扰着很多初学者,如果了解了Java系统的中文问题原理,我们就可以对中文问题能够采取根本的解决之道。

n       HTTP 传输编码用 ISO88-59-1, 一些数据库如 SQLServer2000 等的默认编码也是 ISO88-59-1

n       通常我们在服务器的 Jsp,Html 或者 Servlet 中的编码方式为 GB2312,GBK,UTF-8 等,

         <meta http-equiv="Content-Type" content="text/html; charset=GBK">
      <%@ page contentType="text/html; charset=gb2312" language="java" %>

 

n       有的时候显示可能没有问题,但遇到数据的传输可能会出现乱码

bianma.bmp
JSP
的汉字问题出现环节

n       客户端显示文档时的编码方式(由服务器中的 JSP Servlet 指明)

n       客户端发送汉字时自动转换为 iso-8859-1

n       服务器中采用 gb2312 对汉字编码,接收到客户端汉字需要转换为 gb2312

n       服务器端将 JSP 转换为 Servlet 时自动将汉字转换为 iso-8859-1

n       服务器端应该告诉客户端汉字的编码方式

n       JSP 中的汉字字符串在服务器端用 gb2312

n       在编译为 Servlet 时自动转换为 iso-8859-1

n       在没有特别指示下,浏览器中无法正确显示

 

解决方案

  为解决单独页面显示方面的问题可以使用以下方案

n       HTML 中指示浏览器文档的编码

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

n       JSP 中指示 JSP 引擎文档的编码,每个要显示汉字的 JSP 文档都应该包含该语句

  <%@ page contentType="text/html;charset=gb2312"%>

n       Servle 中加入以下代码

  response.setContentType("text/html;charset=GB2312");

n      但数据在传输的时候可能又会变成乱码,这时候我们需要在接受的页面中加入

request.setCharacterEncoding("GB2312");

    或者使用最古老的解决方案是使用String的字节码转换,这种方案问题是不方便,我们需要破坏对象封装性,进行字节码转换。   

public class trans {

 

 public static String trans(String str)

 {

                String result = null;

                byte temp [];

                try

                {

                        temp=str.getBytes("iso-8859-1");

                       result = new String(temp);

                 }

                 catch(UnsupportedEncodingException e)

                 {

                         System.out.println (e.toString());

                 }

                     return result;

 }

}


    还有一种方式是对
J2EE 容器进行编码设置,如果 J2EE 应用系统脱离该容器,则会发生乱码,而且指定容器配置不符合 J2EE 应用和容器分离的原则。

  在 Java 内部运算中,涉及到的所有字符串都会被转化为 UTF-8 编码来进行运算。那么,在被 Java 转化之前,字符串是什么样的字符集?
        Java总是根据操作系统的默认编码字符集来决定字符串的初始编码,而且Java系统的输入和输出的都是采取操作系统的默认编码。

   因此,如果能统一 Java 系统的输入、输出和操作系统 3 者的编码字符集合,将能够使 Java 系统正确处理和显示汉字。这是处理 Java 系统汉字的一个原则,但是在实际项目中,能够正确抓住和控制住 Java 系统的输入和输出部分是比较难的。 J2EE 中,由于涉及到外部浏览器和数据库等,所以中文问题乱码显得非常突出。 
         J2EE 应用程序是运行在 J2EE 容器中。在这个系统中,输入途径有很多种:一种是通过页面表单打包成请求( request )发往服务器的;第二种是通过数据库读入;还有第 3 种输入比较复杂, JSP 在第一次运行时总是被编译成 Servlet,JSP中常常包含中文字符,那么编译使用javac时,Java将根据默认的操作系统编码作为初始编码。除非特别指定,如在Jbuilder/eclipse中可以指定默认的字符集。
  输出途径也有几种:第一种是 JSP 页面的输出。由于 JSP 页面已经被编译成 Servlet ,那么在输出时,也将根据操作系统的默认编码来选择输出编码,除非指定输出编码方式;还有输出途径是数据库,将字符串输出到数据库。
   由此看来,一个 J2EE 系统的输入输出是非常复杂,而且是动态变化的,而 Java 是跨平台运行的,在实际编译和运行中,都可能涉及到不同的操作系统,如果任由 Java 自由根据操作系统来决定输入输出的编码字符集,这将不可控制地出现乱码。
  正是由于 Java 的跨平台特性,使得字符集问题必须由具体系统来统一解决,所以在一个 Java 应用系统中,解决中文乱码的根本办法是明确指定整个应用系统统一字符集。

  指定统一字符集时,到底是指定 ISO-8859-1 , GB2312 还是 UTF-8 呢?
  1. 如统一指定为 ISO-8859-1 ,因为目前大多数软件都是西方人编制的,他们默认的字符集就是 ISO-8859-1,包括操作系统Linux和数据库MySQL等。这样,如果指定Jive统一编码为ISO-8859-1,那么就有下面3个环节必须把握:

  <1>.开发和编译代码时指定字符集为 ISO-8859-1,
  <2>.运行操作系统的默认编码必须是 ISO-8859-1,Linux
  <3>.在 JSP 头部声明:

<%@ page contentType="text/html;charset=ISO-8859-1" %>


  2. 如果统一指定为 GB2312 中文字符集,上述 3 个环节同样需要做到,不同的是只能运行在默认编码为 GBK 的操作系统,如中文 Windows
  统一编码为 ISO-8859-1 GB2312 虽然带来编制代码的方便,但是各自只能在相应的操作系统上运行。但是也破坏了 Java 跨平台运行的优越性,只在一定范围内行得通。例如,为了使得 GB2312 编码在 linux 上运行,设置 Linux 编码为 GB2312
  那么有没有一种除了应用系统以外不需要进行任何附加设置的中文编码根本解决方案呢?
  将 Java/J2EE 系统的统一编码定义为 UTF-8 , UTF-8 编码是一种兼容所有语言的编码方式,惟一比较麻烦的就是要找到应用系统的所有出入口,然后使用 UTF-8  "结扎"它。
一个
J2EE 应用系统需要做下列几步工作:

开发和编译代码时指定字符集为 UTF-8 ,JBuilderEclipse都可以在项目属性中设置。
使用过滤器,如果所有请求都经过一个 Servlet 控制分配器,那么使用 Servlet filter 执行语句,将所有来自浏览器的请求( request )转换为 UTF-8 ,因为浏览器发过来的请求包根据浏览器所在的操作系统编码,可能是各种形式编码。关键一句:

request.setCharacterEncoding("UTF-8")


public class SetCharacterEncodingFilter implements Filter {

protected String encoding = null;

 

protected FilterConfig filterConfig = null;

 

public void destroy() {

 

        this.encoding = null;

        this.filterConfig = null;

 

}

 

public void doFilter(ServletRequest request, ServletResponse response,

               FilterChain chain) throws IOException, ServletException {

 

        request.setCharacterEncoding(encoding);

 

        chain.doFilter(request, response);

 

}

 

public void init(FilterConfig filterConfig) throws ServletException {

 

        this.filterConfig = filterConfig;

        this.encoding = filterConfig.getInitParameter("encoding");

 

}

 

protected String selectEncoding(ServletRequest request) {

 

        return (this.encoding);

 

}
}

 

 

需要配置 web.xml 激活该 Filter
  <filter>

<filter-name>SetCharacterEncodingFilter</filter-name>

<filter-class>com.yinhe.Filter.SetCharacterEncodingFilter</filter-class>

<init-param>

        <param-name>encoding</param-name>

        <param-value>UTF-8</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>SetCharacterEncodingFilter</filter-name>

<url-pattern>/*</url-pattern>
</filter-mapping>


JSP
头部声明:
<%@ page contentType="text/html;charset= UTF-8" %>  

JSP html 代码中,声明 UTF-8:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

设定数据库连接方式是 UTF-8 ,例如连接 MYSQL 时配置 URL 如下:

jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8

一般数据库都可以通过管理设置设定 UTF-8
其他和外界交互时能够设定编码时就设定 UTF-8,例如读取文件,操作XML等。

posted on 2006-05-19 11:57 JAVA技术探索 阅读(211) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问