Cookie 和 Session 的工作流程

*TOC](Cookie 和 Session 的工作流程)
Cookie 是浏览器在本地持久化存储数据的一种机制

什么是Cookie 和session

1.Cookie 的数据从哪里来?
服务器返回给浏览器的
2.Cookie 的数据的格式
Cookie 中是键值对结构的数据,并且这里的键值对都是程序员自己定义的
3.Cookie 有什么作用?
Cookie 可以在浏览器中存储一些"临时性数据",其中最典型的一种方式,就是用来存储"身份标识":sessionId,这里就涉及到Cookie 和session之间的联动了,Cookie 是浏览器存储数据(sessionId),而session是服务器存储数据 ( 存储用户的详细信息,同时分配给用户一个sessionId(唯一值) ) ,后续再访问该网站的其他页面的时候,请求中就会自动带上刚才的sessionId,进一步的服务器就会知道当前是哪个用户在操作了
4.Cookie 到哪里去?
Cookie 的内容会在下次访问该网站的时候,自动的被带到HTTP请求中
5.Cookie 是怎么存的?
浏览器按照不同的"域名"分别存储Cookie ,域名和域名之间的Cookie 是不能互相干扰的,存储在硬盘上的,存储往往会有一个超时时间

核心操作

HttpServletRequest 类中的相关方法

方法 描述
HttpSession getSession() 在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null
Cookie[]getCookies() 返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对

getSession()方法,是最核心的api,效果有两方面:
1.如果当前用户没有session(会话),就会创建出session
2.如果已经有了session,就能够查询到这个session

HttpServletResponse 类中的相关方法

方法 描述
void addCookie(Cookie cookie) 把指定的 cookie 添加到响应中.

HttpSession 类中的相关方法

一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存任何我们需要的信息

方法 描述
Object getAttribute(Stringname) 该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返回 null.
void setAttribute(Stringname, Object value) 该方法使用指定的名称绑定一个对象到该 session 会话
boolean isNew() 判定当前是否是新创建出的会话

session存在的意义,也是为了让用户存储一些自定义的数据,此处的session更像是一个Map
session这个东西在服务器中是存在很多份的,每个用户都有一份自己的session,一个服务器会有多个用户,因此,服务器这边也会通过Map的方式来组织多个session

Cookie 和 Session 的工作流程_第1张图片

Cookie 类中的相关方法

每个 Cookie 对象就是一个键值对

方法 描述
String getName() 该方法返回 cookie 的名称。名称在创建后不能改变。(这个值是 SetCooke 字段设置给浏览器的)
String getValue() 该方法获取与 cookie 关联的值
void setValue(StringnewValue) 该方法设置与 cookie 关联的值。

HTTP 的 Cooke 字段中存储的实际上是多组键值对. 每个键值对在 Servlet 中都对应了一个 Cookie 对象. 通过
HttpServletRequest.getCookies() 获取到请求中的一系列 Cookie 键值对. 通过
HttpServletResponse.addCookie() 可以向响应中添加新的 Cookie 键值对.

setCookie

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;
@WebServlet("/setCookie")
public class setCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //期望通过这个doGet方法,把一个自定义的Cookie数据返回到浏览器这边
        Cookie cookie = new Cookie("data","2023-09-23");
        Cookie cookie1 = new Cookie("time","16:24");
        resp.addCookie(cookie);
        resp.addCookie(cookie1);
        resp.getWriter().write("setCookie ok");
    }
}

运行setCookie之后,代码中就会构造Cookie放到响应中,通过fiddler抓包工具可以看到本次请求的响应中,出现了
Cookie 和 Session 的工作流程_第2张图片
也就是由代码中的addCookie操作构造除了这两个响应的header
Set-Cookie: data=2023-09-23
Set-Cookie: time=16:24
此后,通过这两个响应头,就可以把cookie返回到浏览器中,我们就可以在浏览器中查看已经设置好了的Cookie属性了
Cookie 和 Session 的工作流程_第3张图片
后续再次发送get请求的时候,cookie内容就会出现在请求中

getCookie

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;
@WebServlet("/getCookie")
public class getCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取到这次请求中的Cookie
        Cookie[]cookies = req.getCookies();
        if (cookies!=null){
            for (Cookie cookie:cookies){
                System.out.println(cookie.getName()+":"+cookie.getValue());
            }
        }else{
            System.out.println("当前请求中没有Cookie");
        }

        resp.getWriter().write("ok");
    }
}

在这里插入图片描述
同时服务器也会收到浏览器返回的cookie内容了
在这里插入图片描述

使用cookie结合session实现登录效果

servlet也提供了session相关的支持
实现登录功能,不需要直接使用cookie api,直接使用session的api就可以了

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录</title>
</head>
<body>
    <form action="login" method="post">
        <input type="text"name="username">
        <input type="password"name="password">
        <input type="submit" value="登录">
    </form>
</body>
</html>

此处先构造出一个html的页面,在用户点击提交按钮的时候,就会使用form表单构造出一个http请求,方法名是post,路径是login

loginServlet

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("/login")
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.获取用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (username == null||password==null||username.equals("")||password.equals("")){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("请求的参数不完整");
            return;
        }
        //2.验证用户名密码是否正确
        if (!username.equals("zhangsan")){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("用户名错误!");
            return;
        }
        if (!password.equals("88888888")){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("密码错误!");
            return;
        }
        //登录成功,此时就可以给这个用户创建会话了
        //参数为true,不存在就会创建(登录时使用)
        //参数为false,不存在就会返回一个null(后续跳转到其他页面,检查用户的登录状态的时候使用)
        HttpSession session =req.getSession(true);
        //在会话中,可以顺便保存自定义的数据,比如保存一个登陆的时间戳
        //setAttribute后面的value是一个object,存任何数据都可以
        session.setAttribute("username",username);
        session.setAttribute("time",System.currentTimeMillis());
        //4.让页面自动跳转到到网站主页
        //此处约定跳转主页的路径是index(也使用servlet来生成一个动态页面)
        resp.sendRedirect("index");

    }
}
此处是关于登录的逻辑,并在登录成功后,通过重定向绑定一个新的页面的路径,新的路径为index

indexServlet

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;

//通过这个servlet来生成一个主页
@WebServlet("/index")
public class indexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //先验证一下用户的登录状态,如果未登录,就要求用户要先登录
        HttpSession session = req.getSession(false);
        if (session==null){
            //用户未登录
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("请先登录,再访问主页");
            return;
        }
        //已经登录成功了
        //取出之前的attribute
        String username = (String) session.getAttribute("username");
        Long time = (Long) session.getAttribute("time");
        System.out.println("username="+username+"time="+time);
        //根据这样的内容构造页面
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("欢迎您!"+username+"!上次登录时间:"+time);
    }
}

你可能感兴趣的:(cookie,session)