您的位置:首页 > 编程语言 > Java开发

深入浅出java中文问题(四)Web应用中的中文问题

2012-12-03 10:04 357 查看
Web应用中出现的中文问题可能是最常见的,也是网络上讨论得最多的java中文问题了,而这跟JSP(Servlet)技术在Web中的广泛应用有着紧密的联系。Web应用运行在一个分布式的环境中,服务端和客户端通过HTTP协议连接在一起,而数据交换的双方分别是Web容器和浏览器。这就是一个典型的B/S结构的分布式应用。Web容器的存在是Web应用跟一般的控制台程序最大的不同之处。在一般的控制台程序中,数据是直接交付给程序员进行处理的,这样程序员对数据格式的控制有很大的自由度,也比较直观。但是在Web应用中,来自客户端的数据是先交付给Web容器,Web容器处理过后再交给程序员的;输出时也同样要经过Web容器进行中转。在这个中转过程中,Web容器帮我们完成了很多基础而且繁琐的工作,但是也在一定程度上减弱了我们对数据控制的自由度。此时,我们只能通过配置Web容器或者在JSP(Servlet)文件中指定的方式来管理数据的编码方式。如果没有处理好这些配置,那么就会出现中文问题了。

解决Web应用中的中文问题,我们同样需要了解Web应用的运行过程,搞清楚哪个步骤会导致中文问题的出现,这才能有的放矢,一击即中。现在,用得比较多的Web容器是tomcat,而 tomcat的默认编码方式是ISO-8859-1,而不是系统的默认编码方式。很多的中文问题就是因为这个原因产生的。下面的描述都是基于tomcat环境的。

Servlet的编写和保存方式跟普通的.java源文件是一致的,当客户端请求该Servlet时,Web容器将相应的.class文件调入虚拟机中,运行,得到结果。

JSP是一种特殊的Servlet,当客户端请求某个JSP文件时,WEB容器调用JSP编译器,JSP编译器先查看JSP文件中是否设置有文件编码格式(使用pageEncoding 属性进行设置),如果JSP文件中没有设置JSP文件的编码格式,则JSP编译器调用JDK先把JSP文件用JVM默认的字符编码格式(也即WEB容器所在的操作系统的默认的file.encoding)转化为临时的Servlet类,然后再把它编译成UNICODE格式的class类,并保存在临时文件夹中。从这以后,JSP的运作方式就跟Servlet保持一致了。

值得注意的是,在部署的过程中,对于Servlet我们只需要编译过后的.class文件,但是对于JSP,我们却需要它的源文件,而这些源文件是在运行过程中由Web容器动态编译成.class文件的,因此我们必须通知Web容器我们的JSP文件是用什么编码方式保存的(使用指令 pageEncoding),而且我们JSP文件的实际保存方式必须与此相同。(一般的IDE都会自动实现这个功能,保证pageEncoding属性的值跟JSP文件的实际保存格式的一致性。但是如果你是用记事本等工具来编写的话就要自己注意了,很可能会出现pageEncoding="UTF-8",但是却按系统默认编码方式保存为GBK的,这样中文问题又来了)。

在Servlet的运作过程中,会收到来自客户端的数据或者向客户端输出数据,如果在这个过程中没有指定request和response的编码方式,Servlet会默认使用ISO-8859-1,而不是系统默认的编码方式。因此,如果输入或者输出的数据含有中文字符,但是程序中却没有指明编码方式,那么Web容器就会用ISO8859-1进行处理,这样就会出现中文问题了。

基于上述分析,我们在编写Web应用的时候可以进行以下处理,以防止中文问题的出现。

1、对于Servlet,我们在doGet和doPost方法中设置好输入和输出的编码方式。

//设置输入编码格式
request.setCharacterEncoding("UTF-8");
//设置输出编码格式
response.setContentType("text/html;charset=UTF-8");


2、在每个JSP文件中加入以下指令和语句,确保JSP文件的编码方式在不同的平台中都能够正确识别,同时正确处理相应的输入和输出。

<%@page pageEncoding="UTF-8"%>//设置页面编码格式

<%@page contentType="text/html;charset=UTF-8"%>//设置输出编码格式

<%request.setCharacterEncoding("UTF-8");%>//设置输入时编码格式
3、如果你嫌每个文件都这么携麻烦的话,用Filter吧。只在doFilter方法中设定好输入输出的编码方式就可以了。但是提醒一下,在这里设定ContentType对Servlet可以起作用,但是对于JSP是没有效果的,因为JSP页面已经隐含调用了getWriter方法,setContentType方法已经不起作用了。对于JSP,还是只有在页面上指定ContentType。
本来,经过上述几个步骤以后,关于JSP(Servlet)的中文问题也就解决了,但是如果你使用的Web容器是tomcat,并且版本在5.0以上,那么新问题又出来了:在处理输入数据过程中,tomcat在处理GET方法和POST方法时方式是不相同的。对于POST方法,经过上面的设置后,tomcat就十分顺从地按照设置的方式处理输入输出数据了。但是对于GET方法,tomcat却显得有点不可理喻,它根本不管我们在程序中request.setCharacterEncoding(encoding)的设置,而是一意孤行,使用ISO-8859-1进行解码,中文问题又出来了。

怎么办呢?不用怕,人民的力量是伟大的。首先,我们要清楚提交给GET方法处理的数据是浏览器按照URL参数的形式传递过去的。哪些数据会使用这种方式进行传递呢?

第一种,是程序员显示地将参数附加到连接的URL中,用以传递数据。如在JSP页面中有以下语句:

<%
String str = "数据";
%>
<a href="view.jsp?data=<%=str%>">点击传递数据</a>


在这种情况下,数据传递过去一定是乱码来的。我们必须先将数据进行URL编码,然后再附加再URL后面进行传递。Java中提供了URL编码相关编码和解码的类。如下:

<%
String data= "数据";
String encodedStr = java.net.URLEncoder.encode(data,"utf-8");
%>
<a href="view.jsp?data=<!---->">点击传递数据a>


第二种情况,是表单使用属性method设定为GET,这样,浏览器会按照当前页面的编码方式自动将表单中的数据编码成URL编码,然后通过URL参数的形式进行传递。

现在,数据是传递过去了,tomcat也收到了,它将怎么处理呢?

1、如果按照默认设置的话,它将按照ISO-8859-1进行解码。如果在数据接收jsp页面或者Servlet中直接使用的话,肯定是要出现乱码了。要解决这个问题,我们在接收处可以这样处理:

2、如果我们不想这么麻烦,每次都重新解码的话,我们可以通知tomcat一声。方法如下:打开tomcat的server.xml文件,在上面添上一句:

debug="0"
acceptCount="100"
connectionTimeout="20000"
disableUploadTimeout="true"
port="80"
redirectPort="8443"
enableLookups="false"
minSpareThreads="25"
maxSpareThreads="75"
maxThreads="150"
maxPostSize="0"
URIEncoding="UTF-8"


这样,tomcat就会自动按照UTF-8解码URL传递过来的数据,还中文的“真我本色”。但是这样的话,我们必须URL传递的数据都是使用UTF-8来编码的。

通过上面设置,java中文问题应该可以在web应用中退出江湖了。当然,Web应用一个很重要的组成部分是数据库,这里同样会出现中文问题,这部分内容将在后续的文章中描述。

转自http://dustin.iteye.com/blog/77553
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: