Servlet API Cookie和Session

简介: 我们在前文【和面试官畅谈「HTTP协议」 3.3.6】中已经提及了Servlet在会话管理操作中的Cookie与Session,但在上篇文章中有些过于理论化,在这篇文章中,我们结合具体的API和综合案例来更深刻的理解Cookie和Session。

1.回顾Cookie与Session


在我们浏览一些网页,比如b站或者码云时,需要进行用户登录的操作,这个操作只有在首次访问时才会有,如果之前已经进行过了,浏览器就会保存下来用户信息,下次再访问该页面时直接登录即可,不必再进行输入。


每位用户在首次进行登陆时,都会在服务器端创建一个Session会话,在Session中存储了对应用户的一些属性,而且每个Session都有唯一身份标识sessionID;服务器存储管理着很多Session会话


在客户端的Cookie中,就存储着sessionID,在客户端进行登录后发送给服务器的请求中有该sessionID,服务器在存储的所有Session会话中,根据sessionID进行查找,如果找到了就返回给客户端对应的Session会话响应。


类似于我们去医院时,用到的就诊卡,就诊卡就相当于Cookie,包含了当前患者的关键信息,我们刷卡后就能查到自己过往病历的具体情况,每位患者的情况就是一个Session会话,存储在医院的服务器上。


2.核心方法


2.1 HttpServletRequest类中的相关方法


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


getSession方法,既能用于获取到服务器上的会话,也能用于创建会话;在调用getSession时,具体要做的事情是:


1.创建会话


首先先获取到请求中cookie里面的sessionID字段(相当于会话的身份标识),判断这个sessionID是否在当前的服务器上存在;

如果不存在,则进入创建会话逻辑。


创建会话,会创建一个HttpSession对象,并且生成一个sessionID(通常是16进制表示的很长的数字,能够保证唯一性),接下来就会把这个sessionID作为key,把这个HttpSession对象作为value,把这个键值对保存到服务器内存中,一个类似“哈希表”的结构。


然后,服务器会返回一个HTTP响应,把sessionID通过Set-Cookie字段返回给浏览器,浏览器就可以保存这个sessionID到Cookie中了。


2.获取会话


首先先获取到请求中cookie里面的sessionID字段(相当于会话的身份标识),判断这个sessionID是否在当前的服务器上存在;

如果存在,就直接查询出这个HttpSession对象,并且通过返回值返回回去。


2.2 HttpServletResponse 类中的相关方法

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


该方法添加进来的键值对,会作为HTTP响应中的Set-Cookie字段来表示


2.3 HttpSession 类中的相关方法


一个HttpSession对象里面包含多个键值对,我们可以往HttpSession中存任何我们需要的信息(Key必须是String,value是一个Object)。


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


下图展示在服务器中HttpSession的存储。


微信图片_20230111172815.png

2.4 Cookie 类中的相关方法


每个Cookie对象也是一个键值对,这些键值对的格式,使用;来分割多个键值对,使用=来分割键和值,这些键值对都会在请求中,通过Cookie字段传给服务器,服务器收到请求之后,就会进行解析,解析成Cookie[]这样的形式。

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


Cookie中,可以保存任意自定制的键值对,如果是一般的键值对,直接通过HttpServletRequest类中的getCookies方法来获取,如果是特殊的键值对(表示sessionID的键值对),不需要使用getCookies,直接用HttpServletRequest类中的getSession就可以帮我们自动从Cookie中获取sessionID了。


3.综合案例


3.1 实现用户登录


首先我们来梳理实现网页用户登录的逻辑:

微信图片_20230111172811.png

下边就是具体的开发流程:


一:前后端约定接口(确定交互的数据格式类型)

该次开发共需要实现两个接口,一个接口负责登录,另一个接口负责获取主页。


微信图片_20230111172806.png

微信图片_20230111172802.png

二:编写前端交互页面(基于form表单构造POST请求)


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



界面预览:

微信图片_20230111172759.png

三:编写处理登录请求的后端Servlet代码

此处的验证登录逻辑,应该与数据库进行交互,为了简便,就不再与数据库进行交互了。


处理思路:


  • 从请求中获取用户名和密码
  • 验证用户名和密码
  • 如果验证通过,则创建会话,并把username
  • 等属性加入会话中,创建好会话后,响应重定向到主页index
  • 如果验证不通过,告知验证失败即可
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        resp.setCharacterEncoding("utf8");
        //获取用户用户名
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        //验证用户
        if("lisi".equals(username)&&"123".equals(password)) {
            //登录成功
            //创建会话,为后续登录的页面做准备
            HttpSession httpSession= req.getSession(true);
            httpSession.setAttribute("username",username);
            //初始情况下设置登录次数
            httpSession.setAttribute("count",0);
            resp.sendRedirect("index");
        } else {
            resp.getWriter().write("登录失败!");
        }
    }
}


四:编写获取主页请求的后端Servlet代码


处理思路:


  • 获取会话
  • 取出会话信息,将主页返回次数加一并写回到会话信息中
  • 返回一个简单的页面
@WebServlet("/index")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取会话,参数需要是false
        HttpSession httpSession=req.getSession(false);
        //取出会话信息
        String username=(String)httpSession.getAttribute("username");
        Integer count=(Integer)httpSession.getAttribute("count");
        //访问次数加1
        count++;
        //写回到会话中
        httpSession.setAttribute("count",count);
        //构造页面
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write("<h3>hello!"+username+"</h3> <h4>这个主页已经被访问了"+count+"次</h4>");
    }
}


运行测试:


微信图片_20230111172754.gif

在整个过程中共有三次交互过程:


一:再搜索栏输入URL,相当于是浏览器给服务器发送了GET请求,服务器返回前端登录页面


微信图片_20230111172749.png

二:输入用户名、密码后点击登录,浏览器给服务发送了请求登录的POST请求,服务器在验证请求中的用户名、密码正确后,返回给浏览器跳转到登陆后个人页面的重定向302响应.


微信图片_20230111172746.png

三:在浏览器接收到服务器传来的重定向响应后,又重新向服务器发送重定向响应中指定跳转路径的GET请求,服务器在接收到该请求后返回登录后的个人前端页面。


微信图片_20230111172742.png

3.2 文件上传


文件上传,也是我们日常Servlet开发经常会涉及到的操作。

其具体操作流程是,前端通过form-data类型的form表单,来构造HTTP请求,服务器通过getPart方法,来取到Part对象,再通过该对象就能获取到文件信息了。


核心方法:

HttpServletRequest类方法


方法 描述
Part getPart(String name) 获取请求中给定name的文件
Collection getParts() 获取所有的文件


Part类方法


方法 描述
String getSubmittedFileName() 获取提交的文件名
String getContentType() 获取提交的文件类型
long getSize() 获取文件的大小
void write(String path) 把提交的文件数据写入磁盘文件


代码示例:文件上传到服务器


前端交互:

注意在form标签中加入:enctype="multipart/form-data"


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="upload" method="post" enctype="multipart/form-data">
        <input type="file" name="myfile">
        <input type="submit" value="提交">
    </form>
</body>
</html>


后端处理代码:

实现思路:


从请求中获取Port对象

调用Port对象的方法(例如写入磁盘)

返回响应

注意加上@MultipartConfig注解


效果预览:

1.微信图片_20230111172732.png

2.

.微信图片_20230111172728.png


3.

微信图片_20230111172725.png


4.

微信图片_20230111172718.png


