面试考点:session和cookie

一、关于 cookie 的前言概括

在之前的 HTTP 格式的介绍当中,有详细的介绍过 cookie 的相关用法。

简单回顾总结就是:

  1. cookie 是让程序员能够在客户端持久存储数据的一种机制
  2. 存储的是程序员自己定义的键值对
  3. 通过服务器响应 set-cookie 这个 header 获取到 cookie 的值,并保存到本地
  4. 下一次请求就会带上 cookie ,发送给服务器

用户输入账号密码登录后,再次登录不需要再次输入账号密码就可以直接的登录成功就是依靠 cookie 来实现的

在这里插入图片描述

但是有关于用户的信息实际上是非常多的,比如访问网站的浏览记录,上次访问网站的时间等等,这么多的信息在服务器客户端之间传输来又去的非常浪费带宽。更何况 cookie 的存储容量又是有限的,一个站点最多保留20个 cookie,这么多的用户信息没有办法单纯的依靠 cookie 来保存在客户端,因此将数据保存到服务器端才是比较科学的做法。

二、session 工作原理

因为要将信息存储在服务器端,就引入了会话机制 session

session是服务端存储的一个对象,主要用来存储所有访问过客户端网页的用户信息(也可以存储其他信息),从而实现保持用户会话状态。但是服务器重启时,内存会被销毁,存储的用户信息也就消失了。

面试题:详述 session 工作原理

  1. 当客户端登录完成后,就会在服务器端产生一个 session,,实际上是一个键值对,key 是 sessionId(随机唯一的字符串),value 保存的就是身份信息(HttpSession 对象)。服务器端将这些键值对形式的会话通过hash 表的形式管理起来
  2. 此时服务器端就会将 sessionId返回到客户端浏览器。
  3. 客户端将 sessionId 存储在浏览器的 cookie
  4. 当用户再次登录的时候,就会拥有对应的 sessionId ,就将该 sessionId 发送到服务器端请求登录
  5. 服务器端在内存中找到对应的 sessionId 就完成登录,如果找不到,说明还没有登录(每个用户登录都会生成一个会话),就返回登录页面让用户进行登录

session 工作原理和校园卡差不多,校园卡中实际上并没有保存太多的内容,但是有着它在学校中拥有的唯一的信息——学号。因此你(客户端)拎着这张卡,通过学号(相当于sessionId)就可以在系统中(服务器)搜索到有关于你的相关具体学生信息,就可以凭借卡进出宿舍大门,在图书馆借书,在食堂吃饭等等。

三、常用的方法

3.1 getSession()

这是 HttpServletRequest 类中的方法,作用是在服务器中获取会话。

HttpSession session = req.getSession(true);
HttpSession session = req.getSession(false);

参数为true

  1. 查看请求中是否有 sessionId ,并判断其合法性
  2. 如果有 sessionId 且合法,就根据该 sessionId 找到对应的 HttpSession对象
  3. 如果没有 sessionId,就生成一个唯一的 sessionId,创建一个HttpSession 对象,把这一组键值对插入到服务器管理 session 的 hash 表中,把 sessionId 通过 Set-Cookie 在响应中返回给客户端

参数为false

  1. 查看请求中是否有 sessionId ,并判断其合法性
  2. 如果有 sessionId 且合法,就根据该 sessionId 找到对应的 HttpSession对象
  3. 如果没有 sessionId,就直接返回 null

通常用法就是前者用于登录,后者用于查看登录的情况。

3.2 getAttribute()和setAttribute()

HttpSession 对象中就保存着我们需要保存的身份信息,这些身份信息的存储方式也是键值对的形式

**1. Object getAttribute(String name) **

该方法返回在该 session 会话中具有指定名称的对象,如果没有指定名称的对象,则返返回 null

int num = (Integer)session.getAttribute("number");
//通过number这个key来找对应的value,找的对象是int类型,需要进行强制类型转换

2. void setAttribute(String name, Object value)

该方法使用指定的名称绑定一个对象到该 session 会话

session.setAttribute("users",user);//将user是value; users是key

简单来说,就是 HttpSession 对象中的键值对,通过 key 来获取 value 的值的方法就是getAttribute,根据 key 来设置 value 的值的方法就是 setAttribute

四、关系总结图

在这里插入图片描述

可以看见Cookie,session,HttpSession 对象中的值都是键值对的形式,其中的关系需要理清。

