Tomcat 服务器 Session的实现

实现Tomcat服务器上不同Web项目间session共享的解决方案 本文还有配套的精品资源,点击获取 简介:在Java Web开发中,Tomcat作为应用服务器处理HTTP请求并托管Web应用程序。部署多个Web项目在同一服务器时,session共享能提升用户体验。本文探讨了几种session共享方法:通过共享Cookie、使用ServletContextListener、实现单点登录(SSO)、配置共享Manager组件、使用分布式ses... 阅读详情

session

结合《HTTP权威指南》和《How Tomcat Works》话一话我所理解的Session以及Tomcat下的实现方式!


Session是什么?

在开始正式讨论之前,我们首先探讨一些原理性的问题,什么是session,它可以用来做什么!
我们每天都会浏览各种网站,不同的用户浏览网站的目的不同,在该网站上留下的历史也不同,为了提供个性化的服务,服务器就需要记录和识别用户!一个用户可以在不同地方,利用不同设备访问网站,服务器如何知道“我是谁”呢?很多人一下子就想到用户名和密码,对没错,这的确是一种方式。但是网站访问是一个连续的过程,每次访问都携带用户名和密码的做法提高了用户风险,更重要的是,如何解决非注册用户的问题呢,一些用户习惯每天打开新闻站点,但是他只是浏览信息,不想输入任何个人信息去注册网站,这样的用户如何提供个性化服务呢!

看看现实生活中政府是如何识别“我是谁”,并且提供差异服务的。我们每个人都有一张身份证,是政府机关发给我们的。身份证只是一个人的基本信息,例如姓名,身份证号,住址。上面并不会纪录你的学历,你的婚姻状况。当我需要这些信息的时候,我们提供身份证,相关的单位就会提供相关证明,例如在很多省份在购买房产的时候,需要未婚人士提供一个单身证明,我们只要向相应的政府机构提供身份证,就可以获取到这些“被认可的”信息。
可以抽象的理解为,政府颁发了一个身份证给个人,当你需要政府服务的时候,只需要提供你的身份证,这样政府就会从它自己维护的数据中,获取你的更多个人信息,提供差异化服务。
身份证会具有有效期,当身份证过期的时候,需要从新申请,否则持有的身份证就会无效。

哪么,可否效仿这个过程,网站服务器“颁发”一个身份证给用户,用户每次访问都带着这个身份证,网站服务器根据这个身份证获取用户更多信息,这样不就可以获取个性化服务了么!当身份证过期的时候,需要用户从新申请。

现在我们要讨论的问题渐渐浮出水面了。我们和服务器之间的交互过程,可以理解为一个Session,直白的翻译就是一次会话,而每次我们携带的身份信息,是通过Cookie的方式实现的。

在《HTTP权威指南中》这样描述了用Cookie实现的身份认证过程。

cookie

Cookie的作用就好像服务器,给用户发的一个身份证,上面写着,“我叫XX,地址”,用户访问服务器的时候,携带着这些信息,服务器会读取所有的这些信息。

用户首次访问Web 站点时,服务器对用户一无所知。为了能够在用户下次访问的时候,识别出这个用户,站点给用户“拍上”一个独有的cookie,这样以后服务器就可以识别出这个用户了。Cookie包含了一个由名字=值这样的信息构成的列表,并通过Set-Cookie或者Set-Cookie2 HTTP响应首部返回给用户。浏览器再下次访问站点的时候,会在Cookie请求首部中,原封不动地携带服务器发送过来的Cookie数据。

其实Cookie的可以携带任意信息,它也是服务器维护用户Session的最常用的手段的一种。服务器真对用户的访问,创建一个拥有唯一ID的Session,然后通过Set-Cookie把这个SessionId贴到用户身上。用户每次访问服务器都带着这个SessionId,服务器就可以通过SessionId找出对应的Session对象,识别出用户了。

当然这仍然是很抽象的描述,不同的Web服务器实现这个机制也有很大差异。下面通过Tomcat的源代码来看一下Tomcat作为Web服务器,如何维护Session,如何根据Cookie来获取用户Session的。


Tomcat Session的实现

