0
点赞
收藏
分享

微信扫一扫

Session&Cookie


一.会话

1.1概念

http协议是基于请求与响应的无状态协议,但是进行使用时,通常会进行多次的请求与响应,将多次的请求与响应当做一个会话(浏览器窗口没有关闭)

  • 是一个过程,用户打开浏览器浏览网页(对同一个服务器多次请求–响应),关闭浏览器,这个过程称为会话

1.2作用

以因为http协议不会保存客户端状态,所以需要使用会话技术进行客户端数据的存储

  • 每个用户与服务器交互,会产生一些数据,程序希望保存这些数据,就可以保存在会话对象中。

二.cookie

2.1概念

  • 是客户端的会话技术,默认cookie是保存在用户的浏览器上
  • 程序把用户的数据以cookie的形式写回到用户的浏览器上(响应头:set-cookie)
  • 当用户使用浏览器访问程序的时候,携带自己浏览器上的cookie(请求头:cookie)

2.2原理

  • cookie是服务器端创建,客户端保存(默认浏览器的缓存中)
  • cookie是基于http协议的
  • cookie可以在客户端与服务器端传递数据

当浏览器向服务器发送请求,服务根据请求处理后决定是否创建cookie,服务器创建cookie并设置cookie相关的信息(数据.地址.时效),并将其放置到响应头中,发送至浏览器,浏览器解析响应头获取cookie数据进行保存(浏览器允许存储cookie的情况下),当浏览器再次请求服务器时,根据存储时cookie设置的信息(地址:判断是否是设置的地址,时效:是否过期)判断是否携带cookie,将cookie放置到请求头中,发送给服务器,服务器接收后从请求头中解析cookie数据并使用.

2.3使用步骤

创建cookie对象并发送至客户端

方法

参数

备注

new Cookie(name,value);

name:存储cookie的名字 value:存储cookie的值

name与value都为字符串(最好不要使用中文)

response.addCookie(c1);

c1:在响应头中添加的cookie对象

该方法由响应对象提供

@WebServlet(name = "SetCookieServlet", value = "/set")
public class SetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //cookie由服务器创建 存储在客户端浏览器中

        //cookie在java中使用Cookie类创建的对象进行表示
        //当客户端浏览器请求服务 需要创建cookie时 创建Cookie对象
        //cookie只能存储字符串 并每个cookie都是一个键值对 对象
        //key与value都是字符串  不建议使用中文 如果使用中文在添加与获取时需要特殊操作
        Cookie c1=new Cookie("username","李四");
        Cookie c2=new Cookie("password","abcdef");

        //cookie通过响应发送至客户端
        response.addCookie(c1);
        response.addCookie(c2);
    }
}

当浏览器请求对应url后,服务器创建cookie对象并响应 存储在客户端 cookie响应结果如下

Session&Cookie_java

注意:在进行数据传输时会进行流的形式传输,如果数据是中文可能导致乱码问题(所以不建议使用中文作为数据)

Session&Cookie_servlet_02

客户端获取cookie后进行保存,当再次请求时会携带请求的缓存数据,如上图request cookies所示

获取请求中的cookie数据

方法

参数

备注

request.getCookies()


由request对象提供的获取请求头中cookie数组的方法

c.getName()


由cookie对象提供的,获取对应cookie对象name的方法

c.getValue()


由cookie对象提供的,获取对应cookie对象value的方法

c.getPath()


由cookie对象提供的,获取cookie携带请求url路径

c.getMaxAge()


由cookie对象提供的,获取cookie的存活时间

@WebServlet(name = "GetCookieServlet", value = "/get")
public class GetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //当客户端请求中携带了cookie数据 可以通过请求对象的方法获取cookie数组
        Cookie[] cookies = request.getCookies();
        //判断cookie是否为null
        if(cookies!=null){
            for (Cookie c:cookies) {
                //获取name与value
                System.out.println(c.getName()+"|"+c.getValue());
                //因为存储数据的编码与当前环境一致 所以在浏览器显示的中文乱码可以识别
            }
        }

    }
}

cookie中文数据的编码与解码