五、实操:实现登录功能并计算访问页面的次数

5.1 登录页面实现(login.html)

<body>
    <form action="login" method="post">
        <input type="text" name="userName"><br>
        <input type="text" name="passWord"><br>
        <input type="submit" value="提交">
    </form>
</body>

通过的 form 表单简单的构造一个登录页面

  1. action=“login” 中,login是处理 post 请求的 Servlet 程序,用于判断用户登录是否成功

  2. method="post"指的是请求的方法时POST

  3. form 表单默认的body格式是 x-www-form-urlencoded ,因此构造的请求 body为 userName=xxx&passWord=xxx

5.2 判断是否登录成功 Servlet 程序(LoginServlet)

class User {
    
    
    public String userName;
    public String passWord;
}
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset=utf8");//设置字符集
        //1.获取到body中的数据
        String userName = req.getParameter("userName");
        String passWord = req.getParameter("passWord");
        //2.验证登录数据的合法性,为null或者为空字符串都为不合法
        if(userName == null||userName.equals("")||passWord == null||passWord.equals("")) {
    
    
            resp.sendRedirect("login.html");
            //不合法就重定向到login.html继续用户名及密码的输入
            return;
        }
        //3.核对信息的正确性(在这里假定用户名字为Peter,用户的密码为123)
        if(!userName.equals("Peter")||!passWord.equals("123")) {
    
    
            resp.getWriter().write("用户名或者密码错误,登陆失败");
            return;
        }
        //到这儿登录成功啦,就可以创建会话了
        User user = new User();
        user.userName = userName;
        user.passWord = passWord;//构造一个 User 对象
        HttpSession session = req.getSession(true);
        //如果会话中不存在该用户就创建一个新的sessionId
        session.setAttribute("user",user);//设置属性
        session.setAttribute("index",0);//代表访问次数,最初为0
        resp.sendRedirect("index");
        //重定向到index路径,实现访问次数的计数
    }
}

流程总结:

  1. 读取到用户提交的用户名和密码
  2. 对用户名及密码的合法性进行校验
  3. 判断是否登录成功
  4. 创建会话,在 HttpSession 对象中保存一些信息
  5. 重定向到指定页面

5.3 显示访问次数 Servlet 程序(IndexServlet)

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        resp.setContentType("text/html;charset = utf8");
        //1.首先需要通过session判断一下,是否已经登录成功了
        HttpSession session = req.getSession(false);
        //此时去找记录的时候,如果没有存档就返回null
        if(session == null) {
    
    
            //说明没有登录过,重定向到 login.html 页面进行登录
            resp.sendRedirect("login.html");
            return;
        }
        //到这里说明已经登录过了
        User user = (User)session.getAttribute("user");
        int visitCount = (Integer)session.getAttribute("index");
        //获取用户 user 和 设置的访问次数 index,首次访问时为0
        visitCount ++;//访问次数增加
        session.setAttribute("index",visitCount); //将值设置回去
        StringBuilder str = new StringBuilder();
        str.append(user.userName);
        str.append("访问次数: ");
        str.append(visitCount);
        resp.getWriter().write(str.toString());
    }
}

5.4 结果验证与展示

首次登录请求:

请求:

在这里插入图片描述

可以查看到form表单中接收请求的对象以及 body 部分

响应:

在这里插入图片描述

状态码 302Location:index,说明重定向到 index 路径进行访问次数的显示了

由于登录成功,服务器通过 Set-Cookie 的Header向客户端传送 sessionId,该sessionId 的 key 为JSESSIONID ,后面跟着的一长串字符串就是 sessionId 的值(唯一的)

此时服务器端就保存了 sessionId

第二次请求:

这次请求服务器就会带着 sessionId ,服务器根据这来找到 HttpSession 对象,取出里面 index 对应的值,自增,在写回去,同时页面显示访问次数结果

浏览器本地查看的 Cookie 内容:

在这里插入图片描述

第二次请求的请求:

在这里插入图片描述

第二次请求的响应:

在这里插入图片描述

页面结果:

在这里插入图片描述

之后的继续访问,原理同上

总体效果展示:

在这里插入图片描述

当服务器进行重启,内存中的 session 数据就会没有,此时客户端拿着之前的 sessionId 是没有办法在服务器端找到 HttpSession 对象的,就会返回 null ,进行重新登录。

完!

猜你喜欢

转载自blog.csdn.net/weixin_46103589/article/details/123738429