Cookie & Session

第一章 会话技术 

1.1 什么是会话

web会话可简单理解为:用户开一个浏览器,访问某一个web网站,在这个网站点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话.

它是指浏览器和服务器之间的多次请求和响应:
也就是说,从浏览器访问服务器开始,可以多次访问服务器资源,到浏览器关闭为止这段时间
产生的多次请求和响应,合起来就叫做浏览器和服务器之间的一次会话。

例如:

1. 打开浏览器
2. 访问京东, 此时 与京东网站 产生了会话
3. 访问京东的具体商品页面; 或 其他页面; 或访问了其他网站, 此时,一直会与京东网站保持着会话连接
4. 关闭浏览器, 此时 与京东网站的会话结束;

重写打开浏览器,再次访问京东, 这就是第二次会话了

Cookie & Session_第1张图片

1.2 为什么要使用会话技术?

会话技术用来解决的客户端与服务器之间的通信问题,通过会话技术可以让每个用户的数据以会话对象的形式存储,方便以后访问web资源的时候使用。    
举几个场景:
    场景一:
        A和B两个人在某购物网站登录账号后,A购物车添加了一个TinkPad键盘,
       而B添加一本《JAVAWEB开发内幕》,这些商品信息都会被记录下来,
       以便用户在结账的时候可以买到对应的商品。
    场景二:
       在论坛登陆的时候,很多时候会有⼀个⼩框框问你是否要⾃动登陆,当你下次登陆的时候就不⽤输⼊密码了。
   场景三:
        根据我以前浏览过的商品,猜我喜欢什么商品

Cookie & Session_第2张图片

1.3 保存会话技术有哪些

在当下的市场开发中,传统项目的会话管理分为两类,分别是:客户端会话管理技术和服务端会话管理技术。
什么是客户端会话管理技术?
   程序把每个用户的数据以某种形式写给用户各自的浏览器。当用户使用浏览器再访问服务器中的web资源时,
   就会带着各自的数据去。这样,web资源处理的就是用户各自的数据了。我们采用Cookie技术实现。
什么是服务端会话管理技术?
    用户使用浏览器访问服务器的时候,服务把用户的信息,以某种形式记录在服务器上,
   这样在访问的时候就能保证用户各自使用各自在服务器中的数据。我们采用Session技术实现。

1.4 Java Web开发中使用的会话技术

在客户端与服务器端交互的过程中,通常会产生一些数据, 为了保存会话过程中产生的数据,在Servlet技术中,提供了两个用于保存会话数据的对象,分别是Cookie和Session。
   
通过京东购物车案例, 了解会话技术 Cookie对象 和 Session对象
    Cookie对象:
        客户端浏览器的会话技术,它可以把服务器传递过来的一些数据记录在客户端浏览器中,
       解决会话从什么时候开始,到什么时候结束。
    Session对象:
        服务器端的会话技术,  它可以把同一用户与服务器多次请求响应的一些数据记录在服务器Session域中,
        实现该用户在本次会话中, 可随时获取Session域中的数据, 满足多次请求响应之间进行数据传递\访问使用.

Cookie & Session_第3张图片

第二章 Cookie技术

2.1 Cookie介绍

1.Cookie是什么?
    它是客户端浏览器的缓存文件,里面记录了客户浏览器访问网站的一些内容。
    同时,也是HTTP协议请求和响应消息头的一部分(在HTTP协议课程中,我们提到过它)。
2.为什么需要会话技术记录这些内容呢?
   我们网页的交互是通过HTTP协议,而HTTP协议是无状态的协议(数据提交后,浏览器和服务器连接就会关闭,再次交    互就得重新建立新的连接)。所以服务器是无法确认用户的信息,于是就给每个用户发一个通行证(Cookie),从而可    以通过此确认用户信息。
3.Cookie技术可以解决什么问题呢?
   可以用来在浏览器存储交互数据,当下次访问服务器的时候会自动带着相应cookie给服务器,
   从以此提高交互的效率!