在进行cookie创建时,如果书写中文,在浏览器存储时可能出现乱码,所以可以先将其转换一定的编码后存储,获取后再解码(编码解码只不过是不想将中文直接显示.也可以理解为简单的加密)

  • URLEncoder.encode(“张三”, “UTF-8”);//编码
  • URLDecoder.decode(cookie.getValue(), “UTF-8”);//解码

//在创建cookie添加value时  将数据字符串编码后添加
        Cookie c1=new Cookie("username", URLEncoder.encode("张三", "UTF-8") );//编码 			 
	   //张三编码后=>%E5%BC%A0%E4%B8%89
	   //在获取cookie后进行解码 输出  
        URLDecoder.decode(c.getValue(), "UTF-8");//解码

该编码与解码方式使用的是中文在url地址栏进行传输时的编码方式

设置cookie的持久化时间

方法

参数

备注

c1.setMaxAge(min);

min:设置持久化时间 单位 :秒

如果不设置 或设置为任意负数 则为关闭浏览器失效

在创建cookie时,可以通过方法设置cookie的持久化时间,如果没有设置默认为-1(任意负数),时间为当前浏览器关闭前(有些浏览器不允许没有进行安全注册(备案)的服务器存储长时间的cookie,但是允许默认cookie的使用)

当关闭浏览器,再次请求时,cookie就会失效,不会携带cookie数据

Session&Cookie_数据_03

@WebServlet(name = "SetCookieServlet", value = "/set")
public class SetCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //在创建cookie添加value时  将数据字符串编码后添加
        Cookie c1=new Cookie("username", URLEncoder.encode("张三", "UTF-8") );//编码
        Cookie c2=new Cookie("password","abcdef");

        //设置cookie的持久化时间 单位秒
        c1.setMaxAge(60*5);

        //cookie通过响应发送至客户端
        response.addCookie(c1);
        response.addCookie(c2);
    }

Session&Cookie_客户端_04

当关闭浏览器 请求获取cookie地址,由于只设置了username的存活时间,所以password设置为默认浏览器关闭失效,所以重新打开浏览器请求只有username

Session&Cookie_客户端_05

设置cookie的访问路径

当创建cookie时可以设置cookie的访问路径(当前请求服务器对应路径时才会携带cookie,请求其他路径不会携带cookie)

方法

参数

备注

c1.setPath(url);

url:设置请求的路径

如果没有设置则当前服务器任意url都携带cookie

//设置cookie访问路径
        //只有请求当前服务器并且访问路径为指定路径时才携带cookie
        //如果没有设置 默认为/  请求当前服务器任意路径都会携带cookie
        c1.setPath("/get");

由于username设置了请求的url为get 所以请求set路径时不会携带cookie

Session&Cookie_java_06

由于设置了项目名称,所以请求的url前需要书写项目名称,所以uername还是不会携带

Session&Cookie_数据_07

当直接请求服务器地址/get时,就会携带对应的cookie

Session&Cookie_java_08

//cookie常用的path设置路径
		//1.默认路径/
		//只要请求的是当前的服务器 都会携带cookie(默认)	
		c1.setPath("/");
		//2.项目路径 /项目名
		//只要请求的url是指定项目下的url 都会携带cookie
		c1.setPath("/web0816")
        //3.服务路径 /项目名/服务名
        //只有请求指定服务时 才会携带cookie
        c1.setPath("/web0816/get")

删除cookie

cookie由服务器创建存储在客户端浏览器,所以不能通过方法直接删除,但是可以通过设置cookie的存活时间进行删除,也可以将value设置为空字符串

//清除Cookie
Cookie cookie = new Cookie("username", "");
//1:设置访问的路径path,  这里的Path必须和设置Cookie 的路径保持一致
cookie.setPath(request.getContextPath());
//2:设置存活时间
cookie.setMaxAge(0);
//3:将cookie发送到浏览器
response.addCookie(cookie);
//删除cookie就是将指定cookie存活时间设置为0让浏览器删除

2.4案例

显示上一次访问时间

