会话管理

一、会话管理
1.1. 什么是会话
会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个 web 资源,然后关闭浏览器,整个过程称之为一个会话。

1.2. 会话过程中要解决的一些问题?
每个用户在使用浏览器与服务器进行会话的过程中,不可避免各自会产生一些数据,服务器要想办法为每个用户保存这些数据。
例如:多个用户点击超链接通过一个 servlet 各自购买了一个商品,服务器应该想办法把每一个用户购买的商品保存在各自的地方,以便于这些用户点结帐 servlet 时,结帐 servlet 可以得到用户各自购买的商品为用户结帐。
 
1.3. 保存会话数据的两种技术
1)Cookie
Cookie 是客户端技术,服务器把每个用户的数据以 cookie 的形式写给用户各自的浏览器。当用户使用浏览器再去访问服务器中的 web 资源时,就会带着各自的数据去。这样, web 资源处理的就是用户各自的数据了。
 
2)Session
Session 是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其独享的 session 对象,由于 session 为用户浏览器独享,所以用户在访问服务器的 web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问服务器中的其它 web 资源时,其它 web 资源再从用户各自的 session 中取出数据为用户服务。

二、Cookie 技术
2.1.Cookie API
Cookie 技术: 会话数据 保存在浏览器客户端中 。是会话技术中的一种。
1) 创建 Cookie 的对象(会话数据保存在 cookie 的对象,以键值对的形式保存会话数据)
Cookie(java.lang.String name, java.lang.String value)
2) 设置 Cookie 对象
void setPath(java.lang.String uri)  :设置访问路径,只有在该路径下访问才有效
void setMaxAge(int expiry):设置过期时间,单位是秒
3)  发送 Cookie 数据
response. addCookie(Cookie cookie):回写cookie给浏览器
4)  接收 cookie 数据
Cookie[] request.getCookies() :获取浏览器的所有cookie
5)获取cookie的key和value
cookie.getName():获取cookie的key
cookie.getValue():获取cookie的value

2.2.Cookie 的原理
1 )服务器创建 Cookie 对象,然后把会话数据保存在 cookie 对象中。
Cookie cookie = new Cookie("name","value")
2 )服务器把 cookie 信息保存在响应头中,随着响应信息发送给浏览器保存
response.addCookie(cookie);
  相当于响应头: Set-Cookie: name=eric
3 )浏览器得到 cookie 信息, 保存在浏览器中 ,然后下次访问时带着 cookie 信息访问服务器。
4 )浏览器带着 cookie 信息( cookie 放在请求头中)访问服务器
  相当于请求头: Cookie: name=eric
5 )服务器获得浏览器带过来的 cookie 信息
request.getCookies();
注意: cookie 信息是在服务器端创建,在浏览器端保存!

2.3.Cookie 会话细节
1)  void setPath(路径):
用于设置 Cookie 保存的有效路径。(在浏览器在有效路径下访问才会把 Cookie 信息带到服务器)
 
2)  void setMaxAge(整数)
设置 Cookie 有效时长 。在不访问 cookie 之后的 n 秒之后, cookie 信息就会丢失。
正整数 cookie 数据保存在浏览器的硬盘缓存目录中。 n 秒之后, cookie 就会丢失
负整数 cookie 数据保存在浏览器的内存中。关闭浏览器, cookie 就会丢失。(默认情况下)
:删除同名的 cookie 信息。 ( 注意: 要清除的 cookie 带有 path 属性,那么发送的清除 cookie 也要带上 path 属性;否则两个都不带 path 属性 )
 
3) 浏览器一般只允许存放 300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB。
 
4)  Cookie 保存的会话数据只能是字符串类型, 而且字符串不能包含中文。

2.4.【案例】显示用户上次访问的时间

package blog.csdn.net.web.cookie;

import java.io.IOException;
import java.util.Date;

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 AccessServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//设置编码
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//获取浏览器带来的所有cookie
		Cookie[] cookies = request.getCookies();
		//获取指定cookie
		Cookie lastTimeCookie = getLastTimeCookie("lastTime",cookies);
		if(null !=lastTimeCookie) {
			//获取cookie中保存的上次访问时间
			String lastTime = lastTimeCookie.getValue();
			response.getWriter().println("上次访问时间是:"+lastTime);
			//更新上次访问时间
			String newTime = new Date().toLocaleString();
			lastTimeCookie.setValue(newTime);
		}else {
			//创建cookie保存访问时间
			String newTime = new Date().toLocaleString();
			lastTimeCookie = new Cookie("lastTime",newTime);
			response.getWriter().println("第一次访问时间是:"+newTime);
		}
		//设置cookie的缓存时间为10s
		//lastTimeCookie.setMaxAge(10);
		
		//设置cookie的访问路径,只有在设置的路径下有效
		//lastTimeCookie.setPath("/access/hello");
		
		//回写cookie给浏览器
		response.addCookie(lastTimeCookie);
		
	}
	
	/**
	 * 获取指定的cookie
	 * @param name
	 * @param cookies
	 * @return
	 */
	private Cookie getLastTimeCookie(String name, Cookie[] cookies) {
		if(null !=cookies) {
			for(Cookie cookie : cookies) {
				if(name.equals(cookie.getName()))
					return cookie;
			}
		}
		return null;
	}

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

}
查看浏览器的cookie

