一文带你快速鉴别Cookie&Session

会话跟踪技术

1、相关基础概念

  • 什么是会话?

    会话就是浏览器和Web服务器建立连接和断开连接的过程。当用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束。在一次会话中可以包含多次请求和响应。

    举例说明:当我们用浏览器访问京东,在进入京东官网(即浏览器和京东的服务器建立连接,会话开始),我们可以在官网点击各种超链接访问各种商品的详细信息(即进行多次请求和响应,会话中),然后我们看累了,直接叉掉京东页面(即浏览器和京东服务器断开连接,会话结束)。以上过程就称之为一次会话。

    image-20220810102628310
  • 什么是会话跟踪

    会话跟踪是一种实现一次会话中多次请求-响应之间数据共享的技术,主要是为了解决HTTP无状态的缺点,服务器需要识别多次请求是否来自于同一浏览器(这个识别过程就是会话跟踪),以便实现一次会话中多次请求-响应之间的数据共享。

    举例说明:在进入京东官网(即浏览器和京东的服务器建立连接,会话开始),当我们看到心怡的商品时,我们就会点击加入购物车,然后浏览器就会显示加入成功的提示(进行第一次请求-响应),然后我们就准备点击购物车进行支付(进行第二次请求-响应),就会显示第一次请求-响应时的商品信息,这个过程就需要两次请求-响应间的数据共享,而数据共享就需要使用会话跟踪技术。

    image-20220810103420904
  • 如何实现会话跟踪技术?

    • 方式一:客户端会话跟踪技术Cookie
    • 方式二:服务端会话跟踪技术Session

2、Cookie

Cookie是一种客户端会话技术,将数据保存到客户端,以后客户端每次请求都会携带Cookie数据进行访问。Servlet API 提供了一个javax.servlet.http.Cookie类,该类包含了所有的Cookie相关操作的API,及其Cookie的各个属性

2.1 Cookie的基本使用

对于后端程序员而言,关于Coolie的操作,主要包含两种类型的操作,一是从服务端发送Coolie对象到客户端,二是从服务端获取来自客户端的Coolie对象

2.1.1 发送Cookie

发送Cookie主要包含两步:

  • Step1:创建Cookie对象,并设置数据

    Cookie cookie = new Cookie("key","value");
    
  • Step2:使用Response对象的addCookie方法进行发送

    response.addCookie(cookie);
    

示例

任务:在Servlet中生成Cookie对象并存入数据,然后将数据发送给浏览器

导入依赖
编写Servlet
查看Coolie
  • Step1:使用Maven导入项目依赖

    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <!--========================项目信息================================-->
        <!--Maven版本信息-->
        <modelVersion>4.0.0</modelVersion>
        <!--项目坐标-->
        <groupId>com.hhxy</groupId>
        <artifactId>day10_CoolieAndSession</artifactId>
        <version>1.0-SNAPSHOT</version>
        <!--项目打包方式-->
        <packaging>war</packaging>
        <!--项目依赖的JDK版本-->
        <properties>
            <maven.compiler.source>16</maven.compiler.source>
            <maven.compiler.target>16</maven.compiler.target>
        </properties>
        <!--==============================================================-->
    
        <!--=============================项目依赖==========================-->
        <!--项目依赖的jar包-->
        <dependencies>
            <!--servlet依赖的jar包-->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
        <!--项目依赖的插件-->
        <build>
            <!--tomcat7插件-->
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                    <configuration>
                        <port>8080</port>
                        <!--                    <path></path>-->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
  • Step2:编写Servlet

    ASerlvet:发送Cookie

    package com.hhxy.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
     */
    @WebServlet("/AServlet")
    public class AServlet extends HttpServlet {
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            this.doGet(request, response);
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1、创建Cookie对象,并设置值
            Cookie cookie = new Cookie("username","zhangsan");
            //2、发送Cookie对象
            response.addCookie(cookie);
        }
    }
    
  • Step3:到浏览器中查看Cookie数据

    设置 → 隐私设置和安全性 → C o o k i e 及其他网站数据 → 查看所有 C o o k i e 和网站数据 设置\rightarrow{隐私设置和安全性}\rightarrow{Cookie及其他网站数据}\rightarrow{查看所有Cookie和网站数据} 设置隐私设置和安全性Cookie及其他网站数据查看所有Cookie和网站数据

    image-20220810152646190

2.1.2 获取Cookie

