5.1.3 用HTTP响应消息头传输中文信息
使用HTTP响应头传递信息是一件非常“酷”的事。但遗憾的是,在传递中文时,会出现乱码问题。其实要解决这个问题也非常简单,只需要对要传输的中文进行编码,然后在接收它们的客户端再对其进行解码即可。
例子 : 用HTTP响应消息头传输中文信息
1. 实例说明
在本程序中通过HTTP响应消息头分别传输英文消息、中文消息和被编码后的中文消息(对中文消息的编码可以采用多种方式,在本例中采用了URL编码的方式,也就是使用java.net.URLEncoder.encode方法对中文消息进行编码),并在客户端使用Socket来访问该Servlet程序,并输出相应的中、英文消息。
2. 编写ChineseHeader类
ChineseHeader是一个Servlet类,负责向客户端发送HTTP响应消息,该类的实现代码如下:
public class ChineseHeader
{
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
// 设置英文响应消息头
response.addHeader("English", "information");
// 设置中文响应消息头
response.addHeader("Chinese", "中文头信息");
// 设置被编码的中文响应消息头
response.addHeader("NewChinese", java.net.URLEncoder.encode("中文头信息",
"utf-8"));
out.println("响应正文");
}
}
上面的代码向客户端输出了三个自定义的HTTP响应消息头字段:English、Chinese和NewChinese。其中English字段值是英文消息、Chinese字段值是未编码的中文消息,而NewChinese字段值是用UTF-8格式编码的中文消息。
ChineseHeader类的配置代码如下:
<servlet>
<servlet-name>ChineseHeader</servlet-name>
<servlet-class>chapter5.ChineseHeader</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ChineseHeader</servlet-name>
<url-pattern>/ChineseHeader</url-pattern>
</servlet-mapping>
3. 查看HTTP响应消息头
查看HTTP响应消息头的方法很多,如可以使用telnet或自己编写程序来获得HTTP响应消息头信息。但这些方式都需要编写程序,比较麻烦。因此,可以借助更简单的工具来完成这个工作。在本例中使用了一个叫“影音传送带”的下载工具。读者也可以使用其它的下载工具。
使用影音传送带下载如下的URL:
http://localhost:8080/demo/ChineseHeader
然后查看影音传送带的下载日志,如图5.1所示。
图5.1 查询HTTP响应消息头
图5.1中的黑框中的内容就是在服务端设置的三个自定义HTTP响应消息头。由此可以看出,English字段的值正常显示了,而Chinese和NewChinese字段的值并没有正常显示。其中Chinese字段的值是乱码,而NewChinese字段的值显示的是URL编码格式。其实这些编码就是“中文头消息”的UTF-8编码,要想获得正确的中文消息,必须要使用java.net.URLDecoder类对其解码。
从以上结果可以得出一个结论,使用setCharacterEncoding或其他方法设置字符集编码,并不会对HTTP响应消息头进行编码,而只会对响应正文进行编码。
4. 编写访问ChineseHeader的客户端程序(MyChineseHeader类)
MyChineseHeader类是一个控制台程序,在该类中通过java.net.Socket类来访问服务端程序,并对被编码的中文消息进行解码。MyChineseHeader类的实现代码如下:
package chapter5;
import java.net.*;
import java.io.*;
public class MyChineseHeader
{
public static void main(String[] args) throws Exception
{
Socket socket = new Socket("localhost", 8080);
OutputStream os = socket.getOutputStream();
java.io.OutputStreamWriter osw = new OutputStreamWriter(os);
// 向服务端发送HTTP请求消息(只有请求头)
osw.write("GET /demo/ChineseHeader HTTP/1.1\r\n");
osw.write("Host:localhost:8080\r\n");
osw.write("Connection:close\r\n\r\n");
osw.flush();
// 从服务端获得HTTP响应消息头
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String s = "";
String responseData = "";
// 按行读取HTTP响应消息头
while((s = br.readLine()) != null)
{
responseData += s + "\r\n";
}
responseData = java.net.URLDecoder.decode(responseData, "UTF-8");
System.out.println(responseData); // 输出解码后的HTTP响应头
is.close();
os.close();
}
}
在编写上面的代码时要注意的是在进行解码时,解码格式必须和服务端一致,也就是说decode方法和encode方法的第二个参数值必须是相同的编码格式,在本例中都是UTF-8。
5. 获得解码后的HTTP响应头信息
运行MyChineseHeader程序,在IDE的Console中将会输出如图5.2所示的HTTP响应消息头信息。 从图5.2输出的信息可以看出,NewChinese字段的值已经正确显示了。
图5.2 输出正常的HTTP响应头消息