Cookie & Session

53 篇文章 2 订阅

目录

第一章 会话技术 

1.1 什么是会话

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

1.3 保存会话技术有哪些

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

第二章 Cookie技术

2.1 Cookie介绍

2.2 Cookie的工作流程

2.3 Cookie的API介绍

2.4 Cookie的代码演示

第三章 Session技术

3.1 Session介绍

3.2 session与cookie的区别

3.3 session的工作流程

3.4 Session的API介绍

3.5 Session 的代码演示

第四章 综合案例

4.1 简易购物车案例


第一章 会话技术 

1.1 什么是会话

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

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

例如:

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

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

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

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

1.3 保存会话技术有哪些

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

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

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

第二章 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的内容保存在浏览器端!!!

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数据

/*
	浏览器访问服务器,以请求头的方式携带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的生命周期
    	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的携带路径

默认路径是 创建该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域 存储购物车商品信息 是否适合?

 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存储在服务器上,客户端是无法获取的。不存在敏感信息泄露问题。

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

3.3 session的工作流程

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中有如下配置:
    <session-config>
       <session-timeout>30</session-timeout>
   </session-config>
2.也可以立刻销毁 session.invalidate()。
3.还可以设置过期时间 session.setMaxInactiveInterval(秒);
4.关闭服务器。

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

3.5 Session 的代码演示

获取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()+
                "<br/>我们还往session存储了数据");

    }
}

观察:响应有了 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()+
                "<br/>我们从session中取了数据"+goods);

    }
}

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

但是浏览器以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 简易购物车案例

效果

分析

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

index.html页面内容

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>研究cookie和session</title>
    </head>
    <body>
       <h1>欢迎来购物</h1>
       <a href="meat.html">买肉</a>&nbsp;&nbsp;
       <a href="ball.html">买球</a>&nbsp;&nbsp;
    </body>
</html>

 meat.html页面内容

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h4>各种肉大甩卖,一律十块:</h4>
        <form name="Meet" id="Meat" action="/WEB07/cart" method="post">
            <input type="checkbox" name="goods" value="鸡肉">鸡肉<br>
            <input type="checkbox" name="goods" value="牛肉">牛肉<br>
            <input type="checkbox" name="goods" value="羊肉">羊肉<br><br>
            <input type="submit" value="提交">
            <input type="reset" value="全部重写"><br><br>
            <a href="ball.html">买点别的</a>&nbsp;&nbsp;<a href="showCart.jsp">查看购物车</a>
        </form>
    </body>
</html>

ball.html页面内容

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h4>各种球大甩卖,一律八块</h4>
        <form action="/WEB07/cart" method="post" name="Ball" id="ball">
            <input type="checkbox" name="goods" value="篮球">篮球<br>
            <input type="checkbox" name="goods" value="足球">足球<br>
            <input type="checkbox" name="goods" value="排球">排球<br><br>
            <input type="submit" value="提交">
            <input type="reset" value="全部重写"><br><br>
            <a href="meat.html">买点别的</a>&nbsp;&nbsp;<a href="showCart.jsp">查看购物车</a>
        </form>
    </body>
</html>

showCart.jsp页面内容

<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*" %>
<html>
    <head>
        <title>显示购物车内容</title>
    </head>
    <body>
        <h3>你选择的结果是:</h3>
        <%
            Set<String> cart = (Set<String>) session.getAttribute("cart");        
            if (cart != null && cart.size() > 0) {
                for (String s : cart) {
                    out.println(s);
                }
            }
        %>
    </body>
</html>

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<String> cart = (Set<String>) 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("<h1>添加购物车成功!</h1> <br/> <a href='index.html'>跳回主页</a><br/><a href='showCart.jsp'>查看购物车列表</a>");
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 													throws ServletException, IOException {
        doGet(request, response);
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值