获取Cookie主要包含三步:

  • Step1:使用Request对象的getCookies方法获取Cookie数组

    Cookie[] cookies = request.getCookies();
    
  • Step2:遍历Cookie数组

    for (Cookie cookie : cookies)
    //或者:
    for (int i=0;i<cookies.length;i++)
    
  • Step3:获取Cookie对象的数据

    //获取name
    cookie.getName();
    //获取值
    cookie.getValue();
    

    拓展:在EL表达始终获取Cookie对象中的数据

    ${cookie.key.value}

示例

获取Cookie的依赖和发送Cookie的依赖是一样的,不在赘述

BServlet:获取Cookie

package com.hhxy.web;

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
 */
@WebServlet("/BServlet")
public class BServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、获取Cookie数组
        Cookie[] cookies = request.getCookies();
        //2、遍历Cookie数组
        for (Cookie cookie : cookies) {
            //3、获取Cookie对象中的数据
            String name = cookie.getName();
            if(name.equals("username")){//筛选出我想要的Cookie对象
                String value = cookie.getValue();
                System.out.println(name+":"+value);
            }
        }
    }
}

访问结果

image-20220810154913633

注意

1)首先要先运行Aservlet,让浏览器中存在Cookie,否则会报错,比如当我们将浏览器中的Cookie删除后,使用BServlet进行访问,直接报错:

image-20220810155448528

2)其次Cookie只能共享同一次会话的数据,无法跨会话共享数据。也就是说只能在同一个模块下Servlet共享数据

3)Cookie只能发送字符串类型的数据,非字符转类型的需要进行转换

4)Cookie发送中文数据会乱码。乱码原因可以参考 Request&Reponse对象详解 中1.4.3节

2.2 Cookie原理

Cookie技术的实现是基于HTTP协议的,数据的传递和发送都是键值对的形式。

在一次会话中,当我们使用浏览器访问AServlet时,Tomcat接收到请求就会自动调用doXXX1方法,将Cookie数据响应到浏览器,而Tomcat在响应过程中,会对我们的Cookie数据进行封装,将数据存在响应头set-cookie中,然后传递给浏览器,浏览器接收到响应数据后,会将这个Cookie数据存储在本地一个Cookie仓库中;当我们再次使用浏览器访问BServlet时,BServlet接收到请求就会获取来自请求数据中的Cookie(这个Cookie是第一次请求-响应的),此时的请求数据被浏览器进行了封装,存在请求头cookie:中。示意图:

image-20220810161747843

2.3 Cookie存活时间

默认情况,服务端发送到浏览器的Cookie数据并不会永久存储,当浏览器关闭时,Cookie数据会被自动释放

思维拓展🚝🚆:浏览器在访问AServlet后,重启Tomcat后再次访问BServlet能够获取到原来的数据?

setMaxAge:用于设置Cookie数据在浏览器的存储时间

setMaxAge(int seconds)

seconds的取值情况:

  • 正数:将Cookie写入浏览器所在电脑的硬盘,持久化存储。到时间自动删除,时间单位是秒
  • 负数:默认值,Cookie在当前浏览器内存中,当浏览器关闭,则Cookie被销毁
  • 零:删除对应Cookie
@WebServlet("/AServlet")
public class AServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 创建Cookie对象
        Cookie cookie = new Cookie("username","zs");
        //设置存活时间   ,1周 7天
        cookie.setMaxAge(60*60*24*7);//阅读性高,但是性能不高
        //cookie.setMaxAge(604800);//阅读性不高,但是性能高
        //2. 发送Cookie,response
        response.addCookie(cookie);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

思维拓展答案:BServlet是肯定能获取的,因为Cookie数据是存储在浏览器中,只要浏览器不重启就没事(亲测有效😄)

2.4 Cookie存储中文

Cookie不能直接存储中文,如需存储需要进行转码!同时想要获取转码后的Cookie数据,还需要进行对应的解码!

示例

AServlet:向浏览器发送Cookie

package com.hhxy.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;
import java.net.URLEncoder;

/**
 * 发送Cookie
 */
@WebServlet("/AServlet")
public class AServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //0、将要存储的中文进行URL编码
        String name = "张三";
        String encode = URLEncoder.encode(name, "UTF-8");
        //测试:
        System.out.println(encode);//输出:%E5%BC%A0%E4%B8%89
        //1、创建Coolie对象,并设置值
        Cookie cookie = new Cookie("username",encode);
        //2、发送Coolie对象
        response.addCookie(cookie);
    }
}