大概的流程可以分为如下几个步骤。

1. 从Cookie中获取SessionID

针对每一次用户的请求,HTTPProcessor负责解析用户请求,会对HTTP请求头部分析,如果发现存在jsessionid这样的cookie,就把cookie值set到HttpSevletRequest对象中

if (name.equals("cookie")) {
   Cookie cookies[] = RequestUtil.parseCookieHeader(value);
   for (int i = 0; i < cookies.length; i++) {
      if (cookies[i].getName().equals("jsessionid")) {
         // Override anything requested in the URL
         if (!request.isRequestedSessionIdFromCookie()) {
            // Accept only the first session id cookie
            request.setRequestedSessionId(cookies[i].getValue());
            request.setRequestedSessionCookie(true);
            request.setRequestedSessionURL(false);
         }
      }
      request.addCookie(cookies[i]);
   }
}

2. 获取Session,如果不存在创建新Session

当需要使用Session访问其中内容的时候,会调用Request的getSession方法

private HttpSession doGetSession(boolean create) {
        // There cannot be a session if no context has been assigned yet
        if (context == null)
            return (null);

        // Return the current session if it exists and is valid
        if ((session != null) && !session.isValid())
            session = null;
        if (session != null)
            return (session.getSession());

        // Return the requested session if it exists and is valid
        Manager manager = null;
        if (context != null)
            manager = context.getManager();

        if (manager == null)
            return (null);      // Sessions are not supported

        if (requestedSessionId != null) {
            try {
                session = manager.findSession(requestedSessionId);
            } catch (IOException e) {
                session = null;
            }
            if ((session != null) && !session.isValid())
                session = null;
            if (session != null) {
                return (session.getSession());
            }
        }

        // Create a new session if requested and the response is not committed
        if (!create)
            return (null);
        if ((context != null) && (response != null) &&
            context.getCookies() &&
            response.getResponse().isCommitted()) {
            throw new IllegalStateException
              (sm.getString("httpRequestBase.createCommitted"));
        }

        session = manager.createSession();
        if (session != null)
            return (session.getSession());
        else
            return (null);

}

简而言之如果之前设置过SessionId,那么request会在Manager中寻找Session,如果有则直接使用,如果不存在,那么就让Manager创建一个Session。

需要补充一点,Tomcat的Session的创建和维护是通过实现Manager接口实现的,其中StandardManager是标准实现,当然真对不同应用场景,例如集群Tomcat,Session需要各个服务器共享,则需要使用不同的Manager来实现Session的维护。

3. 如果Session存在,在Response中,设置SetCookie
在HTTPResponseBase中的SetHeader方法中,检查Request中Session对象是否存在,如果存在,则把SessionId写在Set-Cookie首部

if ((session != null) && session.isNew() && (getContext() != null) && getContext().getCookies()) {
	Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getId());
	cookie.setMaxAge(-1);
	String contextPath = null;
	if (context != null)
	    contextPath = context.getPath();
	if ((contextPath != null) && (contextPath.length() > 0))
	    cookie.setPath(contextPath);
	else
	    cookie.setPath("/");
	if (hreq.isSecure())
		cookie.setSecure(true);
	addCookie(cookie);
}

	// Send all specified cookies (if any)
synchronized (cookies) {
	Iterator items = cookies.iterator();
	while (items.hasNext()) {
		Cookie cookie = (Cookie) items.next();
		outputWriter.print(CookieTools.getCookieHeaderName(cookie));
		outputWriter.print(": ");
		outputWriter.print(CookieTools.getCookieHeaderValue(cookie));
		outputWriter.print("\r\n");
	}
}

其实

SESSION_COOKIE_NAME

就是JSESSIONID,至于tomcat为什么使用这个字符串,可能就要和开发tomcat的程序员探讨一下了,其实她可以叫任何名字。
我们注意到在设置Cookie的时候,有一个CookieTools.getCookieHeaderName的方法,该方法根据HTTP版本号,决定使用Set-Cookie还是Set-Cookie2

public static String getCookieHeaderName(Cookie cookie) {
    int version = cookie.getVersion();

    if (version == 1) {
        return "Set-Cookie2";
    } else {
        return "Set-Cookie";
    }
}

 4. 浏览器验证