4.谁来创建Cookie?它又保存在哪里?
   Cookie是由服务器创建,然后发送给客户端浏览器,
   最终可以保存到浏览器指定位置(前提浏览器支持)上的一段文本信息。

2.2 Cookie的工作流程

流程:
    1.第一次访问服务器,正常访问服务器.
    2.服务器接收到请求后,服务器端可以通过 set-cookie 响应头 响应一小段信息
    3.客户端(浏览器)接收到,自动保存cookie信息到cookie存储区中(由浏览器软件保存该信息)
    4.后续访问中,浏览器会从cookie存储区取出信息,并且在发送信息的时候,通过 cookie 请求头携带上
        服务器端接收到请求后,可以从请求头中获取该小段cookie信息.
强调:
    1.cookie就是一小段标识信息(键值对)!!!  
    2.cookie的内容保存在浏览器端!!!

Cookie & Session_第4张图片

2.3 Cookie的API介绍

服务器端创建Cookie对象

方法 返回值 描述
public Cookie(String name, String value) 构造方法创建Cookie对象 创建Cookie对象, 并指定Cookie中保存 的键值对信息

服务器端Response对象向浏览器发送Cookie

方法 返回值 描述
addCookie(Cookie c) void 把方法参数指定Cookie对象c响应给客户端浏览器

服务器端Request对象获取浏览器发送的Cookie

方法 返回值 描述
getCookies() Cookie[] 获取客户端发送的所有对象的数组,如果客户端浏览器没有发送Cookie返回null

Cookie对象的方法

方法 参数 描述
String getName() 获取cookie 的名称(键)。名称在创建之后不得更改。
String getValue() 获取cookie 的值
void setMaxAge(int s) int 浏览器中Cookie是有生存时间的,默认是当前会话. 浏览器关闭,会话结束 该方法用于指定 cookie 的最大生存时间(以秒为单位)的整数; 如果为负数,则表示不存储该 cookie;如果为 0,则删除该 cookie
void setPath(String p) String 设置携带Cookie的路径 也就是说浏览器访问什么样的路径才会携带Cookie对象
void setDomain(String d) String 设置携带Cookie的域名(如:www.itheima.com) 也就是说浏览器访问什么样的域名才会携带Cookie对象

2.4 Cookie的代码演示

响应Cookie对象给浏览器

package com.itheima.cookie;
​
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;
import java.io.IOException;
/*
构建cookie的servlet
 */
@WebServlet("/create")
public class CreateCookieServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
​
    }
​
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("当浏览器访问到这个servlet的时候,我们就在这里构建一个cookie");
        //如何构建cookie
        Cookie cookie = new Cookie("username", "jack");
        Cookie cookie1 = new Cookie("job", "小钻风");
        System.out.println("构建出来之后 放到响应头中  就返回给了浏览器  完成了cookie的创建及保存");
        response.addCookie(cookie);
        response.addCookie(cookie1);
​
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("cookie已经创建好,你自己个在浏览器找吧!!");
    }
}

ps:第一发起请求,浏览器请求中不带cookie,响应的时候 服务传递两个cookie在响应头中。浏览器中看到了cookie

Cookie & Session_第5张图片

Cookie & Session_第6张图片

 获取客户端浏览器携带的Cookie数据

/*
	浏览器访问服务器,以请求头的方式携带Cookie(可能是多个)
    HttpServletRequest对象提供方法
    public Cookie[] getCookies(): 获取浏览器携带的所有Cookie对象,如果没有携带Cookie返回null
*/
@WebServlet(urlPatterns = "/get")
public class GetCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        										throws ServletException, IOException {
        /**
         *  获取客户端浏览器携带的Cookie数据
         *  request对象方法 getCookies()
         */
        Cookie[] cookies =  request.getCookies();
        for (Cookie cookie : cookies){
            //遍历数组,取出的是数组中的每个Cookie对象
            //取出Cookie中的键
            String key = cookie.getName();
            //取出Cookie中的值
            String value = cookie.getValue();
            System.out.println(key+"==="+value);
        }
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 													throws ServletException, IOException {
        doGet(request, response);
    }
}