BServlet:获取来自浏览器的Cookie

package com.hhxy.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;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * 获取Cookie
 */
@WebServlet("/BServlet")
public class BServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、获取Cookie数组
        Cookie[] cookies = request.getCookies();
        //2、遍历Cookie数组
        for (int i=0;i<cookies.length;i++) {
            //3、获取Cookie对象中的数据
            String name = cookies[i].getName();
            if(name.equals("username")){
                String value = cookies[i].getValue();
                //ULR解码
                String encode = URLDecoder.decode(value, "UTF-8");
                System.out.println(name+":"+encode);//username:张三
            }
        }
    }
}

当我们直接使用Cookie发送中文数据时:

image-20220810170211051

3、Session

Session是一种服务端会话跟踪技术,能够将数据保存到服务端。

3.1 Session的基本使用

Session是一个域对象,他继承HttpSession类,和Reuqest域对象不同的是,他的域的范围是一次会话(一个模块下),而Request域对象的范围仅仅是一次请求-响应之间(需要请求转发)。

  • getSession:获取Session对象:

    HttpSession session = request.getSession();
    
  • setAttribute:存储数据到Session的域中:

    void setAttribute(String name, Object o)
    
  • getAttribute:根据 key,获取值

    Object getAttribute(String name)
    
  • removeAttribute:根据 key,删除该键值对

    void removeAttribute(String name)
    
  • getId:获取Session的id号

    int getId()
    

    备注:Session的id号是Web服务器创建的,当浏览器发送请求,服务器执行getSession未发现请求数据有Session的Id号就会自动创建一个,然后通过响应数据发送给浏览器,浏览器就将这个SessionId存储在本地的Cookie库中

  • isNew:判断当前Session是否是最新的Session

    boolean isNew()
    
    • true:Session是最新的

    • false:Sessino不是最新的(SessionID已经通过浏览器发送给服务器,服务器访问过了)

  • getMaxInactiveInterval:获取Session的非激活时间2间隔(默认是1800s)

    int getMaxInactiveInterval()
    

示例

SessionDemo1:将数据存到Session域中

package com.hhxy.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("/SessionDemo1")
public class SessionDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、获取Session对象
        HttpSession session = request.getSession();
        //2、将数据存到Session域中
        session.setAttribute("username","张三");
    }
}

SessionDemo2:获取存储在Session域中的对象

package com.hhxy.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("/SessionDemo2")
public class SessionDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1、获取Session对象
        HttpSession session = request.getSession();
        //2、获取Session域中的数据
        Object username = session.getAttribute("username");//张三
        System.out.println("username"+username);
    }
}

3.2 Session原理

Session的实现是基于Cookie的。

在一次会话中,当用户使用浏览器访问SessionDemo1时,Tomcat接收到来自浏览器的请求,Tomcat自动运行doXXX1方法生成Session对象,然后将数据存储到Session域中,方法执行后,Tocmat会自动生成一个响应头信息:set-cookie(该信息是Session对象的唯一标识),然后响应到浏览器上,浏览器接收到该数据会将其存储在本地的Cookie库中;当浏览器再次访问SessionDemo2时,浏览器会自动将存在本地Cookie库中的信息封装到请求头cookie中,Tocmat接收到该数据,根据cookie中的id号进行查询,看内存中是否存在等于该id号的Session对象,如果存在就直接调用(这样就能获取到前面存储在Session域中的数据了),不存在就重新创建。

示意图:

image-20220810204614039

3.3 Session的钝化和活化

前面我们在使用Cookie实现会话跟踪技术时,是将信息存储浏览器中的,服务器的重启不会影响到Cookie中的信息;而现在我们在使用Session时,第一次浏览器访问SessionDemo1后信息会存储在Session域中,那么我们在正常重启Tomcat后,访问SessionDemo2信息是否因为Session对象的销毁而造成无法获取呢?(简言之:服务器重启后,Session中的数据是否还在?)

答案是【SessionDemo2仍然能够成功获取到SessionDemo1存储在Session中的数据!】

  • 钝化:当Tomcat正常关闭时,Tocmat会先将Session数据写入硬盘的文件中(存在SESSIONS.ser中),然后再销毁Session对象
  • 活化:当Tomcat再次启动时,Tomcat会自动将SESSIONS.ser文件中的数据加载新创建的Session对象中(这个Session对象已经不是原来的Session了,只是存储的数据是一样的,JSESSIONID的值也是一样)

