天宇的JAVA空间站


Java WEB开发中的中文乱码问题解决之终极之道 - JSP/SERVLET中文参数传递解决篇

08-02-29 21:13Update

LifevV.COM编辑部

本文对Java JSP/SERVLET开发中的比较常见的中文参数乱码 问题做一个透彻地分析,并试图通过范例帮助大家能轻松理解,同时给出中文参数乱码解决的几种方法。

我们在  Java WEB开发中的中文乱码问题解决之终极之道 - 概要篇  一文中 给出了解决Java WEB开发中的乱码问题应该遵守的基本原则。

本文对Java JSP/SERVLET开发中的比较常见的中文参数乱码 问题做一个透彻地分析,并试图通过范例帮助大家能轻松理解,同时给出中文参数乱码解决的几种方法。

本文所有范例以UTF-8为例。大家可以根据自己的情况加以替换。

在开始本文之前,假设本文的读者已经熟悉或了解以下技术:
- Java语法
- Web开发的基本概念
- Jsp
- Servlet
- 至少一种支持JSP/SERVLET的Web服务器(包括安装,运行)

浏览器/WEB服务器之间的参数传递原理分析



浏览器/WEB服务器之间的中文参数传递
1,表单(form)中文参数的传递方法。我们使用一个简单的范例说明表单提交时浏览器的对中文参数的处理。

SubmitAsia.html
<html>

<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>

<body>

<form method="get">
<input type="text" name="userName" id="userName"> <input type="submit" value="submit" />
</form>
</body>

</html>


使用任意浏览器打开该文件,在输入框内输入 “你好” 中文2字,然后按submit按钮,我们注意到浏览器的地址栏:
file:///C:/SubmitAsia.html?userName=%E4%BD%A0%E5%A5%BD

刚才输入“你好”二字,被转换为 %E4%BD%A0%E5%A5%BD 后被发往服务器。

这个 %E4%BD%A0%E5%A5%BD 是什么呢?

我们先使用一个Java程序来测试一下。如下:

EnDecoderUtil.java
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

public class EnDecoderUtil {
    public static void main(String []args) {
        try {
            String str = URLEncoder.encode("你好", "UTF-8");
            System.out.println(str);
            str = URLDecoder.decode(str, "UTF-8");
            System.out.println(str);

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
}


编译执行:
c:\>javac EnDecoderUtil.java

c:\>java EnDecoderUtil
%E4%BD%A0%E5%A5%BD
你好

我们发现,浏览器发送给服务器的“你好”中文参数跟使用java.net.URLEncoder.encode()方法编码后的值完全一样。

原来,浏览器在向服务器传递参数时,对于非数字,非英文的字符(比如中日韩文)时,会先将其加以变换(编码),再发送给服务器,服务器接收到这种格式的字符时,会将其反向编码,还原成原来的字符。


浏览器/WEB服务器之间的中文参数传递 过程模拟


为了帮助大家能更好地理解,我们使用下面的例子,该例通过联结的形式向Google服务器发送一个查询命令参数。
比如,我们通过Google查询“你好啊”,通过以下2种方法向Google服务器发送参数:

SubmitAsia2Google.html
<html>

<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>

<body>
方法1:<a href="http://www.google.com/search?q=你好啊">你好啊</a><br>
方法2:<a href="http://www.google.com/search?q=%E4%BD%A0%E5%A5%BD%E5%95%8A">你好啊</a>

</body>

</html>


使用任意浏览器打开该文件。

方法1:你好啊
方法2:你好啊

使用方法1时,Google的查询页面通常会显示乱码,方法2时显示完全正常。

通过这个例子,我们知道,为了让服务器能够正常接收中文参数,对HTML页面的中文参数一定要经过编码处理。
表单里的中文字符在提交时,浏览器已经替我们做了编码处理,但联结(<a href.../>)里的中文需要我们自己处理。

JSP页面联结的中文参数编码方法


JSP页面里的联结很多情况下是动态生成的,比如根据数据库里的数据的不同动态生成包含中文关键字的联结等等。

方法1:JSP里直接使用java.net.URLEncoder.encode()。例:
<a  href="some.jsp?key=<%=java.net.URLEncoder.encode("可能包含中文的参数","UTF-8")%>">联结</a>

方法2:Javabean使用java.net.URLEncoder.encode()
在Javabean里使用java.net.URLEncoder.encode()处理之后,JSP里加以引用。
<jsp:useBean id="someBean" class="Beans.SomeBean" 
             scope="request" />
...

<%
    String chars = myBean.getSomeProp();

    out.println("<a href=\"some.jsp?key=" + chars + ">联结</a>");
%>
...


方法3:使用自定义标签。
在自定义标签里使用java.net.URLEncoder.encode()方法处理。
关于自定义标签的具体方法,这里不做介绍。


JSP与SERVLET的连动


JSP经过上面的处理之后,最后输出的HTML页面联结已经可以正常向服务器传递中文参数了。

下面我们阐述一下Servlet里怎么接收/解析中文参数。

对于<a href="/someServlet?key=%E4%BD%A0%E5%A5%BD">你好</a>之类的联结,我们可以用下面的servlet来解析传递过来的中文参数。


GetAsiaCharServlet.java
import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GetAsiaCharServlet extends HttpServlet {
    
        
    @Override
    //redir?key=xxxx
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        String key = req.getParameter("key");
        
        key = new String(key.getBytes("ISO-8859-1", "utf-8"));
        
    System.out.println(keyword);
    //...

    //重定向处理
    //res.sendRedirect("http://www.google.com/search?q="+URLEncoder.encode(key, "utf-8"));
    }
}


我们注意到使用req.getParameter("key")得到参数后,还使用了new String(key.getBytes("ISO-8859-1", "utf-8"))把ISO-8859-1字符集形式转换成UTF-8形式。
为什么呢?因为iso-8859-1是Java中网络传输使用的标准字符集,req.getParameter("key")得到的还是ISO-8859-1字符集,所以要转换一下才不会是乱码。

最后,顺便提一下,采用servlet重定向时,也需要对包含中文文字的参数做特殊处理。
例如,SERVLET从HTML页面的联结接受参数,然后重新定向到Google搜索。
则可以在上面的GetAsiaCharServlet里加上如下处理:
res.sendRedirect("http://www.google.com/search?q="+URLEncoder.encode(key, "utf-8"));

也就是说,需要把参数取出来,转换,再重新使用URLEncoder.encode编码,这样就不会出现乱码现象。


相关文章


为了更好地理解本文,我们建议您也阅读下面给出的其他相关文章:
>  WEB开发里需要理解的几个基本概念
>  Java Servlet的实现方法步骤
>  Java WEB开发中的中文乱码问题解决之终极之道 - 概要篇
 
Copyright ©2006-2010 lifevv.com. All Rights Reserved
POWERED BY @pmplat.syboos.com