servlet05 会话技术 cookie session

1 会话技术
1.1 会话技术概述
1.1.1 什么是会话?
当为了实现某一个功能(购物), 浏览器和服务器之间可能会产生多次的请求和响应. 从浏览器访问服务器开始, 到最后访问服务器结束, 这期间产生的多次请求和响应加在一起就称之为是浏览器和服务器之间的一次会话.

1.1.2 如何保存会话中产生的数据
1.可以通过域对象来保存程序中产生的数据.
(1)request域对象可以保存数据, 但是会话一般是由多次请求和响应的, request域的作用范围仅仅是一次请求, 所以不适合保存在会话中产生的数据, request域作用范围太小了.
(2)ServletContext域对象可以保存整个WEB应用范围内的数据, 范围足够大, 但是正是由于范围太大, 所以在保存会话产生的数据时, 可能会导致混乱.
2.可以使用Cookie和Session来保存会话中产生的数据.
参见<<Cookie的工作原理>>图
参见<<Session的工作原理>>图
1.2 Cookie
1.2.1 Cookie保存数据的原理

Cookie是基于Set-Cookie响应头和Cookie请求头来保存会话中产生的数据.
浏览器请求服务器, 将需要保存的数据带给服务器, 服务器从请求中获取到要保存的数据, 再通过Set-Cookie响应头将数据再次带给浏览器, 让浏览器自己来保存.
浏览器再次去请求服务器时, 会在请求中通过Cookie请求头带着上次保存的数据, 服务器可以通过Cookie请求头获取上次发送浏览器的数据, 通过这种方式可以保存会话中产生的数据.
Cookie是将会话中产生的数据保存在了客户端, 是客户端技术. 每个客户端各自持有自己的数据, 需要时再带给服务器, 因此不会混乱!

1.2.2 Cookie的API介绍
1.如何创建Cookie对象
Cookie cookie = new Cookie(String name, String value);

2.如何将Cookie对象添加到响应中
response.addCookie(Cookie cookie) – 将指定的Cookie对象添加到响应中, 最后随响应发送给浏览器保存(底层还是通过set-Cookie响应头将Cookie值发送给浏览器)

3.如何获取请求中的Cookie信息
request.getCookies() – 返回请求中所有的Cookie对象组成的数组. 如果请求中没有任何Cookie信息, 该方法将会返回null.

4.setMaxAge方法 – 设置Cookie的最大生存时间
(1)如果不设置该方法,Cookie默认是会话级别的Cookie,是保存在浏览器的内存中. 随着浏览器的关闭, Cookie也会跟着销毁.
(2)如果设置了该方法,并且是一个有效的时间,Cookie将会以文件的形式保存在浏览器的临时文件夹中。

5.setPath方法 – 设置Cookie被带给服务器的路径
比如:发送Cookie的Servlet是CookieDemo2
CookieDemo2的访问路径为: http://localhost/day16/CookieDemo2
Cookie的path为: /day16/, 这样浏览器在访问/day16/和其子孙路径时将会带着Cookie
如果Cookie的path不是当前web应用的根路径(比如:不是/day16/,而是/day16/servlet/), 这样浏览器在访问day16下某些资源时将不会带着Cookie, 所以最好把Cookie的路径设置为当前WEB应用的根路径, 代码如下:
//设置Cookie的路径(确保浏览器在访问当前应用下任何一个资源时都可以带着Cookie)
String cp = request.getContextPath();
cookie.setPath(cp+"/");

6.如何删除Cookie
在Cookie的API中没有提供直接删除Cookie的方法.在这里我们可以通过向浏览器发送一个同名、同path的Cookie,并且将再次发送的Cookie生存时间设置为0, 由于浏览器是根据一个cookie的名字和Path来区分一个cookie, 因此我们后发的Cookie会覆盖之前的Cookie, 而后发的Cookie生存时间为0, 因此浏览器收到之后也会立即删除!!. 具体代码如下:
//创建一个同名的Cookie
Cookie cookie = new Cookie(“time”,"");
//指定相同的path
cookie.setPath(
request.getContextPath()+"/");
//指定Cookie的生存时间为0
cookie.setMaxAge(0);
//将Cookie添加到响应中发送给浏览器
response.addCookie(cookie);
response.getWriter().write(“Cookie Delete Success!!”);
7.Cookie的常用方法
(1)cookie.getName() – 获取Cookie的名字
(2)cookie.getValue() – 获取Cookie的值
(3)cookie.setValue() – 设置Cookie的值
(4)cookie.setMaxAge() – 设置Cookie的最大生存时间
(5)cookie.setPath() – 设置Cookie的路径