ps:再次访问的时候浏览器会带着cookie过去,这次服务器没有构建cookie所以响应中没有cookie,但是请求中有cookie.服务器可以解析出来两个cookie

Cookie & Session_第7张图片

Cookie & Session_第8张图片

设置生存时间

默认

Cookie & Session_第9张图片

/*
	Cookie的生命周期
    	1.默认情况下: 一次会话有效,关闭浏览器,会话结束Cookie消失
        2.设置Cookie的生命周期(存活时间)
        	Cookie中提供方法
            public void setMaxAge(int s): 设置方法参数指定的s秒的生存时间
            	int s: 单位是秒
*/
@WebServlet(urlPatterns = "/life")
public class LifeCookieServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        										throws ServletException, IOException {
        Cookie cookie = new Cookie("heima","java");
        cookie.setPath(request.getContextPath());
        //设置生存时间
        cookie.setMaxAge(60);
        response.addCookie(cookie);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 													throws ServletException, IOException {
        doGet(request, response);
    }
}

Cookie & Session_第10张图片

设置Cookie的携带路径

默认路径是 创建该cookie上一级路径。
只有跟这个cookie相同路径的servlet才能传递过来到。保证模块独立性。
这个cookie在整个项目中公用,设置为项目路径。    

在Web开发中,Cookie是一种存储在客户端浏览器中的小数据片段,用于跟踪用户会话和存储用户偏好设置等信息。每个Cookie都有一个可选的Path属性,用于指定Cookie的作用域(即哪些Web页面可以访问该Cookie)。

Path属性是一个字符串,指定了Cookie的有效路径。默认情况下,如果未指定Path属性,则Cookie的有效路径为设置Cookie的页面路径。例如,如果在根目录下的index.html页面中设置了一个Cookie,则该Cookie的有效路径为"/",即整个网站可以访问该Cookie。如果在子目录下的页面中设置了一个Cookie,则该Cookie的有效路径为该子目录。

可以使用setPath()方法来设置Cookie的Path属性。例如,以下代码将创建一个名为"username"的Cookie,并将其Path属性设置为"/myapp":

Cookie cookie = new Cookie("username", "john");
cookie.setPath("/myapp");
response.addCookie(cookie);

在这种情况下,只有路径为"/myapp"或其子路径的页面才能访问该Cookie。如果在其他路径下的页面中尝试访问该Cookie,则无法访问。使用Path属性可以限制Cookie的作用域,从而增强Web应用程序的安全性和隐私性。

以上代码演示时,均需要打开浏览器调试模式,查看Cookie是否被创建,访问时是否携带了Cookie对象

第三章 Session技术

3.1 Session介绍

1.为什么要使用Cookie和Session?
    ⽤户使⽤浏览器访问服务器的时候,服务器把可以为每个用户浏览器创建一个会话对象(session对象),
    因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器所属的session中,
   当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据
   实现用户数据在会话中的共享。
2.什么是Session?
    Session对象: 服务器端的会话技术,  它可以把同一用户与服务器多次请求响应的一些数据
    记录在服务器Session域中, 实现该用户在本次会话中, 可随时获取Session域中的数据,
    满足多次请求响应之间 进行数据传递\访问使用.

思考, 下面的购物车案例中, 使用ServletContext域 或 Request域 存储购物车商品信息 是否适合?

Cookie & Session_第11张图片

Cookie & Session_第12张图片

 1.Session与Cookie是紧密相关的。 
    Session的使用要求用户浏览器必须支持Cookie,如果浏览器不支持使用Cookie,
    或者设置为禁用Cookie,那么将不能使用Session。

2.Session信息对客户来说,不同的用户, 使用不同的Session信息来记录。
    当用户启用Session时,Tomcat引擎自动产生一个SessionID. 在新会话开始时,
    服务器将SessionID当做cookie存储在用户的浏览器中。

3.2 session与cookie的区别

