jsp中文问题解决方案.docx

上传人:b****7 文档编号:9555175 上传时间:2023-02-05 格式:DOCX 页数:30 大小:37.03KB
下载 相关 举报
jsp中文问题解决方案.docx_第1页
第1页 / 共30页
jsp中文问题解决方案.docx_第2页
第2页 / 共30页
jsp中文问题解决方案.docx_第3页
第3页 / 共30页
jsp中文问题解决方案.docx_第4页
第4页 / 共30页
jsp中文问题解决方案.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

jsp中文问题解决方案.docx

《jsp中文问题解决方案.docx》由会员分享,可在线阅读,更多相关《jsp中文问题解决方案.docx(30页珍藏版)》请在冰豆网上搜索。

jsp中文问题解决方案.docx

jsp中文问题解决方案

利用过滤器解决JavaWeb(JSP)的乱码问题

我们在做web项目的时候,在中文字符处理上最头痛的一个问题是乱码问题;通常我们是通过在代码里面加入各种设置编码的语句,来处理这个问题,但是有的时候真是收效甚微;而且更繁琐的是如果你的文件很多很多,很多处要进行编码设置,你得到处找到,哪里要进行设置,更坏的是,如果要改系统的编码设置,你想想这得花多大功夫,甚至是一件不可完成的任务。

过滤器机制是servlet的一个很好的拓展机制。

用过滤器是这个问题的一个很好的解决方法。

我们不是去找问题,而是等着问题来找上门来。

在服务器端通过过滤器,将所有的request和response进行编码设置,就相当于一夫当关之效果。

因为所有的请求、回复都是要经过过滤器的。

下面就看如何实现这个简单的过滤器吧。

一、编写过滤器处理类

//CharsetFilter.java

packagefilter;

importjava.io.IOException;

importjavax.servlet.Filter;

importjavax.servlet.FilterChain;

importjavax.servlet.FilterConfig;

importjavax.servlet.ServletException;

importjavax.servlet.ServletRequest;

importjavax.servlet.ServletResponse;

//实现javax.servlet.Filter接口即可作为一个过滤器了

publicclassCharsetFilterimplementsFilter{

privateStringcharset;//字符编码

privatebooleanenabled;//开关

publicvoiddestroy(){

System.out.println("销毁编码过滤器");

}

publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,

FilterChainchain)throwsIOException,ServletException{

if(enabled&&charset!

=null){//如果开关打开且字符编码不空

//设置编码

request.setCharacterEncoding(charset);

response.setCharacterEncoding(charset);

}

chain.doFilter(request,response);

}

publicvoidinit(FilterConfigconfig)throwsServletException{

System.out.println("初始化编码过滤器");

//从配置文件获取参数:

charset

this.charset=config.getInitParameter("charset");this.enabled="true".equals(config.getInitParameter("enabled"));

System.out.println("字符编码:

"+charset+"是否启用:

"+enabled);

}

}

编译好类后将其放到web项目的classes下(当然如果你是在MyEclipse这样的IDE下测试就不必了,省事多了)

二、配置web.xml

在web.xml文件下添加如下内容

charsetFilter

filter.CharsetFilter

charset

gb2312

enabled

true

charsetFilter

