ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Java研学-Cookie与Session

2026/9/24 23:15:54 拓冰建站 浏览量
Java研学-Cookie与Session

一 会话跟踪

1 HTTP 无状态

  HTTP 协议是无状态的,一问一答没有记忆,无法确定发出请求的用户身份。即各个请求的请求对象所包含的信息并不相同,一个会话中的多个请求之间无法共享数据,此时可以使用会话跟踪技术

2 会话跟踪技术

  Cookie 客户端会话跟踪技术
  Session 服务端会话跟踪技术(HttpSession)

3 案例

① 创建web项目,添加对应jar包(JSTL)
② login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录</title>
</head>
<body>
<form action="/http/login" method="post"><p>账号:<input type="text" name="username"></p><p>密码:<input type="password" name="password"></p><p><input type="submit" value="登录"></p>
</form>
</body>
</html>

③ LoginServlet.java

package http;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 java.io.IOException;
@WebServlet("/http/login")
public class LoginServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");if("admin".equals(username)&&"123".equals(password)){//登录成功req.setAttribute("username",username);req.getRequestDispatcher("/index.jsp").forward(req,resp);}}
}

④ index.jsp

<%--新建index.jsp,显示当前登录的用户名及提供点击查看收件箱--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>主页</title>
</head>
<body>
欢迎:${username} <br/>
<a href="/http/list">收件箱</a>
</body>
</html>

⑤ ListServlet.java

@WebServlet("/http/list")
public class ListServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");req.setAttribute("username",username);/*查询邮件列表信息*/List<String> list=new ArrayList<>();list.add("邮件一");list.add("邮件二");list.add("邮件三");req.setAttribute("list",list);req.getRequestDispatcher("/list.jsp").forward(req,resp);}
}

⑥ list.jsp

<%--显示当前用户名及其邮件,提供查询邮件内容--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>邮件列表</title>
</head>
<body>
欢迎:${username} <br/>
<c:forEach items="${list}" var="email"><a href="/http/content">${email}</a> <br/>
</c:forEach>
</body>
</html>

⑦ ContentServlet.java

@WebServlet("/http/content")
public class ContentServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");req.setAttribute("username",username);//跳转到详情页req.getRequestDispatcher("/content.jsp").forward(req,resp);}
}

⑧ content.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>邮件详情页</title>
</head>
<body>
<p>当前登录账号:${username}</p>
<p>这是邮件详情页面</p>
</body>
</html>

二 Cookie

1 概述

  Cookie(客户端技术)程序把各个用户的数据以 cookie 的形式写给用户各自的浏览器。(服务器创建Cookie存到客户端浏览器)当用户使用浏览器访问服务器中的 Web 资源时(再次访问服务器时实现数据共享),就会带着各自的数据到服务器。Web 资源此时处理的是用户各自的数据。
  传递方向:浏览器 -> 服务器(Cookie)-> 浏览器(存入)-> 服务器(获取Cookie 数据)
类似会员卡消费

2 创建 Cookie 对象

Cookie cookie = new Cookie (String name, String value)
属性方法描述
namegetName()共享数据名称(唯一)
valuegetValue()要共享的数据

3 响应 Cookie 给浏览器

// 使用响应对象中的 addCookie(Cookie 对象) 将数据响应给浏览器
resp.addCookie(cookie);

4 服务器端获取 Cookie

// 浏览器发请求时,自动将 Cookie 发送到服务器,服务器程序直接获取即可。
// 数据在请求中,使用请求对象中的 getCookies() 方法获取所有的 Cookie 对象。
Cookie[] cookies = request对象.getCookies();

5 修改 Cookie 数据

// 调用 Cookie 对象的 setValue 方法来覆盖原本的数据,或者重新创建一个同 name 的 Cookie 对象
cookie对象.setValue("大黄");// 无论哪种方式,修改的都是服务器端内存中的 Cookie 数据,和浏览器中存的 Cookie 没有关系,所以需要重新响应新的 Cookie 到浏览器中进行更新。
resp.addCookie(新的Cookie对象);

6 Cookie 分类