会话管理_第1张图片

三、Session 技术
Session 技术的特点
1 )会话数据保存在服务器端(服务器的内存中,适合敏感数据)
2 )可以保存任何类型的数据(对象)
3session是依赖cookie来实现的

3.1.session API
1)  创建或者得到 Session 对象
  request.getSession();
  request.getSession(boolean);
 
2)  域对象相关的
  void setAttribute(java.lang.String name, java.lang.Object value): 保存数据
java.lang.Object getAttribute(java.lang.String name): 得到数据
void removeAttribute(java.lang.String name): 清除数据
 
3) 得到 session 编号
java.lang.String getId()  
 
4)  设置 session 对象的有效时长
  void setMaxInactiveInterval(int interval) :隔 n 秒之后不访问 session ,服务器会自动销毁这个 session 对象
  web.xml 文件中设置
分钟
 
5) 手动销毁 session 对象
void invalidate()  

3.2.session 的访问过程
火狐 1 id=101 ):
访问 Servlet request .getSession() , 保存会话数据(生产标记,服务器保存 id=101 ,把 id=101 发送给浏览器) ( 带着 id=101 的标记访问服务器 ) , 访问 Servlet , 得到会话数据,可以得到!!(服务器查询是否保存了 id=101 的数据)
 
  火狐 2 (没有 id=101 ):
访问 Servlet ,得到会话数据,不可以得到!!!

IE (没有 id=101 ):   
访问 Servlet ,得到会话数据,不可以得到!!!

3.3.Session 原理
HttpSession session = request.getSession();
1 )得到浏览器发送的 Cookie 标记(名: JSESSIONID ,值: id
举例: Cookie: JSESSIONID=6DD4E56CFA0222F55B9D49E7D9F4F655
2 )在服务器中查询是否有这个 id 值的 session 对象
2.1 如果可以找到对应 id ,那么就返回 session 对象
2.1 如果找不到对应的 id ,那么就会创建一个新的 session 对象,给 session 对象分配新的 id
-> 创建一个 Cookie 对象,名为: JSESSIONID ,值为新的 id
-> Cookie 值通过response.addCookie发送浏览器保存.
举例: Set-Cookie: JSESSIONID=6DD4E56CFA0222F55B9D49E7D9F4F655; Path=/servlet_all/
例如首次访问servlet,并调用 request.getSession(),会将Cookie发送给浏览器.
会话管理_第2张图片
再次访问时,浏览器会携带该cookie访问servlet
会话管理_第3张图片

结论 : JSESSIONID 在服务器中查找对应的 session 对象

3.4.Session生命周期
创建:第一次调用request. getSession ()时创建
销毁:
1)服务器非正常关闭
2)设置session超时
默认时间超时:30分钟 tomcat/conf/web.xml有配置
手动设置超时:setMaxInactiveInterval(int 秒)
3)手动干掉session
调用session.invalidate()


3.5. 【案例】使用session添加购物车
package blog.csdn.net.web.servlet;

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

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 Add2CarServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		//获取get请求的商品名,注意需要转码
		String name = new String(request.getParameter("name").getBytes("iso8859-1"),"utf-8");
		
		//获取session
		HttpSession session = request.getSession();
		
		//从session中获取购物车
		Map carMap = (Map) session.getAttribute("car");
		
		if(null ==carMap) {
			//购物车为空,则创建并添加当前商品
			carMap = new HashMap<>();
			carMap.put(name, 1);
		}else {
			//购物车不为空,则判断当前添加的商品是否存在
			if(carMap.containsKey(name)) {
				//存在则累加个数
				Integer count = carMap.get(name);
				carMap.put(name, ++count);
			}else {
				//不存在则添加
				carMap.put(name, 1);
			}
		}
		//将购物车重新保存到session中
		session.setAttribute("car", carMap);
		
		//重定向到购物车
		response.sendRedirect(request.getContextPath()+"/showcar.jsp");
	}

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

}

查看购物车

<%@page import="java.util.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




购物车



	
		
		<%
			//获取session中的购物车
			Map carMap = (Map) session.getAttribute("car");
			if(null == carMap){
				%>
					
				<%
			}else{
				for(String name : carMap.keySet()){
					%>
						
						
					<%
				}
			}
		%>
	
商品名称 商品数量
购物车空空如也
<%=name %> <%=carMap.get(name) %>

继续购物    清空购物车




你可能感兴趣的:(Servlet)