1.2.3 案例:在网页中显示上次访问时间
1.代码实现_1:
// 1.获取本次访问的时间.
String dateStr = new Date()
.toLocaleString();

// 2.将时间通过Set-Cookie响应头响应给浏览器
response.setHeader(“Set-Cookie”,
“time=” + dateStr);

// 3.获取上次访问的时间
String dateStr2 = request
.getHeader(“Cookie”);

// 4.将上次访问时间响应给浏览器并显示在窗口中
// 处理响应正文乱码
response.setContentType(
“text/html;charset=utf-8”);
if(dateStr2 != null){
response.getWriter().write(
"您上一次访问的时间为: "
+ dateStr2);
}else{
response.getWriter().write(
“您是第一次访问本网站…”);
}

2.代码实现_2:(通过Cookie的API实现)
// 0.处理响应正文乱码
response.setContentType(
“text/html;charset=utf-8”);

// 1.获取(记录)本次访问的时间
String dateStr = new Date()
.toLocaleString();

// 2.创建Cookie对象,将时间设置在Cookie对象中
Cookie cookie = new Cookie(“time”,
dateStr);
//设置Cookie最大存活时间
cookie.setMaxAge(360024365);
//设置Cookie的路径(确保浏览器在访问当
//前应用下任何一个资源时都可以带着Cookie)
String cp = request.getContextPath();
cookie.setPath(cp+"/");

// 3.将Cookie对象添加到响应中(发送给浏览器保存)
response.addCookie(cookie);

// 4.通过请求获取所有的Cookie对象组成的数组
Cookie[] cs = request.getCookies();
boolean flag = false;// 没有名称为time的cookie
if(cs != null){
for (Cookie c : cs) {
if (“time”.equals(c.getName())) {
response.getWriter().write(
"您上次访问的时间是: " + c
.getValue());
flag = true;
}
}
}

// 5.如果没有名称为time的Cookie, 则提示是第一次访问
if (!flag) {
response.getWriter()
.write(“您是第一次访问本网站…”);
}
1.3 Session
1.3.1 Session的工作原理

浏览器向服务器发送请求, 并将需要保存的数据带给服务器, 服务器首先会去内存中查看有没有为当前浏览器服务的session, 如果有就直接获取session, 将数据保存在session中; 如果没有session, 就创建一个session,再将数据保存在session中.
浏览器再次请求服务器时, 服务器也会再次去内存中查看有没有为当前浏览器服务的session, 如果有就直接获取session, 通过session取出上次保存的数据, 通过这种方式也可以保存会话中产生的数据.
session是将会话中产生的数据保存在服务器端, 是服务器端技术. 在服务器中每一个浏览器都会有一个对应的session来保存在各个浏览器的数据, 由于数据是包存在不同的session对象中, 因此也不会发生混乱.

1.3.2 案例: 模拟购物车案例
1.在当前WEB应用的根路径下创建一个sale.html网页

2.创建一个BuyServlet, 用于将商品信息加入购物车(session)

BuyServlet代码实现:

3.创建一个PayServlet, 对购物车中的商品进行结算

1.3.3 Session是一个域对象
1.session的创建(获取)
request.getSession();
request.getSession(true); – getSession方法没有参数或者传一个参数true功能是一样的: 如果服务器内部有为当前浏览器服务的session就直接拿过用, 如果没有就创建一个拿过来使用.
request.getSession(false); – 如果服务器内部有为当前浏览器服务的session就直接拿过用, 如果没有就返回null.

