当前位置: 首页 > news >正文

解决关于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过程中&#xff0c;如果前后端项目在一个容器中&#xff0c;session是可以被获取的。例如如下项目结构&#xff1a; 结构 后端的代码是基本的设置值、获取值、销毁值的内容&#xff1a; 运行结果 由此可见&#xff0c;在前后统一的项目中&a…...

ECharts饼图-饼图34,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个饼图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供详…...

如何实现安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯

在工业自动化中&#xff0c;实现不同品牌、不同型号设备之间的通讯是确保生产流程顺畅、高效运行的关键。本文详细介绍了安川MP3300运动控制器与西门子1200系列PLC进行ModbusTCP通讯的具体方法。 一&#xff0e;软硬件需求 1.一台安川MP3300CPU301&#xff0c;其IP地址是192.…...

react18中如何实现同步的setState来实现所见即所得的效果

在react项目中&#xff0c;实现添加列表项&#xff0c;最后一项自动显示在可视区域范围&#xff01;&#xff01; 实现效果 代码实现 import { useState, useRef } from "react"; import { flushSync } from "react-dom"; function FlushSyncRef() {con…...

深入理解MVP架构模式

引言 MVP&#xff08;Model-View-Presenter&#xff0c;模型-视图-提供者&#xff09;是一种广泛应用于软件开发中的架构模式&#xff0c;是经典MVC&#xff08;Model-View-Controller&#xff09;的变种。在传统的MVC模式中&#xff0c;Model和View之间存在直接的依赖和数据交…...

Java面试题七

一、Java中的集合框架是如何组织的&#xff1f;列举几个常用的集合类。 Java中的集合框架是一个设计用来存储和操作对象集合的统一架构。它主要由两大接口派生出来&#xff1a;Collection和Map。这两个接口及其子接口和实现类共同构成了Java集合框架的主体。 集合框架的组织结…...

linux网络编程3——http服务器的实现和性能测试

http服务器的实现 本文使用上一篇博文实现的epollreactor百万并发的服务器实现了一个使用http协议和WebSocket协议的WebServer。 完整代码请看我的github项目 1. 水平触发(Level Trigger)与边沿触发(Edge Trigger) 1.1 水平触发 水平触发是一种状态驱动机制。当文件描述符&a…...

Docker部署Kamailio,并使用LinPhone实现网络通话

前提条件 准备一个路由器&#xff0c;一个服务器&#xff0c;两个终端设备&#xff08;手机或电脑&#xff09; docker部署安装 我使用的是windows系统&#xff0c;docker desktop 先启动Docker desktop打开cmd&#xff0c;输入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开箱测评&#xff0c;工业用途头显&#xff0c;一流视觉保真度 搜维尔科技&#xff1a;varjo xr-4开箱测评&#xff0c;工业用途头显&#xff0c;一流视觉保真度...

mysql数据量分库分表

一、分库分表参考阈值 分库分表是解决大规模数据和高并发访问问题的常用策略。虽然没有绝对的阈值来决定何时进行分库分表&#xff0c;但以下是一些参考阈值和考虑因素&#xff0c;可以帮助你做出决策&#xff1a; 1.1 数据量阈值 单表数据行数&#xff1a;当单表的数据行数…...

Vite创建Vue3项目以及Vue3相关基础知识

1.创建Vue3项目 1.运行创建项目命令 # 使用 npm npm create vitelatest2、填写项目名称 3、选择前端框架 4、选择语法类型 5、按提示运行代码 不出意外的话&#xff0c;运行之后应该会出现 下边这个页面 6.延伸学习&#xff1a;对比webpack和vite&#xff08;这个是面试必考…...

Elasticsearch封装公共索引增删改查

什么是索引&#xff1f; 定义&#xff1a;索引是 Elasticsearch 中用于存储数据的逻辑命名空间。它由多个文档组成&#xff0c;每个文档是一个 JSON 格式的结构化数据对应关系&#xff1a;在关系数据库中&#xff0c;索引类似于表&#xff1b;而在 Elasticsearch 中&#xff0…...

Python异常检测:Isolation Forest与局部异常因子(LOF)详解

这里写目录标题 Python异常检测&#xff1a;Isolation Forest与局部异常因子&#xff08;LOF&#xff09;详解引言一、异常检测的基本原理1.1 什么是异常检测&#xff1f;1.2 异常检测的应用场景 二、Isolation Forest2.1 Isolation Forest的原理2.1.1 算法步骤 2.2 Python实现…...

Git的原理和使用(二)

1. git的版本回退 之前我们也提到过&#xff0c;Git 能够管理⽂件的历史版本&#xff0c;这也是版本控制器重要的能⼒。如果有⼀天你发现 之前前的⼯作做的出现了很⼤的问题&#xff0c;需要在某个特定的历史版本重新开始&#xff0c;这个时候&#xff0c;就需要版本 回退的功能…...

docker 发布镜像

如果要推广自己的软件&#xff0c;势必要自己制作 image 文件。 1 制作自己的 Docker 容器 基于 centos 镜像构建自己的 centos 镜像&#xff0c;可以在 centos 镜像基础上&#xff0c;安装相关的软件&#xff0c;之后进行构建新的镜像。 1.1 dockerfile 文件编写 首先&…...

投了15亿美元,芯片创新公司Ampere为何成了Oracle真爱?

【科技明说 &#xff5c; 科技热点关注】 一个数据库软件公司却想要操控一家芯片厂商&#xff0c;这样的想法不错。也真大胆。 目前&#xff0c;全球数据库巨头甲骨文Oracle已经持有Ampere Computing LLC 29%的股份&#xff0c;并有可能通过未来的投资选择权获得对这家芯片制造…...

vue 报告标题时间来自 elementUI的 el-date-picker 有开始时间和结束时间

要在Vue中使用 Element UI 的 el-date-picker 来选择开始时间和结束时间&#xff0c;并将其展示在报告中&#xff0c;以下是详细的实现步骤。 实现思路&#xff1a; 使用 Element UI 的 el-date-picker 组件&#xff0c;让用户选择时间范围&#xff08;开始时间和结束时间&am…...

简单几何问题的通解

来&#xff0c;这道题怎么做&#xff1f;边长为2的正方形内&#xff0c;2个扇形的交集面积是多少&#xff1f;这道题一定要画辅助线&#xff0c;因为要用到两个扇形的交点&#xff0c;如果不画辅助线&#xff0c;这个交点相关的4个子图一个都无法求出面积&#xff0c;只能求出子…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...