JSP 中文问题完全解决方案

来源:互联网 发布:显示数据库字符集 编辑:程序博客网 时间:2024/06/12 18:27

        

在Java 开发中,中文乱码是一个最让人头疼的问题,如果不对中文做特殊的编码处理,这些中文字符就会变成乱码或者是问号。而在不同情况下对这些乱码的处理方法又各不相同,这就导致很多初学者对中文乱码问题束手无策。其实造成这种问题的根本原因是Java 中才用的默认编码方式是Unicode,而中文的编码方式一般情况是GB2312,因为编码格式的不同,导致在中文不能正常显示。

对于中文乱码问题,在不同的JDK 版本和不同的应用服务器中的处理方法是不同的。但是其本质上都是一样的,就是把中文字符转化成合适的编码方式,或者是把在显示中文的环境中声名采用GB2312的编码。统一编码方案之后自然可以正常显示。

在接下来的章节中,将对JSP 开发过程中的中文乱码问题进行详细的介绍,对各种乱码提供对应的解决方法,在各种编码方案中,UTF-8、GBK、GB2312 都是支持中文显示的,在本章中我们统一采用GB2312 的编码格式来支持中文。


JSP 页面中文乱码

在JSP 页面中,中文显示乱码有两种情况:一种是HTML 中的中文乱码,另一中是在JSP 中动态
输出的中文乱码。下面来看这样一个JSP 程序。
//--------文件名:PageCharset.jsp--------------------
<%@ page language="java" import="java.util.*"%>
<html>
<head>
<title>中文显示示例</title>
</head>
<body>
这是一个中文显示示例:
<%
out.print("这里是用JSP 输出的中文。");
%>
</body>
</html>
上面这个JSP 程序看起来好像是在页面显示几句中文,而且标题栏也是中文,但是在浏览器中的运行结果却如图所示。


显然,图中所示并非我们预期的效果,在我们JSP 源代码中清清楚楚看到的是中文,在这里为什么就成了乱码,造成这种原因的可能就是出在浏览器端的字符显示设置上,所以我们可以把上面的程序进行如下改进。
<%@ page language="java" import="java.util.*"%>
在上面这行代码中件就是对整个页面的起作用的page 指令,我们可以在这个指令中间设置支持中文显示的编码方式,具体修改方法如下所示。
<%@ page language="java" import="java.util.*"contentType="text/html;charset=gb2312"%>
上面这行代码中,向page 指令中添加了页面内容和显示方式的设置,其中采用gb2312 的编码方式来显示HTML 页面的内容,所以中文可以正常显示,改进以后的程序运行效果如图 所示。



URL 传递参数中文乱码

在一般情况下,可以用类似http://localhost:8080/chapt4/URLCharset.jsp?param='中文'这种形式来传递参数,而且HTML 在处理表单的时候,当表单的method 采用get 方法的时候,传递参数的形式与URL传递参数的形式基本一样。下面就是采用URL 传递参数的一个示例程序。
//--------文件名:URLCharset.jsp--------------------
<%@ page language="java" import="java.util.*" contentType="text/html;charset=gb2312"%>
<html>
<head>
<title>URL 传递参数中文处理示例</title>
</head>
<%
String param = request.getParameter("param");
%>
<body>
<a href="URLCharset.jsp?param='中文'">请单击这个链接</a><br>
你提交的参数为:<%=param%>
</body>
</html>
上面这个JSP 程序的功能就是通过一个URL 链接向自身传递一个参数,这个参数是中文字符串,这个程序的运行效果如图 所示。


上图所示的界面中单击链接,可以得到如下图所示的运行效果。


对于URL 传递中文参数乱码这个问题,其处理方法比较独特,仅仅转换这个中文字符串的编码,或者设施JSP 页面显示编码都是不能解决问题的。在这里需要多Tomcat 服务器的配置文件进行修改才可以解决问题。在这里需要修改Tomcat 的conf 目录下的server.xml 配置文件。具体修改方法如下。
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100"
debug="0" connectionTimeout="20000"
disableUploadTimeout="true" />
在上面的这段代码中间添加URl 编码的设置即可,即在 port="8080" 后面添加URI 编码设置URIEncoding="gb2312" 即可。重新启动Tomcat 服务器,可以得到如图所示的界面。