2.域对象: 如果一个对象具有一个可以被看见的范围(request, ServletContext), 利用该对象上的map可以在整个范围内实现数据的共享.
setAttribute(String name, Object value) – 将一个指定的属性添加到session域中
getAttribute(String name) – 通过属性的名称获取指定名称的属性
removeAttribute(String name) – 通过属性名称将指定名称的属性从域中删除
getAttributeNames() – 获取所有属性名称组成的枚举, 因此可以获取所有的属性名

生命周期: (1)创建: 当第一次调用request.getSession()方法时将会创建session对象.(2)销毁session分为三种情况:
a)超时销毁: 如果超过30分钟不操作session, session将会超时销毁.
在当前WEB应用的web.xml文件的根标签中可以修改session超时的时间, 修改如下:

1

b)自杀: 当调用session.invalidate()方法时会立即销毁session
c)意外身亡: 当服务器非正常关闭时, session会销毁! 当服务器正常关闭时, session将会以文件的形式保存在tomcat服务器work目录下, 比如:

这个过程叫做session的钝化; 当服务器再次启动时, 钝化着的session会再次恢复回来, 这个过程叫做session的活化.

作用范围:整个会话范围内

主要功能:在整个会话范围内实现数据的共享.

1.3.4 如何获取浏览器关闭之前的Session
在浏览器访问服务器时, 将需要保存的数据带给服务器, 服务器会创建一个session将数据保存在session中, 同时会为session分配一个独一无二的id, 在响应时将session的id以Cookie的形式发送给浏览器保存, 但是这个Cookie是一个会话级别的Cookie,只要浏览器已关闭, Cookie就会丢失.
如果Cookie丢失, sessionid也就丢失了, 再次打开浏览器访问服务器, 由于没有session的id, 之前的session也就找不到了, 所以服务器会重新为浏览器分配一个新的session, 新的session中没有之前的数据, 所有之前的数据也就获取不到了.
如果在浏览器关闭之后还能够获取到之前的Session.
在服务器第一次调用request.getSession方法(创建session)之后, 我们自己也可以像浏览器发送一个名称为JSESSIONID的Cookie, 值就是session的ID, 同时设置Cookie的path为当前WEB应用的根路径, 最后设置Cookie的最大生存时间.让Cookie能够保存在浏览器的临时文件夹中,即使浏览器关闭, Cookie也不会丢失. 也就意味着Session的id不会丢失, 再次打开浏览器, 也可以将Session的id带给服务器. 因此可以获取之前的数据.具体实现.
// 2.获取一个Session对象
HttpSession session = request.getSession();

// 创建一个Cookie --> 名字:JSESSIONID, 值:session.getId();
Cookie cookie = new Cookie(“JSESSIONID”, session.getId());

// 设置Cookie的path为: /day16/
cookie.setPath(request.getContextPath()+ “/”);

// 设置Cookie的MaxAge: 30分钟
cookie.setMaxAge(1800);

// 将Cookie添加到response中发送给浏览器
response.addCookie(cookie);
1.4 四大作用域的比较
1.servletContext
代表整个WEB应用的对象
生命周期: 当WEB应用被服务器加载时创建ServletContext对象
当WEB应用被服务器移出时销毁ServletContext对象
作用范围: 整个WEB应用范围内
主要功能: 在整个WEB应用范围内实现数据的共享
2.session
代表一次会话的对象
生命周期:在第一次调用request.getSession方法时创建sessio对象
销毁:(1)超时销毁(默认30分钟) (2)自杀(调用invalidate方法) (3)意外身亡
作用范围: 整个会话范围内
主要功能: 在整个会话范围内实现数据的共享
3.request
生命周期: 一次请求开始时创建request对象, 一次请求结束时销毁request对象.
作用范围: 整个请求链
主要功能: 在整个请求链中共享数据
4.pageContext
生命周期: 访问JSP开始时创建pageContext对象, 访问JSP结束时销毁pageContext对象
作用范围: 当前JSP中
主要功能: 在当前JSP中共享数据 隐式对象 可以调用上边三个以及剩余八大隐式对象(不太用这个)

相同点:(1)都是域对象 (2)都具有三个特征 (3)具有相同的方法来操作域中的属性

猜你喜欢

转载自blog.csdn.net/TomHaveNoCat/article/details/82911779