首先我初次请求服务器,浏览器发送的数据如下:
request

可以看出来,浏览器发送的Cookie中,不存在JSESSIONID,因此此刻Session还并没有创建和维护起来。

不过在服务器的Response中可以看到Set-Cookie 首部
response
此时,服务器已经把会话建立起来,并且分配了唯一的标示,并且告诉浏览器:“下次来要告诉我你是谁哦”

然后我们刷一下浏览器,再次请求服务器,可以看到Request如下:
nextrequest
可以看到,这次访问Cookie中已经加上了JSESSIONID,服务器可以利用这个SessionID,从本地找到Session对象,拿到记录下来的用户行为或者用户信息了。


 

 

SAP ABAP实战:手把手教你用BAPI_BILLINGDOC_CREATEMULTIPLE批量开票(附完整代码与避坑指南) 本文详细解析了SAP ABAP中BAPI_BILLINGDOC_CREATEMULTIPLE批量开票的全流程,包括参数配置、事务控制、错误处理及性能优化。通过实战案例和完整代码示例,帮助开发者高效处理大批量发票生成任务,避免常见陷阱,提升开发效率。 阅读详情

相关推荐

保姆级教程:用K210麦克风阵列模块实现声源定位(附完整Python代码与坐标计算)

本教程详细介绍了如何使用K210麦克风阵列模块实现高精度声源定位,包括硬件连接、算法解析与实战代码。通过Python代码示例,展示了从原始数据获取到三维空间坐标计算的完整流程,适用于智能家居、机器人导航等场景。

weixin_42558093的博客 226

Tomcat中的Session

什么是Session 对Tomcat而言,Session是一块在服务器开辟的内存空间,其存储结构为ConcurrentHashMap; Session的目的 Http协议是一种无状态协议,即每次服务端接收到客户端的请求时,都是一个全新的请求,服务器并不知道客户端的历史请求记录; Session的主要目的就是为了弥补Http的无状态特性。简单的说,就是服务器可以利用session存储客户...

yb创作中心 1942

S32K3实战:手把手教你用eMIOS模块实现电机PWM控制(附代码)

本文详细解析了NXP S32K3系列MCU的eMIOS模块在电机PWM控制中的应用,从硬件设计到软件实现,再到调试与优化,提供了完整的实战指南。通过eMIOS模块的硬件级PWM生成能力,工程师可以实现高精度的电机控制,适用于汽车电子和工业控制领域。

weixin_42570484的博客 146

Tomcat之session详解

深入Tomcat源码分析Session到底是个啥! Session到底是个啥? 我们都知道,HTTP协议本身是无状态的(Stateless),这对于一些简单的页面展示来说,功能足够,不受影响。而对于日渐复杂的动态页面、应用,各种需要登录认证等场景,就力不从心了。试想对于一个已经登录的用户仍然一次次的提示登录,会是什么感受呢? 因此,多数需要保持

马万明的专栏 6314

手把手教你用CsvView分析大疆无人机飞行日志(附实战CTF题解)

本文详细介绍了如何使用CsvView工具分析大疆无人机飞行日志,包括环境搭建、日志提取、核心功能解析及CTF实战技巧。通过实战案例,帮助读者掌握无人机取证的关键技术,提升日志分析能力,特别适合网络安全竞赛和实际取证场景。

weixin_42652674的博客 455

Qt 插件开发 plugin 超详细 有源码

Qt 插件化开发框架类似于前后端的微服务的场景,授权哪个微服务则前端可以使用哪个微服务,插件就行硬件插卡一样,可以被随时删除、插入和修改,所以结构很灵活,容易修改,方便软件的升级和维护;插件主要面向接口编程,无需访问.lib文件,热插拔、利于团队开发。即使在程序运行时.dll不存在,也可以正常启动,只是相应插件功能无法正常使用而已;动态库需要访问.lib文件,而且在程序运行时必须保证.lib存在,否则无法正常启动;

q610098308的专栏 6545

Tomcat深入浅出——Session与Cookie(四)