注意:URL 中文乱码的处理方法比较特殊,后续章节中的转码和过滤器的方法对这个问题都不起作
用,这个问题的解决只有更改Tomcat 的配置文件。


表单提交中文乱码

对于表单中提交的数据,可以使用request.getParameter("")的方法获取。但是当表单中如果出现中文数据的时候就会出现乱码。请看下面这个简单的表单。
//--------文件名:FormCharset.jsp--------------------
<%@ page language="java" import="java.util.*" contentType="text/html;charset=gb2312"%>
<html>
<head>
<title>Form中文处理示例</title>
</head>
<body>
<font size="2">
下面是表单内容:
<form action="AcceptFormCharset.jsp" method="post">
用户名:<input type="text" name="userName" size="10"/>
密 码:<input type="password" name="password" size="10"/>
<input type="submit" value="提交">
</form>
</font>
</body>
</html>
在上面这个表单中,向AcceptFormCharset.jsp 这个页面提交两项数据,下面是AcceptFormCharset.jsp的内容。
//--------文件名:AcceptFormCharset.jsp--------------------
<%@ page language="java" import="java.util.*" contentType="text/html;charset=gb2312"%>
<html>
<head>
<title>Form中文处理示例</title>
</head>
<body>
<font size="2">
下面是表单提交以后用request 取到的表单数据:<br>
<%
out.println("表单输入userName 的值:"+request.getParameter("userName")+"<br>");
out.println("表单输入password 的值:"+request.getParameter("password")+"<br>");
%>
</font>
</body>
</html>
在上面这个程序中,如果表单中输入的内容没有中文,则可以正常显示,当输入的数据中有中文的时候,假如有如图 所示的数据输入。


在上面这个表单中,用户名的输入为中文字符,当提交这个表单的时候,就会得到如下图 所示的结果。


在上图所示的界面中可以清楚看到,输入的中文用户名在用request 取出以后全部变成了乱码,造成这个问题的原因是:在Tomcat 中,对于以POST 方法提交的表单采用的默认编码为ISO-8859-1,而这种编码格式不支持中文字符。对于这个问题,可以采用转换编码格式的方法来解决,现在对AcceptFormCharset.jsp 改造如下。
<%
out.println("表单输入userName 的值:"+request.getParameter("userName")+"<br>");
out.println("表单输入password 的值:"+request.getParameter("password")+"<br>");
%>
上面这两行是对表单数据的处理,可以在这里进行数据的转码,具体的转换编码的方法如下。
<%
String userName = request.getParameter("userName");
String password = request.getParameter("password");
out.println("表单输入userName 的值:"+new String(userName.getBytes("ISO-8859-1"),"gb2312")+"<br>");
out.println("表单输入password 的值:"+new String(password.getBytes("ISO-8859-1"),"gb2312")+"<br>");
%>
经过这样的转换编码以后,所有的中文输入都可以用request 对象正常取出。在上面这个程序中,new String(userName.getBytes("ISO-8859-1"),"gb2312")这句代码是转换编码格式的关键,先从ISO-8859-1格式的字符串中取出字节内容,然后再用gb2312 的编码格式重新构造一个新的字符串。这样就可以支持中文的表单输入的正常取值和显示。改进以后的程序运行结果如图 所示。


注意:new String(userName.getBytes("ISO-8859-1"),"gb2312")这个转码的方法中,是从编码格式为ISO-8859-1 的字符串中取出字节内容,然后转换成gb2312,如果原来字符的编码格式不是ISO-8859-1 的时候这个方法就失效。例如在下面的过滤器处理中,把所有的编码都改成了gb2312,这个时候如果再使用new String(userName.getBytes("ISO-8859-1"),"gb2312")这个方法进行转码就会发生错误。