public class LastTimeServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//通过request获取所有的cookie
		Cookie [] cks = req.getCookies();
		
		//定义cookie变量
		Cookie c = null;
		
		//判断cks是否为空
		if(cks != null){
			//遍历数组
			for (Cookie cookie : cks) {
				//查找名字是lasttime的cookie
				if(cookie.getName().equals("lasttime")){
					//找到了
					c = cookie;
					break;
				}
			}
		}
		//获取系统当前时间
		Date date = new Date();
		//判断c是否为空
		if(c == null){
			//用户是第一次访问
			c = new Cookie("lasttime", Long.toString(date.getTime()));
			
			//向客户端响应你好
			resp.getWriter().write("Hello");
		}else{
			//用户不是第一次访问
			String lasttime = c.getValue();
			
			//日期解析
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			
			String now = df.format(new Date(new Long(lasttime)));
			
			//响应到客户端
			resp.getWriter().write("你好上一次访问的时间是"+now);
			
			c.setMaxAge(10);
			
			//将当前系统时间写入到cookie中
			c.setValue(Long.toString(date.getTime()));
			
		}
		
		//将cookie写回浏览器
		resp.addCookie(c);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}
}

显示用户浏览历史记录

product_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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>Insert title here</title>

<style type="text/css">
	img{
		width:200px;
	}
</style>
</head>
<body>
<h2>商品列表</h2>
<div>
	<a href="/huihua/historyServlet?pid=1"><img alt="" src="./image/1.jpg"></a>
	
</div>
<div>
	<a href="/huihua/historyServlet?pid=2"><img alt="" src="./image/2.jpg"></a>
	
</div>
<div>
	<a href="/huihua/historyServlet?pid=3"><img alt="" src="./image/3.jpg"></a>
	
</div>
<div>
	<a href="/huihua/historyServlet?pid=4"><img alt="" src="./image/4.jpg"></a>
	
</div>

<h2>历史浏览记录</h2>

<%
Cookie [] ck = request.getCookies();

if(ck != null){
	for(Cookie cookie : ck){
		if(cookie.getName().equals("history")){
			String lishi = cookie.getValue();
			String [] goodsId = lishi.split("-");
			for(int i = 0;i<goodsId.length;i++){
			%>
			<img alt="" src="./image/<%=goodsId[i] %>.jpg">
			<%
			}
		}
	}
}
%>
</body>
</html>

HistoryServlet.java

package com.yh;

import java.io.IOException;

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

public class HistoryServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//获取商品pid
		String pid = req.getParameter("pid");
		//获取客户端发送的cookie
		Cookie[] cks = req.getCookies();
		//定义cookie
		Cookie cookie = null;
		//判断cks是否为空
		if(cks != null){
			//遍历数组,查找历史纪录的cookie
			for (Cookie c : cks) {
				if(c.getName().equals("history")){
					//历史纪录的cookie已经存在
					cookie = c;
				}
			}
		}
		if(cookie == null){
			//新建历史纪录cookie  "1-2-3-"
			cookie = new Cookie("history", pid+"-");
		}else{
			//获取cookie的值
			String lishi = cookie.getValue();
			//将字符串转StringBuilder
			StringBuilder sb = new StringBuilder(lishi);
			//在字符串中查找pid
			if(sb.indexOf(pid) != -1){
				//找到了
			}else{
				//没找到
				sb.insert(0, pid+"-");
			}
			lishi = sb.toString();
			cookie.setValue(lishi);
		}
		
		//写回浏览器
		resp.addCookie(cookie);
		//重定向商品列表
		resp.sendRedirect("/huihua/product_list.jsp");
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}
}

三.session

3.1概念

  • session是服务器端的技术
  • 服务器在运行时为每一个用户创建一个独享的session对象
  • 每个用户在访问服务器过程中,产生的数据可以放在session对象中
  • 每个用户需要保存个人的,每次访问服务器的时候,都携带个人的sessionid
  • session技术基于cookie,使用cookie传递sessionid。

3.2原理

Session&Cookie_服务器_09

session依赖于cookie保存sessionid,当客户端第一次请求服务器端时,服务器端根据需求判断是否需要创建存储会话数据的session对象(请求服务器可能不会直接创建session对象)。

