会话技术:
- 会话指的是客户端浏览器和服务端之间的度偶次请求和响应
- 当打开浏览器,访问网站地址后,会话开始,当关闭浏览器(或者到了过期时间),会话结束。就像打电话只要不挂电话就是一次会话。
会话过程中产生的数据可以通过会话技术Cookie
、Session
保存
会话管理作用:
最常见的就是购物车,登录成功后,把商品加入到购物车,此时我们无论再浏览什么商品,当点击购物车时,那些加入的商品都仍在购物车中,它是为我们共享数据用的,并且是在不同请求间实现数据共享。
什么时候用会话管理:
如果我们需要在多次请求间实现数据共享,就可以考虑使用会话管理技术。
会话管理分类:
客户端会话管理技术Cookie:
把共享的数据保存到客户端(也就是浏览器)。每次请求时,把会话信息带到服务器,从而实现多次请求的数据共享。
服务端会话管理技术Session:
本质仍是采用客户端会话管理技术,只不过保存到客户端的是一个特殊的标识,并且把要共享的数据保存到了服务端的内存对象中。每次请求时,把这个标识带到服务器端,然后使用这个标识,找到对应的内存空间,从而实现数据共享。
Cookie:
Cookie是客户端会话管理技术,
把共享的数据保存到客户端
(也就是浏览器)。每次请求时,把会话信息带到服务器,从而实现多次请求的数据共享
作用:
由客户端记录数据,可以保存客户浏览器访问网站的相关内容。从而在每次访问需要同一个内容时,先从本地缓存获取,使资源共享,提高效率。
Cookie的属性:
属性名称 | 属性作用 | 是否重要 |
---|---|---|
name | cookie的名称 | 必要属性 |
value | cookie的值(不能是中文) | 必要属性 |
path | cookie的路径 | 重要 |
domain | cookie的域名 | 重要 |
maxAge | cookie的生存时间 | 重要 |
version | cookie的版本号 | 不重要 |
comment | cookie的说明 | 不重要 |
Cookie的限制:
- 每个网站最多只能存20个cookie,大小不能超过4kb。
- 所有网站的cookie总数不超过300个。
- Cookie名称只能包含ASCCI码表中的字母,数字字符,不能包含逗号、分号、空格、不能以$开头
- Cookie的值不能是中文
存活限制:
- 负整数:当前会话结束浏览器关闭就立即清除Cookie
- 0:立即清除
- 正整数:以秒为单位设置存活时间
访问路径限制:
- 默认路径:取自第一次访问路径资源前缀,只要以这个路径开头就能访问
- 设置路径:setPath()方法设置指定路径
Cookie方法:
方法名 | 作用 |
---|---|
Cookie(String name,String value) | 构造方法创建对象 |
属性对应的get/set | 赋值和获取值 |
添加&获取:
返回值 | 方法名 | 说明 |
---|---|---|
void | addCookie(Cookie cookie) | 向客户端添加Cookie |
Cookie[] | getCookies() | 获取所有的Cookie |
演示:
@WebServlet("/cookieDemo")
public class CookieDemo extends HttpServlet {
/**cookie的路径访问,只要是以前缀开头的包括子级路径都可以获取到,反之获取不到比如:/cookieDemo,只要是是前面是/cookieDemo后面是子级的话获取路径也可以,前缀不是就获取不到
*/@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html; charset=UTF-8");// 响应信息PrintWriter printWriter = resp.getWriter();printWriter.write("最后访问时间:<br>");// 创建Cookie对象,记录最后访问时间Cookie cookie = new Cookie("time", System.currentTimeMillis() + "");// 设置最大存活时间,不设置会话结束cookie结束cookie.setMaxAge(3600);// 把Cookie对象添加到客户端resp.addCookie(cookie);// 获取CookieCookie[] cookies = req.getCookies();// 判断Cookie是不是和name的名字相同for (Cookie c : cookies) {if ("time".equals(c.getName())) {// 是的话根据名字获取值,然后转解析字符串String value = c.getValue();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// Long.parseLong()将一个字符串转换成数字printWriter.write(sdf.format(new Date(Long.parseLong(value))));}}}
}
Session:
- Session是服务端会话管理技术,是由服务端记录数据,本质仍是采用客户端会话管理技术,只不过保存到客户端的是一个特殊的标识,并且
把要共享的数据保存到了服务端
的内存对象中。每次请求时,把这个标识带到服务器端,然后使用这个标识,找到对应的内存空间,从而实现数据共享。也是四大域之一的会话域对象。- Session是Servlet规范中提供的一个接口。该接口的实现由Servlet规范的实现提供商提供,Tomcat服务器对Servlet规范进行了实现,用tomcat就不用管了。
- 同时,它也是Servlet规范中四大域对象之一的会话域对象。并且它也是用于实现数据共享的和应用域和请求域是有区别的。
域对象 | 作用范围 | 使用场景 |
---|---|---|
ServletContext | 整个应用范围 | 当前项目中需要数据共享时,可以使用此域对象 |
ServletRequest | 当前请求范围 | 在请求或者当前请求转发时需要数据共享可以使用此域对象 |
HttpSession | 会话返回 | 在当前会话范围中实现数据共享。它可以在多次请求中实现数据共享 |
常用方法:
返回值 | 方法名 | 说明 |
---|---|---|
void | setAttribute(String name,Object value) | 设置共享数据 |
Object | getAttribute(String name) | 获取共享数据 |
void | removeAttribute(String name) | 移除共享数据 |
String | getId() | 获取唯一标识名称 |
void | Invalidate() | 让session立即失效 |
HttpSession获取:
HttpSession接口表示一个会话,可以把 会话的共享数据保存到HttSession里
返回值 | 方法名 | 说明 |
---|---|---|
HttpSession | getSession() | 获取HttpSession对象 |
HttpSession | getSession(Boolean create) | 获取HttpSession对象,未获取到是否自动创建 |
HttpSession获取过程:
用户向服务器发送请求的时候,服务器会创建一个Session并加标识号,后面再请求的时候服务器就会根据唯一表示判断请求是哪个Session的
浏览器禁用Cookie:
解决方式:
- 通过弹框提示信息告诉用户(这个方式是大部分网站常用的)
- 访问时拼接Jsessionid标识,通过encodeURL()方法重写地址
钝化&活化:
- 钝化:序列化,把长时间不用但是没有到期的HttpSession进行序列化写到磁盘上
- 活化:正常状态
- 什么时候钝化:
- 当访问量很大,服务器会根据上一次访问时间排序,对长时间不使用但还没到期的HttpSession序列化当服务器重启的时候,为了保证HttpSession的数据也会序列化
但是httpSession的序列化是由服务器自动完成的,不需要实现什么。
演示:
通过第一个Servlet设置共享数据用户名,并能在第二个Servlet获取到。
设置数据
@WebServlet("/sessionDemo01")
public class SessionDemo01 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 获取请求的用户名String username = req.getParameter("username");// 2. 获取HttpSession的对象HttpSession session = req.getSession();System.out.println(session);System.out.println(session.getId());// 3. 将用户信息添加到共享数据中session.setAttribute("username", username);}
}
获取数据
@WebServlet("/sessionDemo02")
public class SessionDemo02 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 1. 获取HttpSession的对象,如果参数是false,获取不到的时候就不会创建新的CookieHttpSession session = req.getSession(false);System.out.println(session);System.out.println(session.getId());if (session == null) {resp.setContentType("text/html; charset=UTF-8");System.out.println("为了网站的正常访问,请不要禁止Cookie");}resp.getWriter().write("<a href='" + resp.encodeURL("http://localhost:8080/sessionDemo02") + "'>go SessionDemo02<a/>");// 2. 获取共享数据Object username = session.getAttribute("username");System.out.println(session);System.out.println(session.getId());// 3. 将数据响应到浏览器resp.getWriter().write(username + "");}
}