经过上面的更改编码格式的处理,表单的中文输入乱码问题已经解决。但是同时暴露了另一个问题,在上面这个表单中,输入项只有两项,所以对每个输入项都进行编码的转化也不是很麻烦,但是试想一下,现在如果有一个很大的表单,表单的输入项有几十个之多,这个时候对每个输入项都进行转码就很麻烦了,同时,在一个应用系统中,表单的个数也是非常多的,那么对于每个表单都得做同样的转码处理,这样的重复工作是最让人头疼的。
在这种情况下,有一种比较简便的方法,那就是使用过滤器filter,过滤器的原理和使用方法在介绍servlet 的时候会做详细的介绍,在这里由于需要用它处理中文问题,提前知道基本的用法即可。过滤器的基本原理就是对于每一个用户请求,都必须经过过滤器的处理才能继续发送到目的页面,在JSP 中,以POST 方式提交的表单在本质上就是封装在request 对象中,而request 对象是必须要经过过滤器的处理的,所以,对于表单的中文问题来说,可以在filter 中对对所有的请求进行编码格式的处理,这样就不必在每个表单中都做转码处理,节省大量的时间和精力。
下面的代码就是中文处理过滤器的具体代码。
//--------文件名:SetCharacterEncodingFilter.java--------------------
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;
import javax.servlet.UnavailableException;
public class SetCharacterEncodingFilter implements Filter {
protected FilterConfig filterConfig;
protected String encodingName;
protected boolean enable;
public SetCharacterEncodingFilter() {
this.encodingName = "gb2312";
this.enable = false;
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
loadConfigParams();
}
private void loadConfigParams() {
this.encodingName = this.filterConfig.getInitParameter("encoding");
String strIgnoreFlag = this.filterConfig.getInitParameter("enable");
if (strIgnoreFlag.equalsIgnoreCase("true")) {
this.enable = true;
} else {
this.enable = false;
}
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if(this.enable) {
request.setCharacterEncoding(this.encodingName);
}
chain.doFilter(request, response);
}
public void destroy() {
}
}
filter 本质上就是一个servlet,如果这个servlet 要起作用的话就需要在web.xml 中进行配置,对于这个filter 可以在web.xml 中添加下面的内容。
<filter>
<filter-name>SetCharacterEncoding</filter-name>
<filter-class>
SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>gb2312</param-value>
</init-param>
<init-param>
<param-name>enable</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
经过这样的处理,所有的请求都会被转换成gb2312 的编码格式,这样表单中的中文输入就可以正常获取并显示,不必对每个输入项再做转换编码的处理。

注意:web.xml 是每个Web 应用系统必需的一个配置文件,在这里可以配置应用系统中的一些基本信息,还可以配置应用系统中的servlet 等。这个文件改动以后,需要重新启动Tomcat 以后才能生效。


数据库操作中文乱码

在建立数据库的时候,应该选择支持中文的编码格式,最好能和JSP 页面的编码格式保持一致,这样就可以尽可能减少数据库操作的中文乱码问题。同时在JDBC 连接数据库的时候可以使用类似下面这种形式的URL。
jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs;useUnicode=true;characterEncoding=gb2312在上面这行代码中,指定了访问数据所使用的编码策略。在这里我们选择的数据库驱动程序为微软提供的官方驱动,连接的数据库为SqlServer 2000 自带的pubs 数据库,选择的编码为gb2312。
上面所说的方法仅仅适用于创建数据库的时候已经选择支持中文的编码,但是当一个数据库已经创建,而且编码格式已经是ISO-8859-1 的时候,这种情况下通过重新创建数据库显然是不显示的,尤其是当数据库中已经有大量数据的时候,这时候用上面介绍的方法可以正常向数据库中写入中文数据,但是读出的数据格式是ISO-8859-1,如果有中文内容就会显示乱码。这时候只有在读取数据库的时候进行转码,使用的方法还是上一节中的转码方法,在这里把它整理成一个转码的函数。
public String encoder(String str) throws UnsupportedEncodingException
{
String result = new String(str.getBytes("ISO-ISO-8859-1"),"gb2312");
return result;
}
有了这个转码函数,在读取数据库的时候就可以使用encoder(rs.getString(“列名”)),这样取得中文字符串的内容就可以正常显示。


