解决关于HTML+JS + Servlet 实现前后端请求Session不一致的问题
1、前后端不分离情况
在处理session过程中,如果前后端项目在一个容器中,session是可以被获取的。例如如下项目结构:
结构

后端的代码是基本的设置值、获取值、销毁值的内容:

运行结果



由此可见,在前后统一的项目中,session通道不会直接断掉,除非是在关闭浏览器或者session超时后才会变化。
2、前后端分离情况
结构

将对应的session_demo.html放到了前端的项目当中
运行结果(因安全策略,跨域错误)

这里对三个跨域请求的后台设置允许跨域的请求头即可。

跨域运行后获取的Session不一致


也会导致其他按钮使用服务时产生新的通道:


3、原因与解决思路
问题原因
Session的工作原理:当用户首次访问服务器时,服务器会创建一个session,并生成一个唯一的session ID。这个ID通常存储在cookie中,并随请求一起发送回客户端。后续的请求中,客户端将携带这个session ID,服务器通过这个ID来识别用户的会话,并保持状态。
1、Session 是一种服务器端的存储方式,用于存储用户的状态信息。它允许服务器在多个页面请求或访问周期中保持状态。在 HTTP 协议中,默认是无状态的,意味着每次请求都是独立的,服务器不保留任何关于客户端的信息。Session 机制通过在服务端维护状态信息,使得服务器能够在多次请求之间识别同一个客户端,当 Session 超时或被显式销毁时,服务器会停止跟踪用户的状态。如果用户关闭浏览器,客户端的 Cookie 可能会丢失,但服务器端的 Session 数据可能仍然存在,直到超时或被服务器清理。
2、在前后端分离的架构中,前端发起请求和服务端响应确实涉及到多个独立的HTTP请求,因为每次HTTP请求都是无状态的。因此该demo中也是出现了每次访问sessionId不一致的情况。
可以配置为将session ID存储在cookie中,并随每个请求发送。这样,即使请求是独立的,服务器也能够通过session ID来识别和维持用户的会话状态。
解决思路
我们需要通过Cookie来帮助我们解决前后端分离时session不一致的问题。
解决方法
每次使用session时在头部中携带cookie信息,用于保证每次请求和响应都通过cookie携带的sessionId找到对应的Session。
操作步骤
1、我们在前端进行请求的时候添加以下内容,意味传输的时候携带Cookie信息

