几个实用的例子——Cookie读写详解

Cookie简介

Cookie的引文原意是“点心”,它是在客户端访问Web服务器时,服务器在客户端硬盘上存放的信息,好像是服务器发送给客户的“点心”。服务器可以根据Cookie来跟踪客户状态,这对于需要区别客户的场合(如电子商务)特别有用。

当客户端首次请求访问服务器时,服务器先在客户端存放包含该客户的相关信息的Cookie,以后客户端每次请求访问服务器时,都会在HTTP请求数据中包含Cookie,服务器解析HTTP请求中的Cookie,就能由此获得关于客户的相关信息。

Cookie的运行机制是由HTTP协议规定的,多数Web服务器和浏览器都支持Cookie。Web服务器为了支持Cookie,需具备以下功能:

·在HTTP响应结果中添加Cookie数据。

·解析HTTP请求中的Cookie数据。

浏览器为了支持Cookie,需要具备以下功能:

·解析HTTP响应结果中的Cookie数据。

·把Cookie数据保存到本地硬盘。

·读取本地硬盘上的Cookie数据,把它添加到HTTP请求中。

Cookie操作

对Cookie的操作无外乎三部分:读、分析、写。

写Cookie

Cookie theCookie = new Cookie(“username” , “Tom”);

response.addCookie(theCookie);

当Servlet向客户端写Cookie时,还可以通过Cookie类的setMaxAge(intexpiry)方法来设置Cookie的有效期。参数expiry以秒为单位,它具有以下含义:

·如果expiry大于零,就指示浏览器在客户端硬盘上保存Cookie的时间为expriy秒。

·如果expiry等于零,就指示浏览器删除当前Cookie。

·如果expiry小于零,就指示浏览器不要把Cookie保存到客户端硬盘。Cookie仅仅存在于当前浏览器进程中,当浏览器进程关闭,Cookie也就消失。

Cookie默认的有效期为-1。对于来自客户端的Cookie,Servlet可以通过Cookie类的getMaxAge()方法来读取Cookie的有效期。

读取分析客户端Cookie

Cookie[] cookies = request.getCookies();

HttpServletRequest类的getCookies()方法返回一个Cookie数组,它包含了HTTP请求中的所有Cookie。如果在HTTP请求中没有任何Cookie,那么getCookies()方法返回null。

对于每个Cookie对象,可调用getName()方法来获得Cookie的名字,调用getValue()方法来获得Cookie的值。

Cookie的使用示例

示例1

先读取客户端的所有Cookie,把每个Cookie的名字、值和有效期打印出来,然后向客户端写一个Cookie。
public class CookieServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    int count = 0;
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		res.setContentType("text/plain");
		PrintWriter out = res.getWriter();
		Cookie[] cookies = req.getCookies();
		if(cookies != null){
			for(int i = 0 ; i < cookies.length ; i++){
				out.println("Cookie name:" + cookies[i].getName());
				out.println("Cookie value:" + cookies[i].getValue());
				out.println("Cookie maxAge:" + cookies[i].getMaxAge());
			}
		}else{
			out.println("No cookie.");
		}
		res.addCookie(new Cookie("cookieName" + count , "cookieValue" + count));
		count++;
	}
}

在web.xml文件中为CookieServlet映射的URL为“/cookie”,按照下面的步骤访问CookieServlet:

(1)           打开浏览器,第一次访问CookieServlet。由于浏览器端此时还不存在任何Cookie,因此CookieServlet向客户端返回“No cookie.”。

(2)           在同一个浏览器中第二次访问CookieServlet。在步骤一中CookieServlet已经向客户端写了一个Cookie:“cookieName0=cookieValue0”,因此在浏览器第二次发出的HTTP请求中包含了这个Cookie,CookieServlet读取该Cookie,并向客户端返回该Cookie的信息,在页面中显示的Cookie的有效期为-1,表示该Cookie仅存在于当前浏览器进程中,其他浏览器进程无法访问到这个Cookie。

(3)           在同一个浏览器中第三次访问CookieServlet。在步骤二中CookieServlet已经向浏览器写了一个Cookie:“cookieName1=cookieValue1”,CookieServlet向客户端返回步骤一及步骤二中生成的Cookie的信息。

