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

目录

    • Session概念
      • Session使用案例
      • Session的存储媒介
    • Tomcat Session
    • Tomcat session 缺点

Session概念

Session 大家知道是保存用户状态信息的,前端第一次请求后端,后端会生成一个session并返回set-cookie: JSESSIONID=xxxx来标识客户端,等客户端再次访问即可通过JSESSIONID找到服务端对应的session。

Session使用案例

比如说登录的时候我们可以把登录的信息放到session中,用户登录过后把用户信息放入到session中,后续的请求都可以从session中获取到当前用户的数据。因为客户端的sessionid是不会重复的所以此时在后端拿到的session也是不会冲突的,各自拿各自的session数据。

Session的存储媒介

  • JVM (ConcurrentHashMap)
    比如原生的Tomcat session
  • Redis
    spring-data-redis
  • 数据库
    spring-data-jdbc 很少用这种情况

Tomcat Session

在Spring没有做任何配置的时候,默认会使用Tomcat 自带的session来做session机制。比如没有配置SessionRepository 以及 @EnableSpringHttpSession等等。我们下面来分析一个前端请求过来Springboot是如何处理的。

我们都知道客户端第一次请求过后服务端会返回一个jsessionid回来,但是这个jsessionid是怎么生成的,第二次及以后访问是如何匹配session的呢?我们下面先从session生成的节点来分析。
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第1张图片
① Springboot 嵌入式 tomcat 默认采用的是NIO模型,非阻塞IO可以理解为类似Epoll模型linux的多路复用。会将请求交给tomcat线程池中取出的线程进行处理。

Http11NioProtocol
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第2张图片
② 任务会交给http处理器进行处理http11NioProcessor,http11NioProcessor会初始化CoyoteRequest/Respose,这两个对象会在后面执行被封装为HttpServletRequest/Response。
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第3张图片
CoyoteAdapter
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第4张图片

③ 调用CoyoteAdatpter做适配处理的时候会前置处理sessionid,如果cookies中有jsessionid则取cookies中的jsessionid做requestSessionid,如果没有就会在后续责任链的时候调用RequestFacdes.getSession来手动创建session。

method:CoyoteAdapter.service

在这里插入图片描述

method:CoyoteAdapter.CoyoteAdapter

看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第5张图片
① 如果URL中有SESSOINID则取URL中的SESSIONID作为RequestSessionid
② 从cookies中获取sessionid

method:CoyoteAdapter.parseSessionCookiesId

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

① 如果cookies count <= 0 则立马返回,不做任何处理,加入客户端在第一次访问服务端的时候这个时候啥Cookies都没有就是这种情况。
② 如果cookies count > 0则获取cookie name 为JSESSIONID的cookie设置为requestSessionid。

看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第7张图片
如果没做任何配置的话session name 默认的配置是jsessionid。

class:xxxFilter

在这里插入图片描述
在过滤器中使用ServletRequest.getSession()方法的时候会去调用门面方法getSEssion()

method:RequestFacade.getSession()

看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第8张图片
可以看到如果没有sessionid的话这个时候会去创建sessionid.最终会去创建session,生成sessionid.

method:ManagerBase.createSession

我们先来讲一下ManagerBase这个类,这个类是用来管理StandardSession的,Session的存储创建,session管理、session过期等等都是这个类负责的。所有的session操作都最终会落到这个manager进行处理(特指tomcat session)。
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第9张图片
session.setId的时候会把当前的session放到session的管理map中,这样下次就可以从sessions这个map直接根据sessionid获取session了。
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第10张图片

method:ManagerBase.add

看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第11张图片
ManagerBase中sessions这个成员变量就是对所有session管理的map。
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第12张图片
仔细看下这里创建玩session之后会创建一个timer这个就是负责session过期的timer。

method:ManagerBase.generateSessionId

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

生成sessionid的算法

看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第14张图片
那后续的response后会把生成的requestSessionid放入到cookie中返回给前端。前端第二次请求的话,服务端就可以从cookies中获取到jsessionid赋值给requestSessionid。从而从Tomcat维护的MapSession中获取到对应的session,从而实现客户端和服务端的会话保持。

Tomcat session 是如何设置值的?

我们一般都会先获取到session然后再往session的attribute中设置属性值,那我们怎么样在代码中获取到session的呢?
我拿一个最简单例子来举:
我同通过注入HttpServletRequest 或者同xxxContextHolder获取到了Request对象之后,然后根据request对象来获取session。这个时候会进入到RequestFacade.getSession方法中:
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第15张图片
和上述的创建sessionid一样,也会进入到doGetSession()方法中
看完这篇系列文章Spring session你就彻底懂了 - <第一讲> Tomcat session 运作原理以及源码解析_第16张图片
① 之前讲了requestSessionId创建和获取,因为这个时候已经有了requestsessionid和session,直接从sessions里边把对应的session拿出来返回即可。

Tomcat session 缺点

  • 安全性,session劫持,只要用户知道JSESSIONID,该用户就可以获取到JSESSIONID对应的session内容。
  • 增加服务器压力,因为session是直接存储在服务器的内存中的;
  • 如果存在多台服务器的话,还存在session同步问题,当然如果只有一台tomcat服务器的话,也就没有session同步的事情了,然而现在一般的应用都会用到多台tomcat服务器,通过负载均衡,同一个会话有可能会被分配到不同的tomcat服务器,因此很可能出现session不一致问题;解决session同步问题,实际上主要是保证能够抽离出一块共享空间存放session信息,且这块空间不同的tomcat服务器都可以访问到;一般这块共享的空间可以是数据库,或者某台服务器的内存空间,甚至硬盘空间,或者客户端的cookie也是可以的;

你可能感兴趣的:(JAVA,Java基础,杂项,tomcat,spring,java)