Cookie 总是保存在客户端中,按在客户端中的存储位置,可分为内存 Cookie 和硬盘 Cookie。
内存 Cookie 由浏览器维护,保存在内存中,浏览器关闭后就消失了,其存在时间是短暂的。硬盘
Cookie 保存在硬盘里,有一个过期时间,除非用户手工清理或到了过期时间,硬盘 Cookie 不会被删
除,其存在时间是长期的。所以,按存在时间,可分为非持久 Cookie 和持久 Cookie。
默认情况下 Cookie 属于会话 Cookie,即浏览器关闭则失效,无法使用。

7 设置 Cookie 存活时间

// 在创建 Cookie 对象之后给其设置存活时间
Cookie对象.setMaxAge(int time);
expiry 数值例子含义
大于 0setMaxAge(60)Cookie 存活时间单位为秒
等于 0setMaxAge(0)立即删除当前 Cookie 对象
小于 0setMaxAge(-1)会话 Cookie,浏览器关闭则销毁

8 删除 Cookie

// 设置 Cookie 存活时间的方法即可进行删除,一般是中途删除 Cookie,不是创建后马上删除,所以在设置删除之后需要重新发送给浏览器去更新删除
Cookie对象.setMaxAge(0);
resp.addCookie(Cookie 对象);

9 例子

① login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录</title>
</head>
<body>
<form action="/cookie/login" method="post"><p>账号:<input type="text" name="username"></p><p>密码:<input type="password" name="password"></p><p><input type="submit" value="登录"></p>
</form>
</body>
</html>

② LoginServlet

@WebServlet("/cookie/login")
public class LoginServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");if("admin".equals(username)&&"123".equals(password)){//登录成功/*登录成功将账号保存到客户端cookie*//*name共享数据名称(唯一)  value要共享的数据*//*new Cookie (String name, String value)*/Cookie cookie=new Cookie("username",username);Cookie cookie1=new Cookie("username","小黄");cookie.setValue("大黄");//设置有效时间cookie.setMaxAge(120);//设置路径cookie.setPath("/");resp.addCookie(cookie);resp.addCookie(cookie1);req.setAttribute("username",username);req.getRequestDispatcher("/index.jsp").forward(req,resp);}}
}

③ index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>主页</title>
</head>
<body>
欢迎:${username} <br/>
<a href="/cookie/list">收件箱</a>
</body>
</html>

④ ListServlet

@WebServlet("/cookie/list")
public class ListServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/*获取cookie信息*/Cookie[] cookies = req.getCookies();if (cookies!=null){for (Cookie cookie : cookies) {// 获取账号的cookieif (cookie.getName().equals("username")){// 删除cookiecookie.setMaxAge(0);resp.addCookie(cookie);String username = cookie.getValue();// 将账号存储到作用域req.setAttribute("username",username);}}}/*查询邮件列表信息*/List<String> list = new ArrayList<>();list.add("邮件一");list.add("邮件二");list.add("邮件三");req.setAttribute("list", list);req.getRequestDispatcher("/list.jsp").forward(req, resp);}
}

⑤ list.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>邮件列表</title>
</head>
<body>
欢迎:${username} <br/><p>当前登录账号:${cookie.username.value}</p>
<c:forEach items="${list}" var="email"><a href="/cookie/content">${email}</a> <br/>
</c:forEach>
</body>
</html>

⑥ ContentServlet

@WebServlet("/cookie/content")
public class ContentServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/*获取cookie信息*/Cookie[] cookies = req.getCookies();if (cookies!=null){for (Cookie cookie : cookies) {//获取账号的cookieif (cookie.getName().equals("username")){String username = cookie.getValue();//将账号存储到作用域req.setAttribute("username",username);}}}//跳转到详情页req.getRequestDispatcher("/content.jsp").forward(req,resp);}
}

⑦ content.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>邮件详情页</title>
</head>
<body>
<p>当前登录账号:${username}</p>
<p>这是邮件详情页面</p>
</body>
</html>

10 Cookie 的域和路径

① 作用
  使浏览器能够识别 Cookie 发送给对应的服务器,以及识别哪些请求需要携带 Cookie
  默认Cookie 都带了服务器的识别标识以及需要带 Cookie 的资源标识,保护Cookie 中的数据不被带到其他服务器中去。
② 域
  识别服务器,包含 IP:端口或域名:端口,可通过 Cookie 对象的 setDomain 方法设置。默认Cookie 中的域是创建 Cookie 的服务器的域名。域名分类:
一级(主)域名:bilibili.com
多级域名:news.bilibili.com
若想要在相同的主域名下来共享 Cookies 数据,例如,扣扣空间,扣扣音乐共用账号,则只需要
设置 Cookie 的 domain 即可。若主域不同,是无法共享 Cookie 数据。

cookie.setDomain(".bilibili.com");

③ 路径
  识别资源,可通过 Cookie 对象的 setPath 方法设置。默认为创建 Cookie 的资源的路径。
  例:/cookie/login 创建 Cookie,则 path 为 /cookie,则访问 /cookie 开头的资源都会携带该Cookie。
  若想要在访问服务器上的任意资源都带上 Cookie,则只需要在创建 Cookie 之后设置下 path 为 / 即可。

cookie.setPath("/");

④ 小结
若主域不同,不管 path 如何,都无法带上其他主域的 Cookie。
若主域相同,且 path 也为 /,则访问该域下的任意资源都会携带该域的 Cookie。

三 Session

1 概述