本文介绍了Tomcat的Cookie、Session二者的区别、应用场景、常用方法、以及Session的钝化活化

weixin_63597125的博客 854

向量乘法器设计

同样基于Wallace树乘法器,我们来构造向量乘法器。 在一些矩阵运算中经常用到向量的相乘运算,本例以4维向量为例子介绍向量乘法器的verilog HDL设计。 设向量a = (a1, a2, a3, a4), b = (b1, b2, b3, b4)。 则a 与 b的点乘为:a * b = a1 b1 + a2 b2 + a3 b3 + a4 b4, 即向量对应位置的值相乘,再相加...

Reborn Lee 2967

看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析

在Spring没有做任何配置的时候,默认会使用Tomcat 自带的session来做session机制。比如没有配置SessionRepository 以及 `@EnableSpringHttpSession`等等。我们下面来分析一个前端请求过来Springboot是如何处理的。 我们都知道客户端第一次请求过后服务端会返回一个jsessionid回来,但是这个jsessionid是怎么生成的,第二次及以后访问是如何匹配session的呢?我们下面先从session生成的节点来分析。

yh4494的博客 1245

9.23华为OD机试真题 新系统 - 小菊的寻宝之旅 (Java/Py/C/C++/Js/Go)

9.23华为OD机试真题 新系统 - 小菊的寻宝之旅 (Java/Py/C/C++/Js/Go)

算法大师! 984

2023年高教社杯 | 2023年高教社杯全国大学生数学建模思路(A题思路、C题思路)

2023年高教社杯 | 2023年高教社杯全国大学生数学建模思路(A题思路、C题思路)

前程算法屋的博客 624

Tomcat 如何管理 Session

Tomcat 如何管理 Session,Manager 跟 Session 是什么关系,什么是外观模式,有什么有点

qq_56517253的博客 1913

ThingsBoard3.9.1规则引擎方式发送钉钉通知消息

thingsboard3.9.1/4.0规则链方式发送钉钉通知消息。

hssjf的专栏 530

tomcat服务器介绍之二 、session服务器实现方法

上次讲到了session会话的绑定,通过nginx和apache(3种方式)实现;session会话的复制,通过DeltaManager和apache(mod_jk)实现;这次讲解基于msm实现session服务器的过程,需要用到的软件包如下:一、准备工作,先部署nginx可以反向代理客户端请求至2台tomcat服务器测试环境在centos7上,使用nginx和tomcat7...

weixin_34358092的博客 102

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

负载均衡时使用Spring Session和SpringData来实现多台tomcat服务器的session同步

在使用负载均衡的时候,前端使用nginx来平衡负载。 决定http请求到底由哪个tomcat服务器来响应和处理。 但是这样就会产生一个问题。如果用户在登录的状态下,登录的信息保存在tomcat 的httpSession中。 那么如果两次请求分别被两台tomcat处理。 那么另外一台tomcat上的内存中很可能没有session,更有可能有session,但是与之前的tomcat的内存中的se

u013803262的专栏 1538

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

搭建tomcat_两台服务器上搭建tomcat集群,实现session共享

安装环境:操作系统: linux(Centos7)JDK版本:1.8tomcat版本:8.5一、安装JDK1、oracle官网下载JDK for linux版本,这里我使用的版本是jdk-8u161-linux-x64.tar.gz2、解压tar -xvf jdk-8u161-linux-x64.tar.gzmv jdk1.8.0_161/ jdk1.83、加入到环境变量#打开profilevim...

weixin_36308848的博客 601

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

redis缓存服务器(nginx+tomcat+redis+mysql实现session会话共享)

一、redis介绍redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操...

weixin_33851604的博客 587

tengine+tomcat配合redis缓存服务实现多个服务器共享session

现有两台虚拟机 ip分别为192.168.222.3(master)和192.168.222.101(slave1)第一步:上传web服务器连接redis所需要的jar包到各自tomcat的lib目录下第二步:修改redis配置文件 绑定服务器的真实ip地址 vim /usr/local/redis/etc/redis.conf第三步:修改tomcat的配置文件server.xml第四步:修改to...

逆天骚年的博客 740