(4)           再打开一个新的浏览器,从这个浏览器中第一次访问CookieServlet。由于这个浏览器客户端此时还不存在任何Cookie,因此CookieServlet向客户端返回“No cookie.”。

(5)           从第二个浏览器中第二次访问Servlet。在步骤四中CookieServlet向客户端写了一个Cookie:“cookieName3=cookieValue3”,因此CookieServlet向客户端返回该Cookie的信息。

示例2 对Cookie的修改和删除

先读取客户端的所有的Cookie,寻找名为username的cookie,然后判断,如果不存在就向客户端写入一个新的Cookie:“username=Tom”,且有效期为1小时;如果存在且值为Tom,将值改为Jack,如果存在且值为Jack,删除该Cookie。

protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		Cookie cookie = null;
		res.setContentType("text/plain");
		PrintWriter out = res.getWriter();
		Cookie[] cookies = req.getCookies();
		if(cookies != null){
			for(int i = 0 ; i < cookies.length ; i++){
				out.println("Cookie name:" + cookies[i].getName());
				out.println("Cookie value:" + cookies[i].getValue());
				if(cookies[i].getName().equals("username"))
					cookie = cookies[i];
			}
		}else{
			out.println("No cookie.");
		}

		if(cookie==null){
			cookie=new Cookie("username" , "Tom");
			cookie.setMaxAge(60*60);
			res.addCookie(cookie);
		}else if(cookie.getValue().equals("Tom")){
			cookie.setValue("Jack");
			res.addCookie(cookie);
		}else if(cookie.getValue().equals("Jack")){
			cookie.setMaxAge(0);
			res.addCookie(cookie);
		}
	}

(1)      打开浏览器,第一次访问Cookie1Servlet。由于浏览器端此时还不存在任何Cookie,因此Cookie1Servlet向客户端返回“No cookie.”。

(2)      在同一个浏览器中第二次访问Cookie1Servlet。在步骤一中Cookie1Servlet已经向浏览器端写了一个Cookie:“username=Tom”,浏览器在本次HTTP请求中包含了这个Cookie,Cookie1Servlet向客户端返回该Cookie的信息:

Cookie name:username

Cookie value:Tom

(3)      在同一个浏览器中第三次访问Cookie1Servlet。在步骤二中Cookie1Servlet已经把浏览器端的名为“username”的Cookie的值改为“Jack”,浏览器在本次HTTP请求中包含了这个Cookie,Cookie1Servlet向客户端返回修改后的Cookie的信息:

Cookie name:username

Cookie value:Jack

(4)      在同一个浏览器中第四次访问Cookie1Servlet。在步骤三中Cookie1Servlet已经把浏览器端的名“username”的Cookie的有效期设为“0”,浏览器在处理步骤三中的HTTP响应结果时会删除该Cookie。浏览器在本次HTTP请求中不包含任何Cookie信息,因此Cookie1Servlet向客户端返回“No cookie”。

(5)      再打开一个新的浏览器,访问Cookie1Servlet。在步骤四中Cookie1Servlet已经向浏览器端写了一个Cookie:“username=Tom”,它的有效期为1小时,因此浏览器会把它保存到硬盘,其他浏览器也能反问这个Cookie。新打开的浏览器在HTTP请求中包含了这个Cookie,Cookie1Servlet向客户端返回该Cookie的信息。

假定在Tomcat服务器A上有一个app1应用和一个app2应用,在Tomcat服务器B上有一个app3应用。用户会通过一个浏览器进程访问app1、app2、app3应用。

假定app1应用中的一个Web组件X在浏览器上保存了一个Cookie,当浏览器再次请求访问app1、app2和app3应用中的其他Web组件时,浏览器是否会把Cookie添加到HTTP请求中,从而让这些Web组件能够读取该Cookie呢?

在默认情况下,处于安全的原因,只有app1应用中的Web组件能读取该Cookie。如果希望改变Cookie的共享范围,那么app1应用中的Web组件X在写Cookie时,可以通过setPath(Stringpath)和setDodomain(String domain)方法来设置Cookie的path和domain属性。

(1)      让同一个Tomcat服务器A中的app1应用和app2应用共享Cookie。app1应用中的Web组件X的写Cookie的代码:

Cookie cookie = new Cookie(“username” , “Tom”);

cookie.setPath(“/”);

res.addCookie(cookie);

以上serPath()的参数为“/”,表示Tomcat服务器的根路径,因此同一个Tomcat服务器中的所有Web应用可以共享上述Cookie。

(2)      只能让Tomcat服务器A中的app2应用访问该Cookie。app1应用中的Web组件X的写Cookie的代码如下;

Cookie cookie = new Cookie(“username” , “Tom”);

cookie.setPath(“/app2/”);

res.addCookie(cookie);

以上setPath()的参数为“/app2/”,因此只有Tomcat服务器A中的app2应用可以访问该Cookie,app1应用也无法访问该Cookie。

(3)      只让Tomcat服务器A中的app1应用中的位于“/sub”子路径下的Web组件访问Cookie。app1中应用中的Web组件X的写Cookie代码:

Cookie cookie = new Cookie(“username” , “Tom”);

cookie.setPath(“/app1/sub”);

res.addCookie(cookie);

(4)      让Tomcat服务器B中的所有Web应用访问Cookie,假定Tomcat服务器B的域名为www.cat.com。app1应用中的Web组件X的写Cookie的代码:

Cookie cookie = new Cookie(“username” , “Tom”);

cookie.setDomain(“.cat.com”);

res.addCookie(cookie);

模拟taobao等网站的广告推广

类似的网站在客户浏览信息时,会将浏览历史数据保存在客户端,在下次客户打开网站时,向客户推广最近浏览过的商品信息。

页面中的每个连接代表一个商品分类,在点击连接时通过AddCookieServlet向客户端保存Cookie:“itemsNum:6923384801114”:

public class AddCookieServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		Cookie cookie = null;
		res.setContentType("text/html;charset=utf-8");
		PrintWriter out = res.getWriter();
		out.println("<html><head><title>商品列表</title></head><body><ul><li>");
		out.println("<a href=\"addCookie?itemNum=6923384801114\">服装</a></li><li>");
		out.println("<a href=\"addCookie?itemNum=6923384801113\">电器</a></li><li>");
		out.println("<a href=\"addCookie?itemNum=6923384801112\">礼品</a></li><li>");
		out.println("<a href=\"addCookie?itemNum=6923384801111\">娱乐</a></li></ul>");
		Cookie[] cookies = req.getCookies();
		if(cookies != null){
			for(int i = 0 ; i < cookies.length ; i++){
				if(cookies[i].getName().equals("itemsNum")){
					out.println("你可能需要:商品编号[" + cookies[i].getValue() + "]");
					cookie = cookies[i];
				}
			}
		}else{
			out.println("No cookie.");
		}

		String itemNum = req.getParameter("itemNum");
		if(itemNum!=null){
			cookie=cookie==null?new Cookie("itemsNum" , itemNum):cookie;
			cookie.setValue(itemNum);
			cookie.setMaxAge(60*60*24*7);
			res.addCookie(cookie);
		}
		out.println("</body></html>");
	}
}

打开浏览器访问http://localhost:8080/webdemo/addCookie。初始页面为:

点击其中的一个连接,然后再打开另一个浏览器或是关闭当前网页再打开上面的连接,发现页面会显示上次浏览的商品编号:

此类应用可以根据用户的使用,动态设置推广信息、客户个性化喜好等,还可以在逻辑中增加判断,查看客户隔了多长时间再次访问该网站。

使用Cookie模拟自动登录

用户登录一次后选择自动登录,在下次登录该网站时无需登录步骤,就可直接进入网页。

首先应该有一个过滤器判断用户是否设置了自动登录,如果设置了自动登录则从Cookie中读取数据直接登录,进入网站。创建过滤器,并注册到应用中:

public class LoginFilter implements Filter {
	public void init(FilterConfig fConfig) throws ServletException {}
	public void destroy() {}
	public void doFilter(ServletRequest reqest, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) reqest;
		HttpServletResponse res = (HttpServletResponse) response;
		if (!req.getRequestURI().endsWith("login.html")&&!req.getRequestURI().endsWith("loginServlet")) {
			HttpSession session = req.getSession();
			User sessionUser = (User) session.getAttribute("user");
			if (sessionUser == null) {
				Cookie[] cookies = req.getCookies();
				if (cookies != null) {
					for (int i = 0; i < cookies.length; i++) {
						if (cookies[i].getName().equals("login")) {
							String loginInfo = cookies[i].getValue();
							String[] infos = loginInfo.split("&", 2);
							String username = infos[0];
							String password = infos[1];
							User user = new User(username, password);
							session.setAttribute("user", user);
							chain.doFilter(req, res);
							return;
						}
					}
				}
				res.sendRedirect("login.html");
				return;
			}
		}
		chain.doFilter(reqest, response);
	}
}

在该过滤器中先从session中取user值,如果没有则判断该客户端是否有名为login的Cookie,如果有表示该用户设置了自动登录,且已经保存了登录信息(即已经登录过)则直接跳转到目标页面,如果以上条件都没有满足,则跳转至登录页面。web.xml文件中Filter的配置代码为:

<filter>
  	<filter-name>LoginFilter</filter-name>
  	<display-name>LoginFilter</display-name>
  	<filter-class>filter.LoginFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>LoginFilter</filter-name>
  	<url-pattern>*</url-pattern>
  </filter-mapping>

然后创建登录页面:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
	<form name = "loginForm" method="POST" action="loginServlet">
		<table>
			<tr>
				<td><div align="right">用户名:</div></td>
				<td><input type="text" name="username"></td>
			</tr>
			<tr>
				<td><div align="right">密码:</div></td>
				<td><input type="password" name="password"></td>
			</tr>
			<tr>
				<td><input type="checkbox" name="autoLogin">自动登录</td>
			</tr>
			<tr>
				<td><input type="submit" name="submit" value="登录"></td>
				<td><input type="reset" name="reset" value="重置"></td>
			</tr>
		</table>
	</form>
</body>
</html>

该登录页面请求Servlet,在Servlet中进行数据的校验等工作:

public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
		boolean auto = req.getParameter("autoLogin")!=null&&req.getParameter("autoLogin").equals("on")?true:false;
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		User user = new User(username , password);
		HttpSession session = req.getSession();
		session.setAttribute("user", user);
		Cookie cookie = null;
		Cookie[] cookies = req.getCookies();
		if(cookies !=null){
			for(int i = 0 ; i < cookies.length ; i++){
				if(cookies[i].getName().equals("login")){
					cookie = cookies[i];
					cookie.setValue(username + "&" + password);
				}
			}
		}
		if(cookie == null){
			cookie = new Cookie("login" , username + "&" + password);
		}
		if(auto){
			cookie.setMaxAge(60*60*24*7);
		}else{
			cookie.setMaxAge(0);
		}
		res.addCookie(cookie);
		res.sendRedirect("hello.jsp");
	}
}

在该Servlet中完成的工作是将用户信息保存至session并根据逻辑判断操作Cookie。登录成功后页面跳转至欢迎页面hello.jsp:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8" import="helloworld.bean.User"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>hello</title>
<%User user = (User)session.getAttribute("user"); %>
</head>
<body>
	<b>你好:<%=user.getUsername() %></b>
</body>
</html>

在保存用户信息时使用到一个简单的JavaBean:User。

以上就是该实验中用到的页面。按照以下步骤进行访问:

(1)          启动项目后,打开浏览器访问项目中的任意页面。如:http://localhost:8080/webdemo/hello.jsp,发现会被拦截到登录页面,输入登录信息,此时不勾选自动登录,点击登录,页面跳转至hello.jsp。

(2)          关闭浏览器再打开并访问http://localhost:8080/webdemo/hello.jsp,被拦截到登录页面。此时填写登录信息后勾选自动登录,登录成功后关闭浏览器。

(3)          打开同一浏览器,继续访问http://localhost:8080/webdemo/hello.jsp,此时发现没有被拦截,原因是上一步中向客户端写了一个Cookie,打开浏览器并访问时,程序读取到用户信息直接放入session,完成了自动登录的功能。

访问http://localhost:8080/webdemo/login.html.。此时不勾选自动登录,登录成功后,重复步骤一、二,自动登陆功能已经取消。

时间: 2024-08-28 12:38:48

几个实用的例子——Cookie读写详解的相关文章

