【会话技术】
Ø 什么是会话:用户打开一个浏览器访问页面,访问网站的很多页面,访问完成后将浏览器关闭的过程称为是一次会话.
Ø 常见的会话技术:
* Cookie:将数据保存到客户端浏览器.
* Session:将数据保存到服务器端.
Ø 为什么使用会话技术?
* 私有的数据,购物信息数据保存在会话技术中.
参见图一和图二
Ø 使用会话技术:
【Cookie技术的使用】
Ø 向浏览器保存数据:
HttpServletResponse有一个方法:
* void addCookie(Cookie cookie);
Ø 获得浏览器带过来的Cookie:
HttpServletRequest有一个方法:
* Cookie[] getCookies();
Ø 创建一个Cookie对象:
* Cookie(String name,String value);
01_会话技术的概述
会话技术
会话可以简单理解为,一个用户打开一个浏览器,在同一个WEB应用上,点击多个超链接,访问多个WEB资源,
然后关闭浏览器,那这整个过程我们称之为一个会话
作用
会话技术可以保存用户在会话过程中所产生的数据
会话技术也可以让用户在同一个会话中实现数据的共享
想保存数据到购物车 不重要 个人私有
保存哪里 服务器? 数据库 淘宝 京东 不登录
编程最重要的域对象 域对象 临时存储数据
浏览器
可能会被清掉 服务器怎么知道浏览器里面有购物车数据 --每次访问服务器的时候把这个数据给带过去
服务器
占用空间 弄混 我怎么识别这个数据是谁的 我怎么让用户证明这个数据是他的
存在浏览器,主要问题是带来带去 存服务器主要问题是 我要识别这个数据是谁的
归根到底: 会话技术就是用来临时保存数据的
02_会话技术的分类
cookie
cookie是一种客户端技术,程序可以把每一个用户特有的数据,以响应头set-cookie发送给每一个用户的浏览器,那最终会以文件的形式保存在用户的硬盘上,
当用户再次使用浏览器来访问我们的WEB服务器,用户的浏览器会带上他特有的数据,而我们的程序所处理的则是来访用户特有的数据。
session
session是一种服务器技术,WEB服务器会在运行时为每一个用户的每一个会话创建一个其独享的HttpSession对象,
由于session对象是用户独享的,所以我们可以使用session对象来保存用户在一个会话过程中所产生的数据。
session对象也是一个域对象,范围是整个会话
注意:
cookie 把数据保存在用户的硬盘上
session 把数据保存在服务器的内存上
会话: 打开淘宝--浏览--关闭 一个会话
cookie
存在浏览器
1,服务器先创建出来
2,随着响应带到浏览器,然后浏览器做临时保存,保存完之后,下次请求在带回去
优点:减少服务器的压力,服务器内存可以少用一点
缺点:
1,换一个浏览器就获取不到
2,随时都会被清理,适合保存不重要的东西
3,带来带去,占用带宽,适合存小的东西,如果过大,用户等待的时候很长
4,数据传来传去, 不安全
总结: 不必要的,比较小的,不涉及安全性的内容,用cookie
session
存在服务器
session 就是一个域对象,(setAttribute getAttribute,removeAttribute),就是通过这个保存数据
03_记录用户上次访问时间分析 访问网站统计量
第一次访问
服务器端
判断是否有cookie信息,给出欢迎提示,记录本次访问时间
发送响应头
再次访问
服务器端
判断是否有cookie信息,显示上次访问时间,记录本次访问时间
发送响应头
对于cookie 需要关注
1,在服务器端怎么创建一个cookie//Cookie c = new Cookie("lastAccessTime",now);
2,如何把cookie响应到客户端 //response.addCookie(c);
3,在浏览器发送回来的时候,我们服务器端怎么获得这个cookie//Cookie[] cs = request.getCookies();
04_记录用户上次访问时间
1,拿到指定的cookie信息
2,判断是否为null
如果为null,给出提示信息
否则,获取上次的访问时间,并显示
3,获得当前的时间存在cookie当中,发到客户端
步骤;
//记录用户上次的访问时间
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
//获取cookie信息
Cookie[] cs = request.getCookies();
Cookie cookie = null;
if(cs != null) {
for (int i = 0; i < cs.length; i++) {
String name = cs[i].getName();
if("lastAccessTime".equals(name)) {
cookie = cs[i];
break;
}
}
}
//判断是否有上次的访问时间
if(cookie == null) {
//如果没有上次的访问时间,需要给出提示信息
out.println("欢迎第一次访问");
}
else {
//如果有上次的访问时间,需要获取上次的访问时间并显示
String value = cookie.getValue();
out.println("您上次的访问时间为:" + value);
}
//获取这次的访问时间(当前的系统时间)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String now = sdf.format(new Date());
//创建Cookie对象
Cookie c = new Cookie("lastAccessTime",now);
//记录用户这次的访问时间,并发送至客户端
response.addCookie(c);
05_封装获取Cookie对象的功能
/*
* 根据指定的cookie名称返回其对应的cookie对象
* 参数:
* 1.Cookie[]
* 2.cookie的名称
* 返回值:
* 1.如果查找到了想要的cookie对象,返回这个cookie对象
* 2.如果没有查找到想要的cookie对象,返回null
*
*/
public static Cookie getCookie(Cookie[] cs,String name) {
if(cs != null) {
for (int i = 0; i < cs.length; i++) {
String cookieName = cs[i].getName();
if(cookieName.equals(name)) {
//说明找到了想要的cookie对象
return cs[i];
}
}
}
return null;
}
07_Cookie的常用方法
构造方法
Cookie(String name,String value);
获取名称
String getName();
获取值
String getValue();
设置有效时间(过期时间)
void setMaxAge(int expiry)
设置路径
void setPath(String uri)//
当用户访问这个路径下的web资源,或者是这个路径下子路径的资源,他都会自动携带这个cookie
设置有效时间
cookie.setMaxAge(60 * 60 * 24);//有效期一天
cookie.setMaxAge(-1);//当浏览器关闭,会话结束后cookie会自动的被删除
cookie.setMaxAge(0);//cookie会立刻被删除
cookie.setMaxAge(Integer.MAX_VALUE);//最长的有效时间
设置路径
cookie.setPath("/myCookie");//cookie的默认路径是当前WEB应用的根路径
cookie.setPath(request.getContextPath());//推荐使用这个方法,比较灵活
08_记住用户名
经典的Cookie应用场景
LoginUIServlet 登录UI界面,只负责展示页面
LoginServlet 提交之后的跳转页面,负责处理逻辑判断
IndexServlet 登录成功之后的跳转页面
09_记住用户名2
LoginServlet 提交之后的跳转页面,负责处理逻辑判断
登录成功之后,根据记住用户名复选框的状态来设置Cookie
if ("1".equals(remember)) {
//需要记住用户名
//创建Cookie对象
Cookie cookie = new Cookie("username", username);
//设置cookie的有效时间
cookie.setMaxAge(Integer.MAX_VALUE);
//发送cookie至客户端
response.addCookie(cookie);
}else {
//不需要记住用户名
Cookie cookie = new Cookie("username", "");
cookie.setMaxAge(0);
response.addCookie(cookie);
}
LoginUIServlet 登录UI界面,只负责展示页面
获取cookie
Cookie[] cs = request.getCookies();
Cookie cookie = CookieUtils.getCookie(cs, "username");
String username = "";
String checked = "";
if (cookie != null) {
username = cookie.getValue();
checked = "checked = 'checked'";
}
填充数据
out.println("用户名:");
out.println("记住用户名");
10_session的概述
域对象
需要掌握
1,怎么获取session对象
2,什么时候用session对象
3,怎么存数据 取数据 销毁
WEB服务器可以为每一个来访的用户浏览器创建一个会话对象(session对象),
如果需要保存用户的数据,我们的程序可以把用户的数据保存在用户浏览器独享的session对象中,
如果用户再次的使用浏览器来访问其他的WEB资源,其他的WEB资源也可以通过session对象来获取这个用户的数据,以便为这个用户再次的服务
session对象由WEB服务器创建,我们可以通过请求对象的方法getSession()来获取。
cookie和session的区别
cookie
是一种客户端技术,有大小和数量的限制,把数据保存在客户端,所以相对的不安全
session
是一种服务器端技术,没有大小和数量的限制,把数据保存在服务器端,所以相对的安全
如何区分一个session是哪个用户的,这个才是最难
银行 开保险柜 给你钥匙
关键点: 这个钥匙,怎么给到客户 如何让客户每次来的时候都带上钥匙 用的cookie
所以某种意义上 session依赖于cookie id id存在cookie
11_session的实现原理
基于cookie
第一次调用 getSession方法 发现客户端没有session对象,就会创建一个新的session对象
并且把session对象id以Cookie的形式发给客户端
客户端再次访问服务器端(severlet),发现他带了一个sessionid,就会查找对应的session对象
如何获得session对象 直接调用 request.getSession() 一定返回一个session对象,我们就可以直接使用
getSession()细节
第一次来,没有携带jsessionid ,就创建一个新的session
第二次来,携带jsessionid ,根据这个jsessionid去查找对应的session,如果找到就直接返回
携带jsessionid,根据这个jsessionid找不到对应的session,重新创建一个session并返回
12_使用session对象实现数据的共享
//获取session对象,如果客户端没有对应的session对象,则创建新的session对象并返回
HttpSession session = request.getSession();
//设置数据
session.setAttribute("username", "wangwu");
//获取数据
session.getAttribute("username");
//删除数据
session.removeAttribute("username");
cookie --- 传输 --转码 session 存在服务器 不需要
一次会话的时候, 只需要登录一次,保证所有的页面都知道你登录
给一个标记
这个标记保存到哪里好
1,要求
实效性
安全
整个会话的页面都可以使用
存在session中
cookie 窃取
request 一次请求就没有
ServletContext每个人都有登录状态
13_使用session实现用户登陆(初始化数据)
用户类 User
模拟数据库 UserDB
14_使用session实现用户登陆(页面实现)
LoginUIServlet 登录界面
IndexUIServlet 首页
15_使用session实现用户登陆(核心功能实现)
用户登录功能(LoginServlet)
共享用户登录状态的功能
//用户名和密码正确,登陆成功后将用户名添加到session对象中
HttpSession session = request.getSession();
session.setAttribute("username", username);
//获取session对象
HttpSession session = request.getSession();
//获取用户的登陆状态
Object username = session.getAttribute("username");
16_使用session实现用户登陆(注销功能实现)
LogoutServlet 登出界面
//获取session对象
HttpSession session = request.getSession();
//删除数据,删除用户在session中的数据---不推荐
session.removeAttribute("username");
//销毁session对象
session.invalidate();
17_session对象的生命周期
一个对象从创建到销毁的整个过程
时间:
创建: 第一次调用getSession()创建Cookie对象
销毁: 1,超时 默认30分钟(从最后一次请求算起)
2,手动调用invalidate()方法
3,非正常关闭服务器
钝化
当我们使用正确的方式关闭tomcat,tomcat会把session对象以及session对象所存储的数据持久化到tomcat的work目录下,
以便tomcat再次启动的时候可以恢复这些数据
18_钝化的注意事项
钝化就是持久化 必须要实现序列化接口
cookie案例:
步骤分析:
【步骤一】:准备登陆的案例.
【步骤二】:在统计人数的Servlet中.判断是否是第一次访问.
【步骤三】:根据是否是第一次显示不同的信息,同时将当前的时候保存到Cookie中.
代码实现
public class CountServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
Integer count = (Integer) this.getServletContext().getAttribute("count");
// response.getWriter().println("现在网站被访问的次数为:"+count+"
");
/**
* 获得浏览器中带过来的所有的Cookie信息,从数组中查找有没有指定名称的Cookie
* 判断用户是否是第一次访问:(从数组中没有找到指定名称的Cookie)
* * 如果是第一次:显示欢迎,记录当前访问的时间存入到Cookie中.
* * 如果不是第一次:显示欢迎,上一次访问时间,同时记录当前访问的时间存入到Cookie中。
*/
// 获得浏览器带过来的所有的Cookie:
Cookie[] cookies = request.getCookies();
// 从数组中查找指定名称的Cookie:
Cookie cookie = CookieUtils.findCookie(cookies, "lastVisit");
// 判断是否是第一次:
if(cookie == null){
// 第一次访问
response.getWriter().println("您是第"+count+"位访客!");
}else{
// 不是第一次
Long l = Long.parseLong(cookie.getValue());
Date d = new Date(l);
response.getWriter().println("您是第"+count+"位访客! 上次访问时间是:"+d.toLocaleString());
}
// 创建一个Cookie对象:
Cookie c = new Cookie("lastVisit",""+System.currentTimeMillis());
// 保存到浏览器端:
response.addCookie(c);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
案例二:记录用户的商品浏览记录
需求:
在购物网站上浏览商品的信息,商家为了留住用户,记住之前浏览的一些商品.
1.3.2.2步骤分析:
【步骤一】:在登录完成后,显示商品列表页面.
【步骤二】:为商品列表页面做一些准备工作.
【步骤三】:点击某个商品,将商品ID传递一个Servlet.
【步骤四】:在Servlet中:判断是否是第一次浏览商品
【步骤五】:如果是第一次:将商品的ID存入到Cookie中即可.
【步骤六】:如果不是第一次:判断该商品是否已经浏览了.
【步骤七】:如果浏览器过.删除之前元素,将该元素添加到最前面.
【步骤八】:如果没有浏览过该商品.判断最大长度,没有超过限制,直接加到最前,如果已经超过限制,删除最后一个,将其插入到最前.
代码实现:
public class ProductServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/**
* * 接收商品id.
* * 接收从客户端带过来的所有Cookie.
* * 从Cookie的数组中查找指定名称的Cookie.
* * 判断是否是第一次浏览商品:
* * 第一次浏览商品
* * 直接将商品的ID存入到Cookie.
* * 将Cookie回写到浏览器.
* * 不是第一次浏览商品 1-2
* * 判断当前的商品是否已经在浏览记录.
* * 已经存在: 2-1 移除当前元素,将当前元素添加到最开始.
* * 没在浏览记录中:
* * 判断是否已经超过了最大长度:如果超过 2-1-3:删除最后一个 将当前元素添加到最前面.
* * 没有超过:直接将该元素添加到最前位置.
* * 将转换的id的值存入到Cookie,回写浏览器.
*/
// 接收id:
String id = request.getParameter("id");
// 获得所有的Cookie的信息:
Cookie[] cookies = request.getCookies();
// 判断是否是第一次:
Cookie cookie = CookieUtils.findCookie(cookies, "history");
if(cookie == null){
// 第一次浏览商品
Cookie c = new Cookie("history",id);
c.setPath("/day11");
c.setMaxAge(60*60*24*7);
response.addCookie(c);
}else{
// 不是第一次浏览
// 判断选择的商品是否已经在浏览记录中 2-1
String value = cookie.getValue();
String[] ids = value.split("-");
// 将数组变为集合:
LinkedList list = new LinkedList(Arrays.asList(ids));
if(list.contains(id)){
// 之前浏览过该商品
list.remove(id); // 1-2-3
list.addFirst(id);
}else{
// 没有浏览过该商品.
if(list.size() >=3 ){
// 超过3个
list.removeLast();
list.addFirst(id);
}else{
// 没到3个.
list.addFirst(id);
}
}
// 将list中的元素取出,使用-连接上保存到Cookie,写回浏览器.
StringBuffer sb = new StringBuffer();
for(String s:list){
sb.append(s).append("-");
}
String sValue = sb.toString().substring(0,sb.length()-1);
System.out.println(sValue);
// 存入到Cookie中
Cookie c = new Cookie("history",sValue);
c.setPath("/day11");
c.setMaxAge(60*60*24*7);
response.addCookie(c);
}
request.getRequestDispatcher("/demo2/product_info.htm").forward(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
删除持久性的Cookie:
public class ClearServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie cookie = new Cookie("history",null);
cookie.setPath("/day11");
cookie.setMaxAge(0);
response.addCookie(cookie);
response.sendRedirect("/day11/demo2/product_list.jsp");
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
Session案例:
需求:
查看某个商品详情的时候,添加到购物车.需要将商品添加到购物车.
【步骤一】:点击加入购物车提交到Servlet
【步骤二】:在Servlet将购物的商品存入到Session中.
【步骤三】:可以创建一个Map集合用于保存购物信息Map的key可以是商品的名称,Map的value是数量.
【步骤四】:在购物车页面中显示Map中的数据就可以.
public class CartServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 接收商品名称:
String name = new String(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8");
// 创建Map集合用于保存购物信息.Map Map的key是商品的名称 value是购买的数量.
Map map = (Map) request.getSession().getAttribute("cart");
if(map == null){
map = new LinkedHashMap();
}
// 判断购物车中是否已经买了该商品.
if(map.containsKey(name)){
// map中已经有该商品:// * 如果购物车中已经有该商品: 获得到Map中该商品的数量+1。 存回到Map集合中.
Integer count = map.get(name);
count++;
map.put(name, count);
}else{
// map中没有该商品.// * 如果购物车中没有改商品: 将商品添加到Map集合中 数量1.
map.put(name, 1);
}
// * 将Map集合保存到session中.
request.getSession().setAttribute("cart", map);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("继续购物 | 去结算
");
}
Session是域对象:
session何时创建和销毁?作用范围:
* 创建:服务器端第一次调用getSession()创建session.
* 销毁:三种情况销毁session:
* 1.session过期. 默认过期时间为30分钟.
* 2.非正常关闭服务器.如果正常关闭session序列化到硬盘.
* 3.手动调用session.invalidate();
* 作用范围:多次请求.(一次会话)
案例:进行一次性验证码的校验
1.5.1需求:
在登录的页面中,需要有一个验证码的校验.
【步骤一】:生成验证码,将生成验证码的随机的4个字母或数字保存到session中.
【步骤二】:在页面中输入验证码值,点提交.
【步骤三】:在Servlet中从表单中获得验证码从session中获得一个验证码.
【步骤四】:比对两个验证码值是否一致.
【步骤五】:将session中保存的验证码清空.
代码实现:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 校验验证码程序:
String code1 = request.getParameter("code");
String code2 = (String) request.getSession().getAttribute("code");
request.getSession().removeAttribute("code");
if(!code1.equalsIgnoreCase(code2)){
request.setAttribute("msg", "验证码输入错误!");
request.getRequestDispatcher("/demo2/login.jsp").forward(request, response);
return ;
}
...
}
使用JS控制图片切换: