【Servlet】会话管理基础

一句话描述“会话”:从你和你老师偶遇于某十字路口开始,到相互分离于该石子路口,你们之间的谈话内容(受训)可以称为一次会话!其中,你们都用个小本子记录下你们之间的谈话内容,你的记录为Cookie,你老师那里的记录为Session。

Table of Contents

什么是会话管理

Cookie技术

服务器将Cookie发送到浏览器

服务器接收浏览器携带Cookie的请求

Session技术

获得属于本客户端的session对象

向session中存取数据

session对象的生命周期


本文主要内容:

  • Cookie的相关操作(服务器发送客户端、从客户端接收)
  • Session的相关操作(服务器创建、存取、持久化)

什么是会话管理

一次会话:打开浏览器 -> 访问一些服务器内容 -> 关闭浏览器

定义:

  1. 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,称为一次会话
  2. 管理浏览器客户端 和 服务器端之间会话过程中产生的会话数据。
  3. 每一个请求者(或客户端、浏览器),对应一个会话(Session)对象。

为什么需要会话管理:

  1. HTTP是无意识、单向协议。
  2. 在一个会话结束后,HTTP协议本身并不能保存服务器端与客户端之间的通信内容。
  3. 理解:对于某个文件,我是根本不知道我以前有没有发过给你。如果服务器说我发过给你了,那证据就是Session;如果客户端说我发过给你了,那证据就是Cookie。

两大会话技术:

  • Cookie技术:会话数据保存在浏览器客户端。
  • Session技术:会话数据保存在服务器端。

Cookie技术

理解什么是Cookie:

  • 小饼干,其实是一份小数据;
  • 是服务器给客户端的,并且存储在客户端上的一份小数据;

应用场景:

  1. 自动登录;
  2. 浏览记录;

特性:

  • Cookie数据类型只能保存非中文字符串类型的。
  • 可以保存多个cookie,但是浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。

Cookie的主要内容(所需要学习的两个方面):

  • 第一,服务器端怎样将一个Cookie发送到客户端
  • 第二,服务器端怎样接收客户端携带的Cookie

服务器将Cookie发送到浏览器

核心:以响应头的形式发送给客户端。

  1. 构造Cookie对象
    • Cookie(java.lang.String name, java.lang.String value)
  2. 设置cookie
    • void setPath(java.lang.String uri):设置cookie的有效访问路径。有效路径指的是cookie的有效路径保存在哪里,那么浏览器在有效路径下访问服务器时就会带着cookie信息,否则不带cookie信息。
    • void setMaxAge(int seconds):设置cookie的有效时间,单位为秒。
      1. 正整数:表示cookie数据保存浏览器的缓存目录(硬盘中),数值表示保存的时间。
      2. 负整数:表示cookie数据保存浏览器的内存中。浏览器关闭cookie就丢失了!!
      3. 零:表示删除同名的cookie数据
      4. 注意:如果不设置持久化时间,cookie会存储在浏览器的内存中,浏览器关闭后cookie信息销毁(会话级别的cookie),如果设置持久化时间,cookie信息会被持久化到浏览器的磁盘文件里。
    • void setValue(java.lang.String newValue):设置cookie的值
    • cookie.setPath(String path):设置访问那些资源时,要带着这个Cookie
      1. 如果不设置携带路径,那么该cookie信息会在访问产生该cookie的web资源所在的路径都携带cookie信息
      2. cookie.setPath("/MyWeb/cookieServlet"):代表访问MyWeb中的cookieServlet时才携带cookie信息
      3. cookie.setPath("/"):代表访问整个web项目都携带cookie信息
  3. 发送cookie到浏览器端保存(是HttpServletResponse类方法调用)
    • void response.addCookie(Cookie cookie):发送cookie
  4. 服务器接收cookie(是HttpServletRequest类方法调用)
    • Cookie[] request.getCookies():接收cookie

服务器接收浏览器携带Cookie的请求

Cookie信息是以请求头的方式发送到服务器端。

  1. 通过request获得所有的Cookie:
    • Cookie[] cookies = request.getCookies();
  2. 遍历Cookie数组,通过Cookie的名称获得我们想要的Cookie
for(Cookie cookie : cookies) {
    if(cookie.getName().equal(cookieName)){
        String cookieValue = cookie.getValue();
    }
}

Google Chrome中查看Cookie

地址栏输入:chrome://settings/content/cookies è 点击“查看所有Cookie和网站数据”;

在地址栏左边的小锁上,点击,显示相关信息:

案例-显示用户上次访问的时间

编程思路:

  • 第一次访问:
    1. 获取当前时间,显示到浏览器中
    2. 创建Cookie对象,并把时间对象存储于Cookie中(取名为newest)
    3. 把Cookie发送到浏览器中
  • 第n次访问
    1. 获取Cookie中的数据(取出newest),得到上次的访问时间
    2. 显示上次的访问时间
    3. 获取当前时间,并把当前时间对象作为更新Cookie(重新存储于newest)
    4. 把更新后的Cookie发送到浏览器保存

例子-显示用户上次访问的时间
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

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

@WebServlet(
		urlPatterns= {"/cookie"},
		name="CookieUsage"
		)
