5.3.3 读写Cookie信息与Cookie的中文问题
在一些Web应用程序中需要在客户端保存一些信息,如用户名等,以使在下次访问同一个Web程序时可以根据这些信息为用户提供方便,或作为其他的用途。这些信息是由一个key-value对组成。每一对这样的信息被称为一个Cookie。如有一些登录程序在下一次访问时,会自动将用户名显示在用户名文本框中,这就是通过Cookie实现的。
下面的例子演示了如何在Servlet中读、写Cookie信息。
例子 : 读写Cookie信息(包括英文和中文信息)
1. 实例说明
本程序通过WriteCookie和ReadCookie类来分别设置和读取Cookie信息。其中WriteCookie类设置了不同类型的Cookie,包括临时Cookie和永久Cookie。ReadCookie类在不同的情况下读取了这些Cookie信息,读者可以从中了解到不同类型Cookie的区别。
2. 编写WriteCookie类
package chapter5;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class WriteCookie extends HttpServlet
{
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// 临时Cookie
Cookie tempCookie = new Cookie("temp", "temporary cookie");
tempCookie.setMaxAge(-1); // 设为临时Cookie,-1是MaxAge的默认值
response.addCookie(tempCookie);
// 这个cookie不起作用
Cookie cookie = new Cookie("cookie", "deleted");
// Cookie的有效时间设为0,浏览器接收以Cookie后立即被删除
cookie.setMaxAge(0);
response.addCookie(cookie);
// 永久Cookie
// 由于永久Cookie的值是中文,所以需要对其进行编码
String chinese = java.net.URLEncoder.encode("将Cookie保存到硬盘上", "UTF-8");
Cookie persistentCookie = new Cookie("pCookie", chinese);
persistentCookie.setMaxAge(60 * 60 * 24); // 有效时间为1天
// 设置有效路径,设为“/”表示这个Cookie在整个站点都是有效的
persistentCookie.setPath("/");
response.addCookie(persistentCookie);
}
}
上面的代码分别建立了三种Cookie:临时Cookie、有效时间为0的Cookie和永久Cookie。其中临时Cookie只在当前的浏览器窗口有效。而将Cookie的有效时间设为0,则该Cookie不会起到任何作用,因为这种Cookie一到浏览器就会被立即删除。浏览器会将永久Cookie保存在本地硬盘上,对于这种Cookie,即使是在新的浏览器窗口,只要在Cookie的有效期内,该Cookie就会永远有效。
从上面的描述可以看出,Cookie的不同类型是根据有效时间的取值范围确定的,如下所示:
l Cookie有效时间 < 0:临时Cookie,只在当前浏览器窗口以及和该窗口处于同一个进程的窗口中有效。
2 Cookie有效时间 = 0:该Cookie会立即被浏览器删除。
3 Cookie有效时间 > 0:永久Cookie,在Cookie有效时间内有效。
3. 编写ReadCookie类
package chapter5;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ReadCookie extends HttpServlet
{
// 通过一个Cookie名获得Cookie对象,未找到指定名的Cookie对象,返回null
private Cookie getCookieValue(Cookie[] cookies, String name)
{
if (cookies != null)
{
for (Cookie c : cookies)
{
if (c.getName().equals(name))
return c;
}
}
return null;
}
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
// 获得临时Cookie ,getCookies方法获得一个保存了请求消息头中所有Cookie的数组
Cookie tempCookie = getCookieValue(request.getCookies(), "temp");
if (tempCookie != null)
out.println("临时Cookie值:" + tempCookie.getValue() + "<br/>");
else
out.println("临时Cookie值:null</br>");
// 这个Cookie永远不可能获得,因为它的MaxAge为0
Cookie cookie = getCookieValue(request.getCookies(), "cookie");
if (cookie != null)
out.println("cookie:" + cookie.getValue() + "<br/>");
else
out.println("cookie:null</br>");
// 获得永久Cookie
Cookie persistentCookie = getCookieValue(request.getCookies(), "pCookie");
if (persistentCookie != null)
// 对永久Cookie中保存的中文信息进行解码
out.println("persistentCookie:" + java.net.URLDecoder.decode(persistentCookie.getValue(), "UTF-8"));
else
out.println("persistentCookie:null!");
}
}
在上面的代码中分别读取了在WriteCookie类中设置的三个Cookie。由于HttpServletRequest接口中未提供通过Cookie名返回特定Cookie对象的方法,因此,在ReadCookie类中增加了一个getCookieValue方法,用于返回指定Cookie名的Cookie对象。
4. 配置WriteCookie和ReadCookie类
这两个类的配置代码如下:
<!-- 配置WriterCookie -->
<servlet>
<servlet-name>WriteCookie</servlet-name>
<servlet-class>chapter5.WriteCookie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WriteCookie</servlet-name>
<url-pattern>/WriteCookie</url-pattern>
</servlet-mapping>
<!-- 配置ReadCookie -->
<servlet>
<servlet-name>ReadCookie</servlet-name>
<servlet-class>chapter5.ReadCookie</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ReadCookie</servlet-name>
<url-pattern>/ReadCookie</url-pattern>
</servlet-mapping>
5. 在同一个浏览器窗口中测试
在浏览器地址栏中依次输入如下两个URL:
http://localhost:8080/demo/WriteCookie
http://localhost:8080/demo/ReadCookie
浏览器中显示的结果如图5.16所示。
图5.16 在同一个浏览器窗口读取Cookie值
实际上,在访问WriteCookie时,addCookie方法向HTTP响应消息头添加了如下的三个Set-Cookie字段:
Set-Cookie: temp="temporary cookie"
Set-Cookie: cookie=deleted; Expires=Thu, 01-Jan-1970 00:00:10 GMT
Set-Cookie:pCookie=%E5%B0%86Cookie%E4%BF%9D%E5%AD%98%E5%88%B0%E7%A1%AC%E7%9B%98%E4%B8%8A; Expires=Tue, 24-Jun-2008 14:43:23 GMT; Path=/
6. 在不同的浏览器窗口中测试
打开一个新的浏览器窗口,在浏览器地址栏中输入如下的URL:
http://localhost:8080/demo/ ReadCookie
浏览器中显示的结果如图5.17所示。
图5.17 在不同的浏览器窗口读取Cookie值
从上面的测试结果可以看出,在新的浏览器窗口中,并不存在这个临时Cookie,因此,临时Cookie的值为null。
7. 程序总结
在WriterCookie类中使用了setPath方法设置的Cookie有效路径。假设使用setPath设置的路径为“/path”,如果通过localhost访问Web资源。要想该Cookie有效,访问Web资源的URL的前半部分必须是“http://localhost:8080/path”。如下面的URL所指的Servlet可以访问这个Cookie:
http://localhost:8080/path/servlet/MyServlet
实际上,这个路径就相当于上下文路径,如果只想让某个Cookie在当前Web应用程序中有效,可以使用HttpServletRequest接口的getContextPath方法返回值来设置这个Cookie的有效路径。
在使用Cookie时,还有一点需要注意,由于Cookie只支持ISO-8859-1编码格式的字符,因此,不能直接向Cookie中写入中文,如果要让Cookie支持中文,需要将中文字符编码。如Base64编码、URL格式的UTF-8编码。在本例中采用的是URL格式的UTF-8编码。