Java Web 中文乱码问题总结

来源:互联网 发布:固定资产台账软件 编辑:程序博客网 时间:2024/05/02 02:06

目录

  • 1、概述
  • 2、 引言
  • 3、 中文乱码产生的原因
  • 4、中文乱码问题的解决方案
    • 4.1 最基本的乱码问题
    • 4.2 表单get提交方式的乱码处理方式
    • 4.3 表单使用Post方式提交后接收到的乱码问题
    • 4.4 数据库中的中文
    • 4.5 浏览器编码问题
    • 4.6 服务器apache上的乱码


1、概述

此文档并不是原创,而是摘录自网络上的文章
主要摘自以下文章:
1、Java WEB中文乱码问题
2、java web 乱码 问题

2、引言

为了能在计算机中表示不同语言中字符,每个国家(或区域)都规定了计算机信息交换用的字符编码集,如美国的ASCII,中国GB2312和GBK,日本的JIS等。Java语言内部用Unicode来表示字符,Unicode被称为统一的字符编码标准集,它为几乎每种语言中的字符设定了唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。这也使得Java具有良好的可移植性,符合其国际化的思想。然而在实际应用中,由于应用程序的运行环境不同,和各个本地字符集的补充、完善,以及系统或应用程序实现的不规范,转码时出现的中文乱码问题时时困扰着程序员和用户。

3、中文乱码产生的原因