public class CookieUsage extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=utf-8");
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		/*注意,上一句代码中有空格,Tomcat会抛异常:
		 	"An invalid character [32] was present in the Cookie value"
			但不影响程序的正常执行
		*/
		String currentTime = sdf.format(new Date());
		
		//从请求中获取Cookie
		Cookie[] cookies = req.getCookies();
		String lastTime = null; //最后访问时间
		
		//第n次访问
		if(cookies!=null) {
			for(Cookie ele:cookies) {
				if(ele.getName().equals("lastTime")) { //检查Cookie的KEY是否等于"lastTime"
					lastTime = ele.getValue();//上次访问的时间
					//1.把上次显示时间显示到浏览器
					resp.getWriter().write("欢迎回来,你上次访问的时间为:"+lastTime+",当前时间为:"+currentTime);
					//2.更新cookie
					ele.setValue(currentTime);
					ele.setMaxAge(1*30*24*60*60);
					//3.把更新后的cookie发送到浏览器
					resp.addCookie(ele);
					break;
				}
			}
		}
		
		//第1次访问:浏览器端没有Cookie,上次访问的时间也为空,则表明是第一次访问
		if(cookies==null || lastTime==null) {
			//1.显示时间到浏览器
			resp.getWriter().write("你是首次访问本站,当前时间为:"+currentTime);
			//2.创建Cookie对象
			Cookie cookie = new Cookie("lastTime", currentTime);
			cookie.setMaxAge(1*30*24*60*60);//保存一个月,参数的单位是秒;
			cookie.setPath(req.getContextPath()+"/");
			//3.把Cookie发送到浏览器
			resp.addCookie(cookie);
		}
		
	}

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

//访问:http://localhost:8080/K-Servlet/cookie
//刷新即可查看效果

Session技术

Session技术的诞生是为了解决Cookie的局限:

  1. Cookie只能存字符串类型。不能保存对象
  2. 只能存非中文。
  3. 1个Cookie的容量不超过4KB。如果要保存非字符串,超过4kb内容,只能使用session技术!

Session技术核心:

  1. 会话数据保存在服务器端。(内存中)
  2. 会为每个客户端都创建一块内存空间存储客户的数据,但客户端需要每次都携带一个标识ID去服务器中寻找属于自己的内存空间。
  3. 所以说Session的实现是基于Cookie,Session需要借助于Cookie存储客户的唯一性标识JSESSIONID。

Session的主要内容(所需要学习的三个方面):

  1. 怎样获得属于本客户端的session对象(内存区域);
  2. 怎样向session中存取数据(session也是一个域对象);
  3. session对象的生命周期

 

获得属于本客户端的session对象

创建或得到session对象(HttpSerssion是接口,没有构造方法):

HttpSession session = request.getSession(boolean create)

  1. 由于HttpSession是接口,故其返回或创建是用HttpServletRequest类下的方法;
  2. 功能:创建属于该客户端(会话)的私有的session区域
  3. 特性:
    1. 方法内部会判断 该客户端是否在服务器端已经存在session
    2. 如果该客户端在此服务器不存在session 那么就会创建一个新的session对象
    3. 如果该客户端在此服务器已经存在session 获得已经存在的该session返回

向session中存取数据

保存会话数据到session对象(域对象):

  1. void setAttribute(java.lang.String name, java.lang.Object value):保存数据,键值对的形式
  2. java.lang.Object getAttribute(java.lang.String name):获取数据,取其键
  3. void removeAttribute(java.lang.String name):清除数据,取其键
向session中存放数据
import java.io.IOException;
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 HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/* request.getSession()方法
		 * 功能:创建属于该客户端(会话)的私有的session区域
		 * 特性:
		 *   方法内部会判断 该客户端是否在服务器端已经存在session
		 *   如果该客户端在此服务器不存在session 那么就会创建一个新的session对象
		 *   如果该客户端在此服务器已经存在session 获得已经存在的该session返回
		 */
		HttpSession session = request.getSession();
		//向该session域对象中放置数据
		session.setAttribute("name", "jerry");
		String id = session.getId();//该session对象的编号id
		System.out.println("session的JSESSIONID: " + id);
	}

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

向session中拿取数据
import java.io.IOException;
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 HelloServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		/* request.getSession()方法
		 * 功能:创建属于该客户端(会话)的私有的session区域
		 * 特性:
		 *   方法内部会判断 该客户端是否在服务器端已经存在session
		 *   如果该客户端在此服务器不存在session 那么就会创建一个新的session对象
		 *   如果该客户端在此服务器已经存在session 获得已经存在的该session返回
		 */
		HttpSession session = request.getSession();
		
		//拿到session域对象中的数据
		String attr = (String)session.getAttribute("name");
	}

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

session对象的生命周期

session对象的生命周期方法:

  1. void setMaxInactiveInterval(int interval):设置session的有效时间
  2. void invalidate():销毁session对象

session作用范围:

  1. 默认在一次会话中,也就是说在,一次会话中任何资源公用一个session对象
  2. 面试题:浏览器关闭,session就销毁了? 不对

Session对象的生命周期:

  • 创建:当客户端第一次访问服务器时,也即第一次执行request.getSession()时创建;
  • 使用:
    1. 将SessionID存入Cookie中;
    2. 客户端再次请求时,request中将会含有sessionID和其他请求;
    3. 将request中的SessionID和服务器的Session比较,看是否为同一ID;
  • 销毁:
    1. 服务器(非正常)关闭时,因为session是存储在内存(RAM)中的;
    2. session过期/失效(默认30分钟);
    3. 手动销毁,调用invalidate()方法;

问题:时间的起算点 从何时开始计算30分钟?

  • 从不操作服务器端的资源开始计时
  • 可以在该个工程的web.xml中进行配置,在<web-app>标签下直接添加:

  • <session-config>
  •         <session-timeout>30</session-timeout>  单位分钟
  • </session-config>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值