1:Cookie是把用户的数据写给用户的浏览器。Session技术把用户的数据写到用户所属的session中。
2:Session⽐Cookie使⽤⽅便,Session可以解决Cookie解决不了的事情
   【Session可以存储对象,Cookie只能存储字符串。】
3:Cookie存储在浏览器中,对客户端是可⻅的。信息容易泄露出去。
   Session存储在服务器上,客户端是无法获取的。不存在敏感信息泄露问题。

cookie session
会话数据保存的位置 浏览器 服务器
数据的安全性 不安全 安全
存储数是否有限制

3.3 session的工作流程

Cookie & Session_第13张图片

session的工作流程总结:
    1.请求服务器,请求服务器端储存信息
    2.服务器端接收请求,创建一个session对象和一个唯一id 一一映射放在session池中
    3.将数据存储到session对象中 (session对象内部是map集合可以储存很多信息)
    4.响应给客户端的时候,在响应头中带有一个jessionId的cookie 值是该session的唯一ID
    5.客户端在之后的请求中,都自动携带该cookie,服务器端根据该cookie中唯一id,获取与之对应的session对象
        
综上所述:
    1.session是一个域对象,只要在一个会话中就可以实现多个Servlet间数据共享。
    2.每一个客户端都有自己唯一对应的session对象,故存放的数据也是私有的.别的客户端无法获取。
    3:jsessionId 这个Cookie存活时间为会话结束,也就是关闭浏览器就没有了。  

3.4 Session的API介绍

获取通过Request对象调用如下方法获取Session域对象

HttpSession接口,session对象是接口的实现类,实现类对象tomcat引擎创建
方法 request.getSession()获取session对象
作用域 : 一次会话有效,浏览器不关闭
方法 返回值 描述
getSession() HttpSession 获取当前会话对应的Session对象,如果没有,则创建一个Session对象。

Session域对象存储数据

方法 返回值 描述
setAttribute(String name, Object obj) void 向Session域中保存数据
getAttribute(String name) Object 从Session域中获取数据
removeAttribute(String name) void 从Session域中移除数据

Session域对象销毁

1.如果我们打开一个页面长时间不访问,默认会30分钟后进行销毁。
   tomcat配置文件web.xml中有如下配置:
   
       30
   

2.也可以立刻销毁 session.invalidate()。
3.还可以设置过期时间 session.setMaxInactiveInterval(秒);
4.关闭服务器。

方法 返回值 描述
invalidate() void 使此会话无效,然后取消对任何绑定到它的对象的绑定。 销毁Session对象
setMaxInactiveInterval(int s) void 设置过期时间

3.5 Session 的代码演示

Cookie & Session_第14张图片

获取Session域对象并存取数据

package com.itheima.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/cun")
public class CunSessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("当浏览器第一访问 服务器的时候");
        System.out.println("服务器可以 为当前浏览器构建一个session对象");
        HttpSession session = request.getSession();
        //  特点 如果浏览器没有 jsessionid 那么就是新建一个
        //  如果有且在session池中找到了  该方法就是获取方法
        //获取session 创建的新session 有一个id
        System.out.println("查看session的id:"+session.getId());
        //服务器会自己 偷偷把我们的 session的id  封装成 new Cookie("JSESSIONID",id值)
                                           // 存到响应头中
        //我还想 把一个数据存到session中 实现会话中的数据共享
        session.setAttribute("goods","大金砖");//这个域 是会话域 只在这次会话中有效

        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("一个新的session对象产生了,id是:"+session.getId()+
                "
我们还往session存储了数据"); } }

Cookie & Session_第15张图片

Cookie & Session_第16张图片

观察:响应有了 jsessionid 对 jsessioid

同一会话先访问/session1向域中存数据,再访问session2从Session域中取数据

package com.itheima.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/qu")
public class QuSessionServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("当浏览器再次 服务器的时候");
        System.out.println("如果还在这次会话中,getSession获取的session就是上一个session ");
        HttpSession session = request.getSession();
        //  特点 如果浏览器没有 jsessionid 那么就是新建一个
        //  如果有且在session池中找到了  该方法就是获取方法
        //获取session 创建的新session 有一个id
        System.out.println("查看session的id:"+session.getId());
       //从域中取数据
        Object goods = session.getAttribute("goods");//这个域 是会话域 只在这次会话中有效

        System.out.println("取出的物品是:"+goods);

        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("再次访问服务器,是找到之前的session,sessionid是:"+session.getId()+
                "
我们从session中取了数据"+goods); } }

Cookie & Session_第17张图片Cookie & Session_第18张图片

观察 :取得时候,再次访问了看到了 大金块 说明数据实现了会话域共享,而且访问的时候带着令牌去访问的,所以可以获取之前存的数据。

但是浏览器以Cookie的形式保存Session对象的id,默认生命周期是一次会话有效

总结:

同一会话访问/cun,发现浏览器Cookie中保存的id和代码输出到控制台的id是相同的
接着访问/qu,发现控制台输出的id和前面一样,
说明/qu对应的Servlet中并没有创建新的Session对象 

持久化Session对象(只需要持久化Session对应的id)

package com.itheima.session;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/sessionlong")
public class SessionLongServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      //想要持久化jessionid 怎么做呢
        System.out.println("先获取我们session 如果有就获取 ,没有就新建");
        HttpSession session = request.getSession();
        System.out.println("当前session对象的id是:"+session.getId());
        //我们 之前的jsession遵循默认规则  我们可以显性化
        Cookie jsessionid = new Cookie("JSESSIONID", session.getId());
        jsessionid.setMaxAge(60*10);
        jsessionid.setPath(request.getContextPath());//设置路径为项目路径
        //存到响应头
        response.addCookie(jsessionid);

        response.getWriter().write("see this session:"+session.getId());

    }
}

总结

如果想  关闭浏览器再打开访问的session是同一个,只需我们修改jsessionid的存活时间即可。
作为面试题出现,开发不做。
session什么时候失效呢?
    服务器关闭
    从浏览器的角度,默认情况关闭浏览器,会话就结束。
    服务器中默认 session是30分钟。
    可以手动让session销毁 session.invalidate();

第四章 综合案例

4.1 简易购物车案例

效果

Cookie & Session_第19张图片

分析

Cookie & Session_第20张图片

准备页面(直接放在/web根目录下)

index.html页面内容



    
        
        研究cookie和session
    
    
       

欢迎来购物

买肉   买球  

 meat.html页面内容



    
        
        Title
    
    
        

各种肉大甩卖,一律十块:

鸡肉
牛肉
羊肉



买点别的  查看购物车

ball.html页面内容



    
        
        Title
    
    
        

各种球大甩卖,一律八块

篮球
足球
排球



买点别的  查看购物车

showCart.jsp页面内容

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

    
        显示购物车内容
    
    
        

你选择的结果是:

<% Set cart = (Set) session.getAttribute("cart"); if (cart != null && cart.size() > 0) { for (String s : cart) { out.println(s); } } %>

CartServlet类内容

@WebServlet("/cart")
public class CartServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        										throws ServletException, IOException {
        // 1:获取  页面提交 需要加入购物车的  商品
        request.setCharacterEncoding("utf-8");
        String[] goods = request.getParameterValues("goods");
        //从域中获取一个购物车对象  其实就是商品列表信息
        Set cart = (Set) request.getSession().getAttribute("cart");
        // 判断
        if (cart == null) {
            //购物车是空的
            cart = new HashSet<>();
            if (goods != null && goods.length > 0) {
                // 将数组中数据 收集到指定的 集合中
                Collections.addAll(cart, goods);
            }
        } else {
            // 往里面追加
            if (goods != null & goods.length > 0) {
                // 将数组中数据 收集到指定的 集合中
                Collections.addAll(cart, goods);
            }
        }
        //购物车完成了更新
        // 存到session中
        request.getSession().setAttribute("cart", cart);
        //自己做个遍历
        for (String s : cart) {
            System.out.println(s);
        }
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("

添加购物车成功!


跳回主页
查看购物车列表"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }

你可能感兴趣的:(后端,前端,html,java,servlet)