当我们使用Ctrl+C进行关闭:

image-20220810204219773

SESSIONS.ser文件按可以在该目录下查看项目目录\target\tomcat\work\Tomcat\localhost\项目名称\SESSIONS.ser,如图:

image-20220810204138175

然后使用mvn tomcat7:run重新启动Tomcat后,SESSIONS.ser文件被加载成Session对象后自动消失

3.4 Session的存活时间

  • 默认情况下,Session对象只会存在30分钟,这三十分钟没有对Session进行操作(这是在Tomcat的web.xml中写死的)

  • 手动销毁Session对象:

    session.invalidate();
    
  • 设置Session对象的存活时间:

    在web.xml中配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
             version="3.1">
        <session-config>
            <session-timeout>100</session-timeout>
        </session-config>
    </web-app>
    

总结

Cookie和Session的比较

  • 安全性:Session存储的数据更安全。Session对象的数据是存储在服务端,而Cookie的数据存储在客户端,客户端的数据容易被窃取和截获,存在很多不安全的因素,客户端的数据容易被窃取和截获,存在很多不安全的因素

  • 便利性:Session存储数据更方便。Cookie只能存储字符串数据,而Session可以存储任何Object类型的数据,并且Cookie存储中文数据时要进行转码,接收时要进行解码,否则会乱码,而Session能直接传中文数据

  • 存储时间:默认存储时间不同。Cookie和Session存储的数据都会因为浏览器重启而丢失,都不会因为服务器的重启而导致数据丢失,但在浏览器不重启的时候,Cookie默认是长期保存在浏览器中,而Session默认在服务器中保存30分钟

  • 存储容量:Session的存储容量大于Cookie。Cookie最大只能存3KB,而Session无大小限制


  1. doXXX表示:doGet方法或doPost方法,Tomcat会根据浏览器不同的请求方式,自动调用与之对应的方法 ↩︎ ↩︎

  2. Session非激活时间就是不进行任何操作的情款下,Session的存活时长 ↩︎

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
Eclipse是一个开放源代码的集成开发环境(IDE),可用于Java开发,但也可以用于其他编程语言的开发。在本文中,我将向你展示如何使用Eclipse进行Java开发。 1. 下载Eclipse 首先,你需要从Eclipse官方网站下载Eclipse IDE。下载页面上将提供几个不同的版本,包括Eclipse IDE for Java Developers、Eclipse IDE for JavaScript and Web Developers,以及Eclipse IDE for C/C++ Developers等。选择适合你的版本,然后按照安装向导进行安装。 2. 创建Java项目 一旦你安装了Eclipse,你可以启动它并创建一个新的Java项目。选择“File”->“New”->“Java Project”,然后按照向导创建一个新的Java项目。在创建项目时,你需要指定项目名称、项目类型以及JRE版本等信息。 3. 创建Java类 一旦你创建了一个Java项目,你就可以创建一个Java类。选择你的Java项目,在“src”文件夹上右键单击,然后选择“New”->“Class”。输入类名和选择要继承的类(如果有的话),然后点击“Finish”。 4. 编写Java代码 现在你已经创建了一个Java类,可以开始编写Java代码了。在Eclipse的编辑器中,你可以输入Java代码并保存它。当你保存Java文件时,Eclipse会自动编译你的代码,并在Problems视图中显示任何编译错误。 5. 运行Java程序 一旦你编写了Java代码并保存了它,你可以运行Java程序。右键单击Java文件,然后选择“Run As”->“Java Application”。如果一切顺利,你的Java程序将在控制台中输出结果。 6. 调试Java程序 如果你的Java程序出现了错误或不按预期运行,你可以使用Eclipse的调试器来调试它。在Eclipse的编辑器中,你可以设置断点并启动调试器。当程序执行到断点时,调试器会暂停程序并允许你检查变量、运行代码等。 7. 导入外部JAR包 有时,你可能需要使用外部JAR包来完成你的Java项目。在Eclipse中,你可以简单地将外部JAR包导入到你的项目中。右键单击Java项目,然后选择“Build Path”->“Configure Build Path”。在“Libraries”选项卡上,你可以添加外部JAR包。 总结 在本文中,我们介绍了如何使用Eclipse进行Java开发。我们学习了如何创建Java项目、创建Java类、编写Java代码、运行Java程序、调试Java程序以及导入外部JAR包。Eclipse具有强大的功能,可以大大提高Java开发的效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识汲取者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值