Servlet知识详解(2)

文章目录

一、Cookie和Session

1. Cookie和Session的介绍

Cookie 是HTTP 协议中一个重要的字段,同时也是浏览器和客户端这边保存数据的一种比较古老的方式。

Cookie从哪来?服务器产生的,通过HTTP 响应 的set-Cookie 字段来进行设置,返回给浏览器的。
Cookie怎么存?在浏览器这边存储,浏览器会根据域名/地址 ,来分别存储Cookie。
Cookie到哪去?会在下次请求中自动被添加到请求中,发给服务器。
Cookie存的是什么?存的是字符串,是键值对结构的字符串,此处的键值对都是程序员自定义的。

Session 称为“会话”,HTTP协议,本身是无状态的
无状态的意思是:某个用户A,对服务器进行了两次请求,第一次请求和第二次请求,对于服务器来说,是感知不到关联关系的。但实际开发中,又需要有状态,用户登录完成之后,后续再访问这个网站的时候,就需要知道用户的身份信息。

Session是在服务器中存储的,可以简单地把Session想象成一个hash表,key 就是 sessionId,value 就是程序员自定义的数据(可以存储用户的身份信息),下面会实现一个Session,自己去体会。

Cookie 和 Session 之间需要相互配合。

2. 浏览器和服务器使用Cookie和Session的交互逻辑

在这里插入图片描述
这张图的关键点就在于:服务器可以得知第二次这个请求是哪个用户发来的,并根据用户信息去更新数据

详细过程
如:首先用户登录后,因为服务器中没有存储对应的sessionId,因此就为其分配sessionId,value中就保存它的用户名和密码等信息,响应中有Set-Cookie字段来告诉浏览器,该用户的session为什么什么。等该用户点到购物车的时候,浏览器就拿着Cookie(包含sessionId)给服务器,服务器就会根据该sessionId去查找,找到对应的sessionId后,取出value里面的userId,再根据userId去数据库中查找,找出指定userId的购物车数据。

上面只不过是典型的登录流程,除了服务器在Set-Cookie中放入sessionId外,其实可以不放sessionId,而是可以直接把用户信息序列化,通过Set-Cookie返回给浏览器,这样也是可行的

只需要把浏览器的两个请求能够联系起来就行,进行联系的不一定非得是sessionId,也可以是userId,也可以是其它ID,都是可以的。
使用sessionId只是常用的做法,这样做的好处是,可以方便实现“注销操作“。在服务器这边把 session 哈希表中对应的键值对给删了即可。返回sessionId 也有助于保护用户的隐私。

此处所说的cookie和session 的联动,主要是针对主流的网页进行实现。如果是更加新的一些网页,实现的时候完全可以不依赖 cookie,cookie 存在的目的就是为了在浏览器这边本地存储。还可以使用 localStorage 和 indexDB 来代替cookie 。

3. 对Cookie和Session操作的API

上面讲的都是一些理论知识,不过有了前面的理论,了解Cookie和Session 的交互过程,我们才能更好的在代码中体现。

Servlet中对上面的流程大部分都已经封装好了,我们实际上操作的过程不算很多,只需要一些简单的API调用即可。

核心方法:
HttpServletRequest 类中的相关方法(常用)

方法

描述

HttpSession getSession()

在服务器中获取会话. 参数如果为 true, 则当不存在会话时新建会话; 参数如果为 false, 则当不存在会话时返回 null

Cookie[] getCookies()

返回一个数组, 包含客户端发送该请求的所有的 Cookie 对象. 会自动把Cookie 中的格式解析成键值对

HttpServletResponse 类中的相关方法

方法

描述

void addCookie(Cookie cookie)

把指定的 cookie 添加到响应中

HttpSession 类中的相关方法(常用)
一个 HttpSession 对象里面包含多个键值对. 我们可以往 HttpSession 中存储任何我们需要的信息。

方法

描述

Object getAttribute(String name)

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

void setAttribute(String name, Object value)

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

boolean isNew()

判定当前是否是新创建出的会话

本来sessionId和value就是一个键值对,而其中的value 就是HttpSession ,HttpSession里存储的又是键值对,该类里面的key和value都是由程序员自己定义的,之所以用键值对的方式表示HttpSession,是为了方便程序员自定义数据

4. 实现简单的用户登录

前端:

    <form action="login" method="POST">
        用户名:<input type="text" name="username">
        <br>
        密码:<input type="text" name="password">
        <br>
        <input type="submit" value="登录">
    </form>

页面:在这里插入图片描述
后端:
实现LoginServlet 类

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        // 1. 先从请求的 body 中读取 用户名 和 密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        // 2. 判定一下用户名密码是否正确(此处就不读数据库了, 直接固定用户名密码, 就是 zhangsan 123
        if (!"zhangsan".equals(username) || !"123".equals(password)) {
            // 登录失败!!
            resp.getWriter().write("登录失败!");
            return;
        }
        System.out.println("登录成功");
        // 3. 登录成功, 则创建出一个会话来~, 会话不存在就创建
        //    会话是根据请求中的 sessionId 来查的. sessionId 是 在 Cookie 中的.
        //    但是此处是首次登录, 此时请求中是没有 Cookie (Cookie 是服务器返回)
        //    此处就会触发 "找不到就创建" 这样的流程~
        //    同时这里进行的操作: 先创建出一个 HttpSession 对象(作为 value)
        //    再生成一个随机的字符串, 作为 sessionId (作为 key)
        //    把这个 key 和 value 插入到 hash 表中~~
        //    同时把这个生成的 sessionId 通过 Set-Cookie 字段返回给浏览器
        HttpSession httpSession = req.getSession(true);
        //    还可以存入程序猿自定义的数据, 可以存入身份信息(用户名和登录次数)
        httpSession.setAttribute("username", "zhangsan");
        httpSession.setAttribute("loginCount", 0);
        //登录成功之后,就创建了HttpSession对象,同时生成了sessionId
        // 4. 让页面跳转到主页, 使用重定向的方式实现即可
        resp.sendRedirect("index");
    }
}

实现IndexServlet 类:

@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 根据当前用户请求中的 sessionId, 获取到用户信息, 并显示到页面上.
        resp.setContentType("text/html; charset=utf-8");
        // 1. 判定当前用户是否已经登录了. (请求中有没有 sessionId, 以及 sessionId 是否合法)
        //    如果会话不存在, 就不能创建了~ 只是查询, 不是登录
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null) {
            // 当前没有找到合法会话, 当前用户尚未登录, 重定向到 login.html, 让用户进行登录
            resp.sendRedirect("login.html");
            return;
        }
        // 2. 如果用户已经登录, 就可以从 HttpSession 中拿到用户信息了.
        String username = (String) httpSession.getAttribute("username");
        Integer loginCount = (Integer) httpSession.getAttribute("loginCount");
        loginCount = loginCount + 1;
        httpSession.setAttribute("loginCount", loginCount);
        // 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值