Java中文问题一直困扰着很多初学者,如果了解了Java系统的中文问题原理,我们就可以对中文问题能够采取根本的解决之道。最古老的解决方案是使用String的字节码转换,这种方案问题是不方便,我们需要破坏对象封装性,进行字节码转换。还有一种方式是对J2EE容器进行编码设置,如果J2EE应用系统脱离该容器,则会发生乱码,而且指定容器配置不符合J2EE应用和容器分离的原则。
       在Java内部运算中,涉及到的所有字符串都会被转化为UTF-8编码来进行运算。那么,在被Java转化之前,字符串是什么样的字符集? Java总是根据操作系统的默认编码字符集来决定字符串的初始编码,而且Java系统的输入和输出的都是采取操作系统的默认编码。 因此,如果能统一Java系统的输入、输出和操作系统3者的编码字符集合,将能够使Java系统正确处理和显示汉字。这是处理Java系统汉字的一个原则, 但是在实际项目中,能够正确抓住和控制住Java系统的输入和输出部分是比较难的。J2EE中,由于涉及到外部浏览器和数据库等,所以中文问题乱码显得非常突出。
       J2EE应用程序是运行在J2EE容器中。在这个系统中,输入途径有很多种:

  • 通过页面表单打包成请求 (request)发往服务器的
  • 通过数据库读入
  • JSP在第一次运行时总是被编译成Servlet,JSP中常常包含 中文字符,那么编译使用javac时,Java将根据默认的操作系统编码作为初始编码。除非特别指定,如在Jbuilder/eclipse中可以指定默 认的字符集
       输出途径也有几种:
  • JSP页面的输出。由于JSP页面已经被编译成Servlet,那么在输出时,也将根据操作系统的默认编码来选择输出编码,除非指定输出编码方式
  • 数据库,将字符串输出到数据库
       由此看来,一个J2EE系统的输入输出是非常复杂,而且是动态变化的,而Java是跨平台运行的,在实际编译和运行中,都可能涉及到不同的操作系统,如果任由Java自由根据操作系统来决定输入输出的编码字符集,这将不可控制地出现乱码。
       正是由于Java的跨平台特性,使得字符集问题必须由具体系统来统一解决,所以在一个Java应用系统中,解决中文乱码的根本办法是明确指定整个应用系统统一字符集。 指定统一字符集时,到底是指定ISO8859_1 、GBK还是UTF-8呢?
  • 3. 那么有没有一种除了应用系统以外不需要进行任何附加设置的中文编码根本解决方案呢? 将Java/J2EE系统的统一编码定义为UTF-8。UTF-8编码是一种兼容所有语言的编码方式,惟一比较麻烦的就是要找到应用系统的所有出入口,然后使用UTF-8去“结扎”它。 一个J2EE应用系统需要做下列几步工作:
    • 3.1 开发和编译代码时指定字符集为UTF-8。JBuilder和Eclipse都可以在项目属性中设置。
    • 3.2 使用过滤器,如果所有请求都经过一个Servlet控制分配器,那么使用Servlet的filter执行语句,将所有来自浏览器的请求(request)转换为UTF-8,因为浏览器发过来的请求包根据浏览器所在的操作系统编码,可能是各种形式编码。
      关键一句:request.setCharacterEncoding(“UTF-8”)。 网上有此filter的源码,Jdon框架源码中com.jdon.util.SetCharacterEncodingFilter ,需要配置web.xml 激活该Filter。
    • 3.3在JSP头部声明。
    • 3.4 在Jsp的html代码中,声明UTF-8。
    • 3.5设定数据库连接方式是UTF-8。例如连接MYSQL时配置URL如下: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8 一般数据库都可以通过管理设置设定UTF-8
    • 3.6 其他和外界交互时能够设定编码时就设定UTF-8,例如读取文件,操作XML等。在Web应用中,通常都包括了浏览器、Web服务器、Web应用程序和数据库等部分。若不指定编码格式,浏览器会根据本地系统默认的字符集(如:GB2312)提交数据,而Web容器默认采用的是ISO-8859-1的编码方式解析Post数据,另外JDBC驱动程序多数也采用ISO-8859-1的编码方式
  • 因此,在Web应用程序运行过程中,输入的中文字符往往需要在不同的字符集之间来回转换,这就导致了中文乱码问题的频繁出现。

    4、中文乱码问题的解决方案

           通过对中文乱码产生原因的分析,结合容易产生该问题的具体场景,提出以下的解决方案。

    4.1 最基本的乱码问题。

           这个乱码问题是最简单的乱码问题。一般新人会出现。就是页面编码不一致导致的乱码。

    <%@ page language="java" pageEncoding="UTF-8"%><%@ page contentType="text/html;charset=iso8859-1"%><html><head><title>中文问题</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head></head><body>我是个好人</body></html>

    三个地方的编码。
    第一个地方的编码格式为jsp文件的存储格式。Ecljpse等编辑jsp的环境会根据这个编码格式保存并编译jsp文件,编辑时要将编辑jsp的环境设置成这样的编码格式载入。

    第二处编码为解码格式,即浏览器按照什么格式显示网页。缺省是使用iso8859-1的编码格式。因为iso8859-1不含中文字符,这样如有中文肯定出现乱码。也就是要换成GB2312或UTF-8。此句必须,若不设置有时浏览器不知道用什么编码方式显示网页。当此句设置的和第一句相同时,可以省略第一句。

    第三处编码为html控制浏览器的解码方式。如果前面的两处都无误的话,这个编码格式没有关系。有的网页出现乱码,就是因为浏览器不能确定使用哪种编码格式。因为页面有时候会嵌入页面,导致浏览器混淆了编码格式。出现了乱码。

    4.2 表单get提交方式的乱码处理方式

           如果使用get方式提交中文,接受参数的页面也会出现乱码,这个乱码的原因也是tomcat的内部编码格式iso8859-1导致。Tomcat会以get的缺省编码方式iso8859-1对汉字进行编码,编码后追加到url,导致接受页面得到的参数为乱码。解决办法:A, 使用上例中的第一种方式,对接受到的字符进行解码,再转码。B, Get走的是url提交,而在进入url之前已经进行了iso8859-1的编码处理。要想影响这个编码则需要在server.xml的Connector节点增加useBodyEncodingForURI=”true”属性配置,即可控制tomcat对get方式的汉字编码方式,上面这个属性控制get提交也是用request.setCharacterEncoding (“UTF-8”)所设置的编码格式进行编码。所以自动编码为utf-8,接受页面正常接受就可以了。但我认为真正的编码过程是,tomcat又要根据

    <Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" useBodyEncodingForURI="true" disableUploadTimeout="true" URIEncoding=”UTF-8”/>

    里面所设置的URIEncoding=”UTF-8”再进行一次编码,但是由于已经编码为utf-8,再编码也不会有变化了。如果是从url获取编码,接受页面则是根据URIEncoding=”UTF-8”来进行解码的。

    4.3表单使用Post方式提交后接收到的乱码问题

           这个问题也是一个常见的问题。这个乱码也是tomcat的内部编码格式iso8859-1在捣乱,也就是说post提交时,如果没有设置提交的编码格式,则 会以iso8859-1方式进行提交,接受的jsp却以utf-8的方式接受。导致乱码。既然这样的原因,下面有几种解决方式,并比较。

    1. 接受参数时进行编码转换String str = new String(request.getParameter(“something”).getBytes(“ISO-8859-1”),”utf-8”) ; 这样的话,每一个参数都必须这样进行转码。很麻烦。但确实可以拿到汉字。
    2. 接受此参数的页面,执行请求的编码代码, request.setCharacterEncoding(“UTF-8”),把提交内容的字符集设为UTF-8。这样的话,直接使用String str = request.getParameter(“something”);即可得到汉字参数。但每页都需要执行这句话。这个方法也就对post提交的有效 果,对于get提交和上传文件时的enctype=”multipart/form-data”是无效的。稍后下面单独对这个两个的乱码情况再进行说明。
    3. 为了避免每页都要写request.setCharacterEncoding(“UTF-8”),建议使用过滤器对所有jsp进行编码处理。
    如:在web.xml里面加

     <filter>        <filter-name>char</filter-name>        <filter-class>com.bbs.common.CharacterFilter</filter-class> </filter> <filter-mapping>        <filter-name>char</filter-name>        <url-pattern>/*</url-pattern> </filter-mapping>

    CharacterFilter类

    package com.bbs.common;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class CharacterFilter implements Filter {    public void destroy() {    }    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {        System.out.println("filter....");        request.setCharacterEncoding("UTF-8");        chain.doFilter(request, response);    }    public void init(FilterConfig filterConfig) throws ServletException {    }}

    4.4数据库中的中文

           对于大多数数据库的JDBC驱动程序,在Java程序和数据库之间传递数据都是以ISO-8859-1为默认编码格式,所以,在程序中向数据库存储包含中文的数据时,驱动程序受限把程序内部Unicode编码格式的数据转换为ISO-8859-1编码,然后传递到数据库中;在数据库保持数据时,默认即以ISO-8859-1保持,这就是为什么常常在数据库中读取中文数据时,读到的是乱码。要解决上述问题 只需要将数据库默认的编码格式改为GBK或GB2312即可。

    4.5 浏览器原因中文乱码

           问题:编码为utf-8,url 出现乱码。form表单get、post方式都无乱码,页面链接地址也无中文乱码,刷新页面无乱码,但是选中地址栏中的url 敲回车,乱码出现了!
      原因:浏览器配置问题。
      解决方案:
      ie:“internet选项/高级”中“总以utf-8发送网址”的选项的配置;
      firefox:地址栏中输入about:config,修改network.standard-url.escape-utf8 为False (缺省为True);如果你想让浏览器直接url-encode成utf-8,修改network.standard-url.encode-utf8为true(缺省为false)。解释:根据Web规范,URL必须以UTF-8字符集进行编码。 而Firefox默认gbk encode,ie默认utf8 encode;另外Firefox对地址中的中文采取了不同于IE的编码方式,也就是说:当url参数值含有中文时firefox默认使用escape进行编码,当参数值没有用escape进行编码时,使用进行解码IE下不会乱码,但Firefox下会乱码。
      附:prefs.converted-to-utf8 * 首选项转换成UTF-8编码格式 network.standard-url * Standard URL settings

    4.6、服务器apache上的乱码

           apache的配置问题,注意的方面有以下几点:
      1)conf/httpd.conf
      把AddDefaultCharset ISO-8859-1 改成 AddDefaultCharset GBK
      2)apache进行了rewrite
      把需要rewrite的url中的中文参数进行两次编码(encode),因为apache在rewrite时会做一次url解码,这时jk进行请求转发时,就不会再是编码后的字符串了;或者在接收请求时先用ISO-8859-1取字节流,再使用UFT-8来new String。(new String(str.getBytes(“ISO-8859-1”),”UFT-8”))

    0 0