如果需要创建session对象存储数据,那么在创建后获取创建session对象的id,在响应中添加对应的cookie存储并响应,当客户端再次请求时(没有关闭浏览器拥有sessionid缓存cookie),服务端获取请求携带的coolie数据中的sessionid获取存储对应会话的session对象并进行数据操作

注意:在客户端cookie中存储的id,只是一个标识,用于在请求时告诉服务器,应该从哪个sessio对象中获取数据,当浏览器关闭时,丢失的是在客户端浏览器存储的cookie对象,而在服务器中对应存储的session并没有丢失,而是达到最大存活时间后自动回收。

3.3 API

方法名

功能

备注

void setAttribute(String name, Object value)

向域对象存入值

Object getAttribute(String name)

域对象取值

void removeAttribute(String name)

域对象删除值

String getId()

session的空间有唯一的id值,获取该id值的。

void invalidate()

销毁session对象

3.4创建和销毁

创建

  • HttpSession session=request.getSession()
  • 该方法可以创建session的对象,但是也可以来获取到session对象
  • 根据cookie对象中是否有jsessionid的cookie,如果有,通过id值查找,找到了不用创建了,返回。如果没有找到,创建一个新的session对象。
  • session.setAttribute(‘数据’) 存储数据
  • session.getAttribute(‘对象’)
  • A90685673C053479D142FB92FB099BD1
  • A90685673C053479D142FB92FB099BD1
  • 12C54052AE2091B6FBBA46754F1B3D8D

销毁

  • 配置session的默认销毁时间,默认值是30分钟(在tomcat/conf/web.xml文件中设置了session默认超时时间)

<session-config>
	<session-timeout>30</session-timeout>
</session-config>

  • 关闭服务器销毁session
  • 非正常的原因关闭服务器,销毁session
  • 如果正常关闭服务器,session会被序列化到磁盘上。
  • 设置session最大的存活的时间
  • void setMaxInactiveInterval(int interval)
  • 直接使用方法,销毁session
  • invalidate()

3.5购物车案例

product_list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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>Insert title here</title>

<style type="text/css">
	img{
		width:200px;
		
	}
</style>
</head>
<body>
<h2>商品列表</h2>
<div>
	<img alt="" src="./image/1.jpg">
	<a href="./addCart?pid=1">添加到购物车</a>
</div>
<div>
	<img alt="" src="./image/2.jpg">
	<a href="./addCart?pid=2">添加到购物车</a>
</div>
<div>
	<img alt="" src="./image/3.jpg">
	<a href="./addCart?pid=3">添加到购物车</a>
</div>
<div>
	<img alt="" src="./image/4.jpg">
	<a href="./addCart?pid=4">添加到购物车</a>
</div>
</body>
</html>

AddCartServlet.java

package com.yh;

import java.io.IOException;
import java.util.HashMap;

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

public class AddCartServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {	//获取商品id
		String pid = req.getParameter("pid");
		//获取session  创建session
		HttpSession session = req.getSession();
		//获取session中的购物车信息
		Object o = session.getAttribute("cart");
		//判断o是否为空
		if(o == null){
			//第一次添加购物车
			//创建购物车
			HashMap<String, Integer> map = new HashMap<String, Integer>();
			//将商品放入购物车
			map.put(pid, 1);
			//将购物车放入session
			session.setAttribute("cart", map);
		}else{
			//不是第一次添加商品到购物车
			//判断购物车中是否包含当前pid
			HashMap<String, Integer> map = (HashMap<String,Integer>)o;
			if(map.containsKey(pid)){
				//获取当前商品的数量
				Integer count = map.get(pid);
				//数量+1
				count++;
				//将数量放入map集合
				map.put(pid, count);
			}else{
				//购物车不存在当前商品
				map.put(pid, 1);
			}
			
			System.out.println(map);
		}
		//跳转添加成功页面
		resp.sendRedirect("/huihua/addSucc.jsp");
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		doGet(req, resp);
	}
}