  Session 是服务器端技术(服务器创建,存在服务器),服务器运行时可为每个用户的浏览器创建一个其独享的 session 对象
  用户在访问服务器的 Web 资源时,可以把各自的数据放在各自的 session 中,当用户再去访问服务器中的其它 Web 资源时(再次访问服务器时实现数据共享),其它 Web 资源再从用户各自的 session 中取出数据为用户服务。(通过sessionId识别不同的浏览器用户)
原理图
  Session 底层依赖 Cookie 来传递 Session 的 id 值。所以浏览器关闭后 Session 就无法使用了(sessionId 丢失)。服务器会在 30 分钟内清除无操作的 Session 对象。存 sessionId 的 Cookie 为会话Cookie。

2 方法

① 获取session(HttpServletRequest的API)

方法作用
getSession(true)判断是否存在 Session,存在则获取,不存在则创建新 Session 对象返回
getSession(false)判断是否存在 Session,存在则获取,不存在则返回 null
getSession()存在则获取,不存在则创建新 Session 对象返回

② 数据共享(HttpSession的API)

方法作用
setAttribute(String name, Object value)设置属性名和属性值
getAttribute(String name)通过属性名去获取属性值
removeAttribute(String name)从 Session 中移除指定属性名的属性值
invalidate()移除整个 Session 对象,删除所有的属性和属性值

3 例子

① login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登录</title>
</head>
<body>
<form action="/session/login" method="post"><p>账号:<input type="text" name="username"></p><p>密码:<input type="password" name="password"></p><p><input type="submit" value="登录"></p>
</form>
</body>
</html>

② LoginServlet

@WebServlet("/session/login")
public class LoginServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {String username = req.getParameter("username");String password = req.getParameter("password");if("admin".equals(username)&&"123".equals(password)){//登录成功//账号存储sessionHttpSession session = req.getSession();//获取sessionidString id = session.getId();System.out.println(id);//设置超时时间session.setMaxInactiveInterval(60*5);session.setAttribute("username",username);req.getRequestDispatcher("/index.jsp").forward(req,resp);}}
}

③ index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>主页</title>
</head>
<body>
欢迎:${username} <br/>
<a href="/session/list">收件箱</a>
</body>
</html>

④ ListServlet

@WebServlet("/session/list")
public class ListServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/*查询邮件列表信息*/List<String> list=new ArrayList<>();list.add("邮件一");list.add("邮件二");list.add("邮件三");req.setAttribute("list",list);// 从Session中获取数据System.out.println(req.getSession().getAttribute("username"));req.getRequestDispatcher("/list.jsp").forward(req,resp);}
}

⑤ list.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>邮件列表</title>
</head>
<body>
欢迎:${username} <br/>
<p>当前登录账号:${sessionScope.username}</p>
<c:forEach items="${list}" var="email"><a href="/session/content">${email}</a> <br/>
</c:forEach>
</body>
</html>

⑥ ContentServlet

@WebServlet("/session/content")
public class ContentServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 从session中获取数据System.out.println(req.getSession().getAttribute("username"));//跳转到详情页req.getRequestDispatcher("/content.jsp").forward(req,resp);}
}

⑦ content.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>邮件详情页</title>
</head>
<body>
<p>当前登录账号:${username}</p>
<p>这是邮件详情页面</p>
</body>
</html>