Eclipse 开发工具中JSP 文件中文不能保存

在Eclipse 中,JSP 文件默认的编码格式为ISO-8859-1,所以在JSP 代码中间如果出现中文就不能保存,像下面这段JSP 代码就不能保存。
<%@ page language="java" import="java.util.*" %>
<html>
<head>
<title>中文显示示例</title>
</head>
<body>
这是一个中文显示示例:
</body>
</html>

这段代码在保存的时候会有如图所示的提示。


对与这个问题,只要在JSP 页面中指明页面编码即可。
<%@ page language="java" import="java.util.*" %>
把上面这行代码添加支持中文的页面编码就能保存,具体代码如下所示。
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
其中 pageEncoding="gb2312"指明了JSP 页面编码采用gb2312,这样就可以正常保存JSP 的源文件。


Eclipse 开发工具中中文显示乱码

在Eclipse 中,由于默认的JSP 编码格式为ISO-8859-1,所以当打开由其他编辑器编辑的JSP 页面就会出现乱码,下面这个JSP 程序就是用UltraEdit 编辑的页面,中文完全可以显示。
<%@ page language="java" import="java.util.*"%>
<html>
<html>
<head>
<title>中文显示示例</title>
</head>
<body>
这是一个中文显示示例:
<%
out.print("这里是用JSP 输出的中文。");
%>
</body>
</html>
但是在Eclipse 中打开以后却成为下面这样。
<%@ page language="java" import="java.util.*"%>
<html>
<html>
<head>
<title>?D????¨º?¨º?¨¤y</title>
</head>
<body>
?a¨º?¨°????D????¨º?¨º?¨¤y¡êo
<%
out.print("?a¨¤?¨º?¨®?JSP¨º?3?¦Ì??D???¡ê");
%>
</body>
</html>
在上面这个JSP 中,所有的中文都变成乱码。造成这个问题的原因是两个编辑器保存源文件的编码格式不同,在UltraEdit 中可以支持中文,但是在Eclipse 中对JSP 文件的保存方式为ISO-8859-1,而这种编码格式对中文不支持,所以就出现了乱码的问题。
(1) 对于这个问题的解决方法是更改Eclipse 默认的编码方案。在Eclipse 中选择“Window”|“Preferences”会弹出如图所示的窗口。


(2) 在上面这个窗口中选择“General”|“Content Types”会切换到如图所示的界面。


(3) 在上面的窗口的右上部分,选择“Text”|“JSP”在上面窗口的右下部分就会出现各种JSP文件的列表,选择*.jsp,然后按照图设置,然后单击“Update”更新设置,最后重新启动Eclipse中文就可以在Eclipse 中正常显示。



JSP 下载中文文件名乱码

在实现文件下载功能的时候,如果出现中文文件名,如果不进行特殊的处理,下载下来的中文文件名会变成乱码,在下载前,就需要对这个文件名进行处理,然后才能正常显示中文的文件名,具体处理方法示例如下。
//--------文件名:FileNameCharset.jsp--------------------
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
<%@ page import="java.io.*" %>
<%
String fname = "中文";
OutputStream os = response.getOutputStream();//取得输出流
response.reset();//清空输出流
//下面是对中文文件名的处理
response.setCharacterEncoding("UTF-8");
fname = java.net.URLEncoder.encode(fname, "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename="+ new String(fname.getBytes("UTF-8"),
"gb2312") + ".xls");
response.setContentType("application/msexcel");//定义输出类型
os.close();
%>
<html>
<body>
</body>
</html>
经过上面的处理,下载下来的中文文件名称可以正常显示。



总之,在JSP 中出现中文乱码的问题,在不同的服务器中有不同的原因,但最根本的原因都是相通
的,那就是编码格式的冲突,只要知道使用的服务器采用的编码格式,然后再根据这个编码格式把中文
字符串转码即可。读者要在上面的这些例子中理解中文处理的关键所在,要做到以不变应万变。

0 0
原创粉丝点击