/*

完成后的web.xml大致如下:

xmlversion="1.0"encoding="UTF-8"?

>

xsi="http:

//www.w3.org/2001/XMLSchema-instance"version="2.5"xsi:

schemaLocation="

index.jsp

--配置过滤器-->

--过滤器名称-->

charsetFilter

--过滤器类路径-->

filter.CharsetFilter

--初始化参数-->

--编码参数-->

charset

gb2312

--控制是否启用过滤器-->

enabled

true

--还可以配置其他更多参数-->

--过滤器映射-->

charsetFilter

--过滤的URL(*表示所有请求都被拦截过滤)-->

/*

至此过滤器完成了。

可以编写一下测试用例进行测试,并且试试修改一下配置文件里的编码,看看是不是可以决定整个系统的编码。

jsp中文问题解决方案(完整版)_jsp技巧

开发java应用出现乱码是很常见的,毕竟现在unicode的使用还不是很广泛,在使用gb2312(包含了gbk简体,big5繁体)的系统中要正确实现中文的display和数据库的存储是最基本的要求。

1.首先developer要明确自己为什么会遇到乱码,遇到什么样的乱码(无意义的符号还是一串问号或者其它什么东西)。

新手遇到一堆很乱的字符时通常不知所措,最直接的反映就是打开google搜索”java中文”(这个字符串在搜索引擎上的查询频率非常高),然后一个一个的去看别人的解决方法。

这样做没有错,但是很难达到目的,原因下面会提到。

总之,出现乱码的原因是非常多的,解决的方法也完全不一样,要解决问题必须先分析自己的”上下文环境”。

2.具体说来,需要哪些信息才能确定项目中的乱码的根源。

⏹开发者所用的操作系统

⏹j2ee容器的名称,版本

⏹数据库的名称,版本(精确版本)以及jdbc驱动的版本

⏹出现乱码的sourcecode(比如是systemout出来的,还是jsp页面中的,如果是jsp中的,那么头部声明的情况也很重要)

3.如何初步分析乱码出现的原因。

(1)分析一下你的”乱码”到底是什么编码。

这个其实不难,比如

System.out.println(testString);

这一段出现了乱码,那么不妨用穷举法猜测一下它的实际编码格式。

System.out.println(newString(testString.getBytes(”ISO-885Array-1″),”gb2312″));

System.out.println(newString(testString.getBytes(”UTF8″),”gb2312″));

System.out.println(newString(testString.getBytes(”GB2312″),”gb2312″));

System.out.println(newString(testString.getBytes(”GBK”),”gb2312″));

System.out.println(newString(testString.getBytes(”BIG5″),”gb2312″));

等等,上述代码的意思是用制定的编码格式去读取testString这个”乱码”,并转换成gb2312(此处仅以中文为例)

(2)如果用上面的步骤能得到正确的中文,说明你的数据肯定是在的,只不过是界面中没有正确显示而已。

那么第二步就该纠正你的view部分了,通常需要检查的是jsp中是否选择了正确的页面编码。

在此要声明被很多人误解的一点,那就是指令和content=”text/html;charset=gb2312″>两者的不同。

通常网上的很多文章在提到中文问题时都是说数据库中选择unicode或者gb2312存储,同时在jsp中用page指令声明编码就可以解决。

但是我觉得这种说法很不负责任,害的我费了N多时间为本来并不存在的乱码而郁闷。

实际上page的作用是在jsp被编译成为html的过程中提供编码方式让java来”读取”表达式当中的String(有点类似于上面的第三个语句的作用),而meta的作用是众所周知的为IE浏览器提供编码选择,是用来”显示”最后的数据的。

但是没有看到有人提醒这一点,我一直把page当成meta在用,导致本来是iso-885Array的数据,被page指令读成gb2312,于是乱码,所以又加了编码转化的函数把所有的string数据都从iso885Array转到gb2312(为什么这么转,当时也没考虑这么多,因为这么做可以正常显示了,所以就这么改了,呵呵当时实在没有时间慢慢排查问题了)。

4.数据库选择什么样的编码比较好。

目前流行的DB主要有sqlserver,mysql,oracle,DB2等,其中mysql作为免费DB中的老大,性能和功能是得到公认的,安装配置比较方便,相应的driver也比较完善,性价比是绝对的OK。

所以就以mysql为例。

我个人建议采用mysql的默认编码来存储,也就是iso-885Array-1(在mysql的选项中对应于latin-1)。

理由主要有这么几个,一是iso-885Array-1对中文的支持不错;二是跟java中的默认编码一致,至少在很多地方免除了转换编码的麻烦;三是默认的比较稳定,兼容性也更好,因为多编码的支持是由具体的DB产品提供的,别说跟其它的DB会不兼容,即使自身的不同版本也可能出现兼容性的问题。

例如mysql4.0以前的产品中,很多中文的解决方案是利用connection中的characterEncoding字段来制定编码,比如gb2312什么的,这样是ok的,因为原数据都是ISO885Array_1编码,jdbc驱动会采用url里面指定的characterset来进行编码,resultSet.getString(*)取出的就是编码后的字符串。

这样就直接拿到gb2312的数据了。

但是mysql4.1的推出给很多dbadmin带来了不小的麻烦,因为mysql4.1支持columnlevel的characterset,每个table,column都可以指定编码,不指定就是ISO88Array5_1,因此jdbc取出数据后会根据column的characterset来进行编码,而不再是用一个全局的参数来取所有的数据了。

————————————————————————————————

由于Java编程中的中文问题是一个老生常谈的问题,在阅读了许多关于Java中文问题解决方法之后,结合作者的编程实践,我发现过去谈的许多方法都不能清晰地说明问题及解决问题,尤其是跨平台时的中文问题。

于是我给出此篇文章,内容包括对控制台运行的class、Servelets、JSP及EJB类中的中文问题我剖析和建议解决办法。

Abstract:

本文深入分析了Java程序设计中Java编译器对Java源文件和JVM对class类文件的编码/解码过程,通过此过程的解析透视出了Java编程中中文问题产生的根本原因,最后给出了建议的最优化的解决Java中文问题的方法。

1.中文问题的来源

计算机最初的操作系统支持的编码是单字节的字符编码,于是,在计算机中一切处理程序最初都是以单字节编码的英文为准进行处理。

随着计算机的发展,为了适应世界其它民族的语言(当然包括我们的汉字),人们提出了UNICODE编码,它采用双字节编码,兼容英文字符和其它民族的双字节字符编码,所以,目前,大多数国际性的软件内部均采用UNICODE编码,在软件运行时,它获得本地支持系统(多数时间是操作系统)默认支持的编码格式,然后再将软件内部的UNICODE转化为本地系统默认支持的格式显示出来。

Java的JDK和JVM即是如此,我这里说的JDK是指国际版的JDK,我们大多数程序员使用的是国际化的JDK版本,以下所有的JDK均指国际化的JDK版本。

我们的汉字是双字节编码语言,为了能让计算机处理中文,我们自己制定的gb2312、GBK、GBK2K等标准以适应计算机处理的需求。

所以,大部分的操作系统为了适应我们处理中文的需求,均定制有中文操作系统,它们采用的是GBK,GB2312编码格式以正确显示我们的汉字。

如:

中文Windows默认采用的是GBK编码显示,在中文Windows2000中保存文件时默认采用的保存文件的编码格式也是GBK的,即所有在中文Windows2000中保存的文件它的内部编码默认均采用GBK编码,注意:

GBK是在GB2312基础上扩充来的。

由于Java语言内部采用UNICODE编码,所以在Java程序运行时,就存在着一个从UNICODE编码和对应的操作系统及浏览器支持的编码格式转换输入、输出的问题,这个转换过程有着一系列的步骤,如果其中任何一步出错,则显示出来的汉字就会出是乱码,这就是我们常见的Java中文问题。

同时,Java是一个跨平台的编程语言,也即我们编写的程序不仅能在中文windows上运行,也能在中文Linux等系统上运行,同时也要求能在英文等系统上运行(我们经常看到有人把在中文Windows2000上编写的Java程序,移植到英文Linux上运行)。

这种移植操作也会带来中文问题。

还有,有人使用英文的操作系统和英文的IE等浏览器,来运行带中文字符的程序和浏览中文网页,它们本身就不支持中文,也会带来中文问题。

几乎所有的浏览器默认在传递参数时都是以UTF-8编码格式来传递,而不是按中文编码传递,所以,传递中文参数时也会有问题,从而带来乱码现象。

总之,以上几个方面是Java中的中文问题的主要来源,我们把以上原因造成的程序不能正确运行而产生的问题称作:

Java中文问题。

2.Java编码转换的详细过程

我们常见的Java程序包括以下类别:

⏹直接在console上运行的类(包括可视化界面的类)

⏹JSP代码类(注:

JSP是Servlets类的变型)

⏹Servelets类

⏹EJB类

⏹其它不可以直接运行的支持类

这些类文件中,都有可能含有中文字符串,并且我们常用前三类Java程序和用户直接交互,用于输出和输入字符,如:

我们在JSP和Servlet中得到客户端送来的字符,这些字符也包括中文字符。

无论这些Java类的作用如何,这些Java程序的生命周期都是这样的:

⏹*编程人员在一定的操作系统上选择一个合适的编辑软件来实现源程序代码并以.Java扩展名保存在操作系统中,例如我们在中文Windows2000中用记事本编辑一个Java源程序。

⏹*编程人员用JDK中的Javac.exe来编译这些源代码,形成.class类(JSP文件是由容器调用JDK来编译的)。

⏹*直接运行这些类或将这些类布署到WEB容器中去运行,并输出结果。

那么,在这些过程中,JDK和JVM是如何将这些文件如何编码和解码并运行的呢?

这里,我们以中文Windows2000操作系统为例说明Java类是如何来编码和被解码的。

第一步,我们在中文Windows2000中用编辑软件如记事本编写一个Java源程序文件(包括以上五类Java程序),程序文件在保存时默认采用了操作系统默认支持GBK编码格式(操作系统默认支持的格式为file.encoding格式)形成了一个.Java文件,也即,Java程序在被编译前,我们的Java源程序文件是采用操作系统默认支持的file.encoding编码格式保存的,Java源程序中含有中文信息字符和英文程序代码;要查看系统的file.encoding参数,可以用以下代码:

publicclassShowSystemDefaultEncoding

{

publicstaticvoidmain(String[]args)

{

Stringencoding=System.getProperty(”file.encoding”);

System.out.println(encoding);

}

}

第二步,我们用JDK的Javac.exe文件编译我们的Java源程序,由于JDK是国际版的,在编译的时候,如果我们没有用-encoding参数指定我们的Java源程序的编码格式,则Javac.exe首先获得我们操作系统默认采用的编码格式,也即在编译Java程序时,若我们不指定源程序文件的编码格式,JDK首先获得操作系统的file.encoding参数(它保存的就是操作系统默认的编码格式,如Windows2000,它的值为GBK),然后JDK就把我们的Java源程序从file.encoding编码格式转化为Java内部默认的UNICODE格式放入内存中。

然后,Javac把转换后的unicode格式的文件进行编译成.class类文件,此时.class文件是UNICODE编码的,它暂放在内存中,紧接着,JDK将此以UNICODE编码的编译后的class文件保存到我们的操作系统中形成我们见到的.class文件。

对我们来说,我们最终获得的.class文件是内容以UNICODE编码格式保存的类文件,它内部包含我们源程序中的中文字符串,只不过此时它己经由file.encoding格式转化为UNICODE格式了。

这一步中,对于JSP源程序文件是不同的,对于JSP,这个过程是这样的:

即WEB容器调用JSP编译器,JSP编译器先查看JSP文件中是否设置有文件编码格式,如果JSP文件中没有设置JSP文件的编码格式,则JSP编译器调用JDK先把JSP文件用JVM默认的字符编码格式(也即WEB容器所在的操作系统的默认的file.encoding)转化为临时的Servlet类,然后再把它编译成UNICODE格式的class类,并保存在临时文件夹中。

例如:

在中文Windows2000上,WEB容器就把JSP文件从GBK编码格式转化为UNICODE格式,然后编译成临时保存的Servlet类,以响应用户的请求。

第三步,运行第二步编译出来的类,分为三种情况:

⏹直接在console上运行的类

⏹EJB类和不可以直接运行的支持类(如JavaBean类)

⏹JSP代码和Servlet类

⏹Java程序和数据库之间

下面我们分这四种情况来看。

A、直接在console上运行的类

这种情况,运行该类首先需要JVM支持,即操作系统中必须安装有JRE。

运行过程是这样的:

首先Java启动JVM,此时JVM读出操作系统中保存的class文件并把内容读入内存中,此时内存中为UNICODE格式的class类,然后JVM运行它,如果此时此类需要接收用户输入,则类会默认用file.encoding编码格式对用户输入的串进行编码并转化为unicode保存入内存(用户可以设置输入流的编码格式)。

程序运行后,产生的字符串(UNICODE编码的)再回交给JVM,最后JRE把此字符串再转化为file.encoding格式(用户可以设置输出流的编码格式)传递给操作系统显示接口并输出到界面上。

以上每一步的转化都需要正确的编码格式转化,才能最终不出现乱码现象。

B、EJB类和不可以直接运行的支持类(如JavaBean类)

由于EJB类和不可以直接运行的支持类,它们一般不与用户直接交互输入和输出,它们常常与其它的类进行交互输入和输出,所以它们在第二步被编译后,就形成了内容是UNICODE编码的类保存在操作系统中了,以后只要它与其它的类之间的交互在参数传递过程中没有丢失,则它就会正确的运行。

C、JSP代码和Servlet类

经过第二步后,JSP文件也被转化为Servlets类文件,只不过它不像标准的Servlets一校存在于classes目录中,它存在于WEB容器的临时目录中,故这一步中我们也把它做为Servlets来看。

对于Servlets,客户端请求它时,WEB容器调用它的JVM来运行Servlet,首先,JVM把Servlet的class类从系统中读出并装入内存中,内存中是以UNICODE编码的Servlet类的代码,然后JVM在内存中运行该Servlet类,如果Servlet在运行的过程中,需要接受从客户端传来的字符如:

表单输入的值和URL中传入的值,此时如果程序中没有设定接受参数时采用的编码格式,则WEB容器会默认采用ISO-885Array-1编码格式来接受传入的值并在JVM中转化为UNICODE格式的保存在WEB容器的内存中。

Servlet运行后生成输出,输出的字符串是UNICODE格式的,紧接着,容器将Servlet运行产生的UNICODE格式的串(如html语法,用户输出的串等)直接发送到客户端浏览器上并输出给用户,如果此时指定了发送时输出的编码格式,则按指定的编码格式输出到浏览器上,如果没有指定,则默认按ISO-885Array-1编码发送到客户的浏览器上。

D、Java程序和数据库之间

对于几乎所有数据库的JDBC驱动程序,默认的在Java程序和数据库之间传递数据都是以ISO-885Array-1为默认编码格式的,所以,我们的程序在向数据库内存储包含中文的数据时,JDBC首先是把程序内部的UNICODE编码格式的数据转化为ISO-885Array-1的格式,然后传递到数据库中,在数据库保存数据时,它默认即以ISO-885Array-1保存,所以,这是为什么我们常常在数据

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1