相关文章
|
3月前
|
存储 编解码 应用服务中间件
会话跟踪技术(Session 以及Cookie)
会话跟踪技术(Session 以及Cookie)
|
13天前
|
存储 JavaScript 前端开发
Cookie 反制策略详解:Cookie加解密原理、Cookie和Session机制、Cookie hook、acw_sc__v2、jsl Cookie调试、重定向Cookie
Cookie 反制策略详解:Cookie加解密原理、Cookie和Session机制、Cookie hook、acw_sc__v2、jsl Cookie调试、重定向Cookie
34 1
|
15天前
|
存储 安全 搜索推荐
【JavaWeb 秘籍】Cookie vs Session:揭秘 Web 会话管理的奥秘与实战指南!
【8月更文挑战第24天】本文以问答形式深入探讨了Web开发中关键的会话管理技术——Cookie与Session。首先解释了两者的基本概念及工作原理,随后对比分析了它们在存储位置、安全性及容量上的差异。接着,通过示例代码详细介绍了如何在JavaWeb环境中实现Cookie与Session的操作,包括创建与读取过程。最后,针对不同应用场景提供了选择使用Cookie或Session的指导建议,并提出了保障二者安全性的措施。阅读本文可帮助开发者更好地理解并应用这两种技术。
26 1
|
19天前
|
存储 安全 搜索推荐
深入探讨Session和Cookie的概念、用途以及如何在Java Web开发中有效地使用它们进行用户状态管理。
在Java Web开发中,Session和Cookie是管理用户状态的核心技术。Session存储于服务器端,通过唯一的Session ID识别用户,确保数据安全与隐私;Cookie则存储于客户端,用于记录用户偏好等信息。两者各有优势:Session适合存储敏感数据,但需合理管理避免资源浪费;Cookie便于持久化存储,但在安全性上需谨慎设置。开发者可通过Servlet API轻松操作二者,实现个性化用户体验与应用性能优化。
17 2
|
19天前
|
存储 缓存 安全
Cookie和Session
【8月更文挑战第20天】
13 1
|
26天前
|
存储 JSON JavaScript
震撼!Cookie、Session、Token、JWT 终极对决:揭开 Web 认证的神秘面纱!
【8月更文挑战第13天】Web 开发中,Cookie、Session、Token 和 JWT 常混淆。Cookie 是服务器给客户端的小信息片,如登录状态,每次请求都会返回。Session 则是服务器存储的用户数据,通过 Session ID 追踪。Token 类似通行证,证明客户端身份且可加密。JWT 是结构化的 Token,含头部、载荷及签名,确保数据完整性和安全性。
34 4
|
8天前
|
C# 开发者 Windows
WPF遇上Office:一场关于Word与Excel自动化操作的技术盛宴,从环境搭建到代码实战,看WPF如何玩转文档处理的那些事儿
【8月更文挑战第31天】Windows Presentation Foundation (WPF) 是 .NET Framework 的重要组件,以其强大的图形界面和灵活的数据绑定功能著称。本文通过具体示例代码,介绍如何在 WPF 应用中实现 Word 和 Excel 文档的自动化操作,包括文档的读取、编辑和保存等。首先创建 WPF 项目并设计用户界面,然后在 `MainWindow.xaml.cs` 中编写逻辑代码,利用 `Microsoft.Office.Interop` 命名空间实现 Office 文档的自动化处理。文章还提供了注意事项,帮助开发者避免常见问题。
28 0
|
2月前
|
存储 安全 搜索推荐
Cookie和Session的区别,99%的程序员都不知道的细节!
大家好,我是小米,在Web开发中,Cookie和Session是两种重要的状态管理工具。它们有着不同的存储位置、安全性和应用场景。本篇文章将详细解析它们的区别和应用,让你在开发过程中能够更加游刃有余。让我们一起深入了解吧!
50 1
|
28天前
Error unprotecting the session cookie.The key {...} was not found in the key ring.
Error unprotecting the session cookie.The key {...} was not found in the key ring.
47 0
|
28天前
Error unprotecting the session cookie.The payload was invalid.
Error unprotecting the session cookie.The payload was invalid.
49 0