redis缓存服务器(Nginx+Tomcat+redis+MySQL实现session会话共享

一、redis介绍redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操...

weixin_34397291的博客 184

智能断电报警器原理与应用:从MQTT通信到养殖场实战部署

断电报警器是一种通过检测电路状态实现电力中断自动告警的物联网设备。其核心原理基于电压检测电路和通信模块,当监测到断电时,设备通过MQTT等物联网协议将报警信息推送至云端。这种技术能有效解决传统人工巡检的响应延迟问题,在养殖场温控保障、数据中心运维等场景中具有重要价值。以梅方断电报警器为例,它采用智能插座形态实现即插即用,支持4G/NB-IoT多模通信,通过备用电源确保断电后持续工作30分钟。该设备通过多通道通知机制,可及时向管理人员发送报警信息,帮助养殖场快速启动备用电源,避免畜禽冻伤等损失,实现用电安全的

weixin_34038293的博客 1065

Windows环境下Nginx+Tomcat+Redis实现应用服务器集群负载均衡和Session共享

1.实验环境和所需软件    1.Windows7环境    2.nginx 1.6.3    3.redis 2.6.2    4.Tomcat 7.0.56  2.配置Nginx           [java] view plain copy Nginx路径:E:\new\Tomcat_Nginx_Clust

luckykapok918的专栏 838

Tomcat的session集群和session服务器

概述session的作用httpd是无状态协议,多个http请求之间是没有关联的,服务器端也无法识别哪些请求来自同一个客户端。为了解决这一问题,当客户端第一次访问时,服务器端会创建一个session来保存这一次的会话信息,然后将sessionID(session的唯一标识符)放置在响应报文的首部发送给客户端,客户端再次请求时会携带这个sessionID(通常在request的...

weixin_34239592的博客 118

windows下利用 nginx服务器 搭建tomcat集群,并利用Redis实现Session共享

废话不多说,直接上教程。本教程不涉及java代码后台处理session,直接修改配置即可实现。 一、环境搭建 首先,我是在windows平台搭建的环境,所以,这篇文章主要讲述windows下tomcat集群的搭建,以及session的共享问题 jdk版本:1.7 下载链接:https://www.oracle.com/technetwork/java/javase/downloads/j...

loveLifeLoveCoding的博客 735

Nginx+Tomcat+Redis实现应用服务器集群负载均衡和Session共享

1.实验环境和所需软件    1.Windows7环境    2.nginx 1.6.3    3.redis 2.6.2    4.Tomcat 7.0.56  2.配置Nginx          Nginx路径:E:\new\Tomcat_Nginx_Cluster\nginx-1.6.3\#Nginx所有用户和组,window下不指定 #user Adminstrato

逍遥飞鹤的专栏 4365

lnmp架构下:完成客户的动态访问请求—tomcat服务器之间负载均衡—sticky粘滞—实现session共享和会话保持

一、Tomcat简介 Tomcat 服务器是一个开源的轻量级Web应用服务器,在中小型系统和并发量小的场合下被普遍使用,是开发和调试Servlet、JSP 程序的首选。 二、JDK简介 JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。 三、安装 ...

qq_46089299的博客 306

重头开始搭建负载均衡服务器(Linux环境下:Nginx+memcached+tomcat实现负载均衡+共享session)

一、前言: 这段时间,在学习服务器集群的搭建,其中遇到过很多的问题,自己也是一边看博客一边找资料,慢慢的去研究,然后搭成了一个简单的集群环境。希望对刚刚接触这方面的哥们有所帮助。 二、博客分布介绍: 1、首先话不多说,你在做这个实验前所需要的资料,我放在百度网盘上 2、本实验我分为三步走战略思想实现: (1)、部署Linux环境:安装Linux软件,部署:jdk环境、tomcat服务器、Nginx...

weixin_41557853的博客 408
上一篇: Jsoup 实现的基于列表-详情结构的网页爬虫
下一篇: Android客户端和Java服务器端集成支付宝
文西
文西 领域专家: 算法与数据结构技术领域 领域专家: 算法与数据结构技术领域
博客等级 码龄19年 967粉丝 79原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值