C++文件读写详解(ofstream,ifstream,fstream)

c++bufferiosiostreamfilestream 目录(?)[+] 在看C++编程思想中,每个练习基本都是使用ofstream,ifstream,fstream,以前粗略知道其用法和含义,在看了几位大牛的博文后,进行整理和总结: 这里主要是讨论fstream的内容: [java] view plaincopyprint? #include <fstream> ofstream         //文件写操作 内存写入存储设备 ifstream         //文件读操作,存储设

cookie属性详解

cookie属性详解 在chrome控制台中的resources选项卡中可以看到cookie的信息. 一个域名下面可能存在着很多个cookie对象. name字段为一个cookie的名称. value字段为一个cookie的值. domain字段为可以访问此cookie的域名. 非顶级域名,如二级域名或者三级域名,设置的cookie的domain只能为顶级域名或者二级域名或者三级域名本身,不能设置其他二级域名的cookie,否则cookie无法生成. 顶级域名只能设置domain为顶级域名,不能

iOS开发——实用篇&amp;KVO与KVC详解

KVO与KVC详解 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC).键值监听(KVO)特性: 键值编码KVC 键值监听KVO 键值编码KVC 我们知道在C#中可以通过反射读写一个对象的属性,有时候这种方式特别方便,因为你可以利用字符串的方式去动态控制一个对象.其实由于ObjC的语言特性,你根部不必进行任何操作就可以进行属性的动态读写,这种方式就是Key Valu

DBCP2的使用例子和源码详解(包括JNDI和JTA支持的使用)

目录 简介 使用例子 需求 工程环境 主要步骤 创建项目 引入依赖 编写jdbc.prperties 获取连接池和获取连接 编写测试类 配置文件详解 数据库连接参数 连接池数据基本参数 连接检查参数 缓存语句 事务相关参数 连接泄漏回收参数 其他 源码分析 数据源创建 BasicDataSource.getConnection() BasicDataSource.createDataSource() 获取连接对象 PoolingDataSource.getConnection() Generic

HTTP Session、Cookie机制详解

一.什么是http session,有什么用 HTTP协议本身是无状态的,本身并不能支持服务端保存客户端的状态信息,于是,Web Server中引入了session的概念,用来保存客户端的状态信息. 这 里用一个形象的比喻来解释session的工作方式.假设Web Server是一个商场的存包处,HTTP Request是一个顾客,第一次来到存包处,管理员把顾客的物品存放在某一个柜子里面(这个柜子就相当于Session),然后把一个号码牌交给这个顾 客,作为取包凭证(这个号码牌就是Session

Session和Cookie对比详解

会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份. 1. Cookie机制 在程序中,会话跟踪是很重要的事情.理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆.例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话

C++文件读写详解

转自:http://blog.csdn.net/kingstar158/article/details/6859379 在看C++编程思想中,每个练习基本都是使用ofstream,ifstream,fstream,以前粗略知道其用法和含义,在看了几位大牛的博文后,进行整理和总结: 这里主要是讨论fstream的内容: 1 #include <fstream> 2 2.ofstream //文件写操作 内存写入存储设备 3 3.ifstream //文件读操作,存储设备读区到内存中 4 4.fs

关于登录记住密码使用cookie的详解

下面是我看的一篇文章引用过来,很易懂 设置cookie每个cookie都是一个名/值对,可以把下面这样一个字符串赋值给document.cookie:document.cookie="userId=828";如果要一次存储多个名/值对,可以使用分号加空格(; )隔开,例如:document.cookie="userId=828; userName=hulk";在cookie的名或值中不能使用分号(;).逗号(,).等号(=)以及空格.在cookie的名中做 到这点很

Session与Cookie的详解及如何实现Session共享

首先我们来说一说Cookie,Cookie实际是Web服务端与客户端彼此传递的一部分内容,内容是任意的,但要在允许的长度范围内(一般每个域名在30-70不等).客户端会将它保存在本地机器上(如IE会保存在本地的一个txt文件).由于客户端程序对其进行管理,过期的Cookie会自动删除,我们可以通过以下方式来设置cookie的过期时间: 默认cookies失效时间是直到关闭浏览器,也可以指定cookie过期时间 //首先说一下Cookie的创建和删除 // java Cookie cookie =