$.ajax({...//新增 对cookie的携带xhrFields: {withCredentials: true},...})
2、后端需要设置对应的跨域ip,以及同意携带cookie的方法

@WebServlet("/setSession")
public class SetSessionServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取sessionHttpSession session = req.getSession();String user = req.getParameter("user");//新增 限制的访问地址String host = "http://localhost:5500";resp.setHeader("Access-Control-Allow-Origin",host);//新增 允许携带cookieresp.setHeader("Access-Control-Allow-Credentials","true");resp.setContentType("text/html;charset=UTF-8");if (user == null){resp.getWriter().println("session未存放数据!");}else {//session中设置属性session.setAttribute("user",user);resp.getWriter().println("session已存放数据,sessionId为:"+req.getSession().getId()); //获取session的唯一id}}
}
4.优化后运行结果



5、附件
前端项目代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>5500 前端</title>
</head><body><button id="getSession" onclick="getSession()">获取session</button><button id="setSession" onclick="setSession()">存放session</button><button id="rmSession" onclick="removeSession()">移除session</button><script src="./js/jQuery-3.7.1.js"></script><script>function getSession() {$.ajax({url: 'http://localhost:8081/Java_Web_Servlet_war_exploded/getSession',//新增 对cookie的携带xhrFields: {withCredentials: true},method: 'GET',success: function (resp) {alert(resp)}})}function setSession() {$.ajax({url: 'http://localhost:8081/Java_Web_Servlet_war_exploded/setSession',//新增 对cookie的携带xhrFields: {withCredentials: true},data: { 'user': 'admin' },method: 'POST',success: function (resp) {alert(resp)}})}function removeSession() {$.ajax({url: 'http://localhost:8081/Java_Web_Servlet_war_exploded/removeSession',//新增 对cookie的携带xhrFields: {withCredentials: true},method: 'GET',success: function (resp) {alert(resp)}})}</script>
</body></html>
后端项目结构:

后端代码-1:
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("/getSession")
public class getSessionServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取sessionHttpSession session = req.getSession();String user = (String) session.getAttribute("user");String host = "http://localhost:5500";resp.setHeader("Access-Control-Allow-Origin",host);resp.setHeader("Access-Control-Allow-Credentials","true"); resp.setContentType("text/html;charset=UTF-8");if (user == null) {resp.getWriter().println("你的session没有存放数据!");} else {resp.getWriter().println("sessionId为"+session.getId()+",存放的数据为:" + user);}}
}
后端代码-2:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;@WebServlet("/setSession")
public class SetSessionServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取sessionHttpSession session = req.getSession();String user = req.getParameter("user");String host = "http://localhost:5500";resp.setHeader("Access-Control-Allow-Origin",host);resp.setHeader("Access-Control-Allow-Credentials","true");resp.setContentType("text/html;charset=UTF-8");if (user == null){resp.getWriter().println("session未存放数据!");}else {//session中设置属性session.setAttribute("user",user);resp.getWriter().println("session已存放数据,sessionId为:"+req.getSession().getId()); //获取session的唯一id}}
}
后端代码-3:
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("/removeSession")
public class RemoveServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username = (String)req.getSession().getAttribute("user");req.getSession().removeAttribute("user");resp.setCharacterEncoding("UTF-8");resp.setContentType("text/hml;charset=UTF-8");String host = "http://localhost:5500";resp.setHeader("Access-Control-Allow-Origin",host);resp.setHeader("Access-Control-Allow-Credentials","true");resp.getWriter().println("你的sessionId是:"+req.getSession().getId()+",移除了user:"+username);}
}
相关文章:
解决关于HTML+JS + Servlet 实现前后端请求Session不一致的问题
1、前后端不分离情况 在处理session过程中,如果前后端项目在一个容器中,session是可以被获取的。例如如下项目结构: 结构 后端的代码是基本的设置值、获取值、销毁值的内容: 运行结果 由此可见,在前后统一的项目中&a…...
ECharts饼图-饼图34,附视频讲解与代码下载
引言: 在数据可视化的世界里,ECharts凭借其丰富的图表类型和强大的配置能力,成为了众多开发者的首选。今天,我将带大家一起实现一个饼图图表,通过该图表我们可以直观地展示和分析数据。此外,我还将提供详…...
如何实现安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯
在工业自动化中,实现不同品牌、不同型号设备之间的通讯是确保生产流程顺畅、高效运行的关键。本文详细介绍了安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯的具体方法。 一.软硬件需求 1.一台安川MP3300CPU301,其IP地址是192.…...
react18中如何实现同步的setState来实现所见即所得的效果
在react项目中,实现添加列表项,最后一项自动显示在可视区域范围!! 实现效果 代码实现 import { useState, useRef } from "react"; import { flushSync } from "react-dom"; function FlushSyncRef() {con…...
深入理解MVP架构模式
引言 MVP(Model-View-Presenter,模型-视图-提供者)是一种广泛应用于软件开发中的架构模式,是经典MVC(Model-View-Controller)的变种。在传统的MVC模式中,Model和View之间存在直接的依赖和数据交…...
Java面试题七
一、Java中的集合框架是如何组织的?列举几个常用的集合类。 Java中的集合框架是一个设计用来存储和操作对象集合的统一架构。它主要由两大接口派生出来:Collection和Map。这两个接口及其子接口和实现类共同构成了Java集合框架的主体。 集合框架的组织结…...
linux网络编程3——http服务器的实现和性能测试
http服务器的实现 本文使用上一篇博文实现的epollreactor百万并发的服务器实现了一个使用http协议和WebSocket协议的WebServer。 完整代码请看我的github项目 1. 水平触发(Level Trigger)与边沿触发(Edge Trigger) 1.1 水平触发 水平触发是一种状态驱动机制。当文件描述符&a…...
Docker部署Kamailio,并使用LinPhone实现网络通话
前提条件 准备一个路由器,一个服务器,两个终端设备(手机或电脑) docker部署安装 我使用的是windows系统,docker desktop 先启动Docker desktop打开cmd,输入docker命令docker run --name kamailio --rm…...
JAVA-石头迷阵小游戏
采用企业式项目结构,接下来我将分享全部代码和结构,希望大家点点关注! 这是我的结构。首先使用IDE创建一个Module,命名stone-maze,接着把自带src下的main方法删除,接着在src下创建包,包名为com.wmuj,接着创建APP类代码如下: package com.wmuj;public class App {publ…...
鸿蒙--进度条通知
主要介绍如何使用通知能力和基础组件,实现模拟下载文件,发送通知的案例。 效果 代码结构 ├──entry/src/main/ets // 代码区 │ ├──common │ │ ├──constants │ │ │ └──CommonConstants.ets // 公共常量类 │ │ └──utils │ │ ├──Logger.ets //…...
搜维尔科技:varjo xr-4开箱测评,工业用途头显,一流视觉保真度
varjo xr-4开箱测评,工业用途头显,一流视觉保真度 搜维尔科技:varjo xr-4开箱测评,工业用途头显,一流视觉保真度...
mysql数据量分库分表
一、分库分表参考阈值 分库分表是解决大规模数据和高并发访问问题的常用策略。虽然没有绝对的阈值来决定何时进行分库分表,但以下是一些参考阈值和考虑因素,可以帮助你做出决策: 1.1 数据量阈值 单表数据行数:当单表的数据行数…...
Vite创建Vue3项目以及Vue3相关基础知识
1.创建Vue3项目 1.运行创建项目命令 # 使用 npm npm create vitelatest2、填写项目名称 3、选择前端框架 4、选择语法类型 5、按提示运行代码 不出意外的话,运行之后应该会出现 下边这个页面 6.延伸学习:对比webpack和vite(这个是面试必考…...
Elasticsearch封装公共索引增删改查
什么是索引? 定义:索引是 Elasticsearch 中用于存储数据的逻辑命名空间。它由多个文档组成,每个文档是一个 JSON 格式的结构化数据对应关系:在关系数据库中,索引类似于表;而在 Elasticsearch 中࿰…...
Python异常检测:Isolation Forest与局部异常因子(LOF)详解
这里写目录标题 Python异常检测:Isolation Forest与局部异常因子(LOF)详解引言一、异常检测的基本原理1.1 什么是异常检测?1.2 异常检测的应用场景 二、Isolation Forest2.1 Isolation Forest的原理2.1.1 算法步骤 2.2 Python实现…...
Git的原理和使用(二)
1. git的版本回退 之前我们也提到过,Git 能够管理⽂件的历史版本,这也是版本控制器重要的能⼒。如果有⼀天你发现 之前前的⼯作做的出现了很⼤的问题,需要在某个特定的历史版本重新开始,这个时候,就需要版本 回退的功能…...
docker 发布镜像
如果要推广自己的软件,势必要自己制作 image 文件。 1 制作自己的 Docker 容器 基于 centos 镜像构建自己的 centos 镜像,可以在 centos 镜像基础上,安装相关的软件,之后进行构建新的镜像。 1.1 dockerfile 文件编写 首先&…...
投了15亿美元,芯片创新公司Ampere为何成了Oracle真爱?
【科技明说 | 科技热点关注】 一个数据库软件公司却想要操控一家芯片厂商,这样的想法不错。也真大胆。 目前,全球数据库巨头甲骨文Oracle已经持有Ampere Computing LLC 29%的股份,并有可能通过未来的投资选择权获得对这家芯片制造…...
vue 报告标题时间来自 elementUI的 el-date-picker 有开始时间和结束时间
要在Vue中使用 Element UI 的 el-date-picker 来选择开始时间和结束时间,并将其展示在报告中,以下是详细的实现步骤。 实现思路: 使用 Element UI 的 el-date-picker 组件,让用户选择时间范围(开始时间和结束时间&am…...
简单几何问题的通解
来,这道题怎么做?边长为2的正方形内,2个扇形的交集面积是多少?这道题一定要画辅助线,因为要用到两个扇形的交点,如果不画辅助线,这个交点相关的4个子图一个都无法求出面积,只能求出子…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