addCartSucc.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<h2>添加成功页面</h2>
<a href="./product_list.jsp">继续剁手</a>
<a href="./cart.jsp">结算</a>
</body>
</html>

cart.jsp

<%@page import="org.apache.jasper.tagplugins.jstl.core.ForTokens"%>
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.Set"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!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>Insert title here</title>
</head>
<body>
<h2>购物车页面</h2>
<c:choose>
	<c:when test="${empty sessionScope.cart }">
		没有数据
	</c:when>
	
	<c:otherwise>
		<c:forEach var ="good" items="${sessionScope.cart }">
			${good }
		</c:forEach>
	</c:otherwise>
</c:choose>
</body>
</html>

Cookie和Session的区别

从存储方式上比较

Cookie只能存储字符串,如果要存储非ASCII字符串还要对其编码; Session可以存储任何类型的数据,可以把Session看成是一个容器
cookie数据存放在客户的浏览器上,session数据放在服务器上;
单个cookie在客户端的限制是4K,就是说一个站点在客户端存放的COOKIE不能超过4K(不同浏览器不同);

从隐私安全上比较

Cookie存储在浏览器中,对客户端是可见的。信息容易泄露出去。如果使用Cookie,最好将Cookie加密
Session存储在服务器上,对客户端是透明的。不存在敏感信息泄露问题。

从有效期上比较

Cookie保存在硬盘中,只需要设置maxAge属性为比较大的正整数,即使关闭浏览器,Cookie还是存在的
Session的保存在服务器中,设置maxInactiveInterval属性值来确定Session的有效期。并且Session依赖于名为JSESSIONID的Cookie,该Cookie默认的maxAge属性为-1。如果关闭了浏览器,该Session虽然没有从服务器中消亡,但也就失效了。

从对服务器的负担比较

Session是保存在服务器的,每个用户都会产生一个Session,如果是并发访问的用户非常多,是不能使用Session的,Session会消耗大量的内存。
Cookie是保存在客户端的。不占用服务器的资源。像baidu这样的大型网站,一般都是使用Cookie来进行会话跟踪。

作业

1.完成购物车功能,添加查看购物清单方法,点击查看清单将相同物品数量进行展示

例如:购物车内物品[花生,瓜子,矿泉水,花生,矿泉水,瓜子,大碗面]

购物清单如下:

花生 x2

瓜子 x2

矿泉水 x2

大碗面 x1

2.书写代码,完成当前用户请求次数的限制(例如:许愿每个人只能许愿3次并记录)

在输入框输入信息并点击提交,服务器接受并保存,当保存数据达到上限,再次提交后会显示:已达最大提交次数

泄露出去。如果使用Cookie,最好将Cookie加密
Session存储在服务器上,对客户端是透明的。不存在敏感信息泄露问题。

从有效期上比较

Cookie保存在硬盘中,只需要设置maxAge属性为比较大的正整数,即使关闭浏览器,Cookie还是存在的
Session的保存在服务器中,设置maxInactiveInterval属性值来确定Session的有效期。并且Session依赖于名为JSESSIONID的Cookie,该Cookie默认的maxAge属性为-1。如果关闭了浏览器,该Session虽然没有从服务器中消亡,但也就失效了。

从对服务器的负担比较

Session是保存在服务器的,每个用户都会产生一个Session,如果是并发访问的用户非常多,是不能使用Session的,Session会消耗大量的内存。
Cookie是保存在客户端的。不占用服务器的资源。像baidu这样的大型网站,一般都是使用Cookie来进行会话跟踪。

作业

1.完成购物车功能,添加查看购物清单方法,点击查看清单将相同物品数量进行展示

例如:购物车内物品[花生,瓜子,矿泉水,花生,矿泉水,瓜子,大碗面]

购物清单如下:

花生 x2

瓜子 x2

矿泉水 x2

大碗面 x1

2.书写代码,完成当前用户请求次数的限制(例如:许愿每个人只能许愿3次并记录)

在输入框输入信息并点击提交,服务器接受并保存,当保存数据达到上限,再次提交后会显示:已达最大提交次数


举报

相关推荐

0 条评论