Springboot整合springsession实现session共享 | 您所在的位置:网站首页 › tomcat实现session共享 › Springboot整合springsession实现session共享 |
Springboot整合springsession实现session共享
简介
session我们之前有介绍过(可见springboot整合springsecurity),简单来说就是将用户信息或者数据存储在服务器上,通常用于验证用户身份或者避免通过获取相关信息。 但是,缺点也是非常明显: 占用服务器负载:我们可以使用token,用时间换取空间 对于多服务器环境,session无法共享 对于第二点缺点,我们目前有几种比较常用的解决方法 使用cookie加密的方式将session保存在客户端上 优点是可以减轻服务器压力,缺点是每次请求都要带上cookie信息,占用一定带宽。此外若用户禁用cookie则无法使用 服务器间同步 通过配置tomcat集群,在集群中广播自己的session信息,但是缺点很明显,当集群规模较大时,会占用大量资源来进行session同步处理 基于分布式缓存的session共享机制 将session缓存到redis中,这样不同服务器都可以直接到内存中获取session,效率高,也最常用 SpringsessionspringSession是 spring 旗下的一个项目,把 servlet 容器实现的 httpSession替换为springSession,专注于解决session管理问题。可简单快速且无缝的集成到我们的应用中。 springsession就是spring的一个框架,实现了我们上面说的基于分布式缓存的session共享机制 操作实例我们先来看看简单的操作实例 程序源码 pom.xml org.springframework.session spring-session-data-redis 2.5.0 org.springframework.boot spring-boot-starter-data-redis 2.5.1 application.yml spring: redis: # 数据库索引,默认为0 database: 0 # redis host ip host: 192.168.56.129 # redis 连接端口 port: 6379 # 服务器连接密码(默认为空) password: # 连接超时时间(毫秒) timeout: 1000 #设置springsession存储类型,默认为redis session: store-type: redis 启动类加上@EnableRedisHttpSession @SpringBootApplication @EnableRedisHttpSession public class SpringsessionApplication { public static void main(String[] args) { SpringApplication.run(SpringsessionApplication.class, args); } } SessionController这里我们构建一个简单的controller测试是否实现了session共享 @RestController @RequestMapping("/session") public class SessionController { /** * 设置session * @param request * @param attributes * @return */ @PostMapping("/set") public Map setSession(HttpServletRequest request, @RequestParam("attributes")String attributes){ request.getSession().setAttribute("attributes",attributes); Map map = new HashMap(); map.put("SessionID:",request.getSession().getId()); return map; } /** * 获取session * @param request * @return */ @GetMapping("/get") public String getSession(HttpServletRequest request){ String attributes = (String) request.getSession().getAttribute("attributes"); return attributes; } }两个方法都很简单 setSession:通过请求中的参数设置session中的attributes getSession:测试是否能获取在其他端口设定的session中对应attributes的值 运行结果由于要体现session共享,所以我们这里将在两个不同端口运行程序 通过IDEA不同端口启用同一个项目,可以在右上角运行处选择edit config,然后添加springboot项目,并同意parallel run port:8080 /session/set 可以看到成功设置了session并且返回了SessionID port:8090 /session/get 成功获取到了session中的值,标明我们实现了session共享 我们再来看看redis存储的session 这里以sessionID为KEY,session为value存储,但是sessionID前面的命名空间太长了,而且不具有项目标识,我们可以通过在application.yml中设置namespace="xx"即可 Springsession 逻辑分析我们可以看到springsession使用非常简单,对于用户几乎不用进行什么操作,那么springsession具体为我们做了什么工作呢? 其实springsession通过autoconfigure帮我们自动配置了一个过滤器SessionRepositoryFitlter SessionRepositoryFitlter @Order(-2147483598) public class SessionRepositoryFilter extends OncePerRequestFilter {定义来看: 这里为SessionRepositoryFilter设定了一个非常小的order值,以确保能够在filterchain中被优先执行。 优先执行是为了将原生HttpRequest进行替换和封装 继承了OncePerRequestFilter,确保一次请求只通过一次 源码命名太长,直接贴代码太乱了,这里就直接截图了 可以看到,我们这里首先对request和response进行封装,之后将封装请求传入doFilter() 所以具体逻辑就在两个封装类中,这里我们着重关注request的封装类 获取session的逻辑如下: this.getCurrentSession() 检查serlvet容器中是否有session,如果有session则直接返回,如果没有则去redis中去拿 this.getRequestedSession() 根据请求中的信息获取sessionID,然后根据sessionID去redis中获取session 这里并不是每次查询都是去redis中查询,而是设置了一个session缓存,每次查询先检查缓存中有没有,如果有则直接拿值,如果没有则通过httpSessionIdResolver.resolveSessionIds(this)获取sessionID 获取sessionid有两种方式,一种是根据请求中Header信息获取,一种是放在cookie中 我们这里httpSessionIdResolver = new CookieHttpSessionIdResolver()选择使用cookie获取sessionID 查询到session之后,更新session相关信息并返回 如果在redis中没有找到,则根据create判断是否创建新的session 基本的逻辑非常清楚也非常好理解,我们再来具体看看springsession是如何在redis中查询session的 SessionRepositoryspringsession为我们提供了这样一个session仓库,能够完成对session的CRUD操作 我们这里使用的是RedisSessionRepository,实现了将session存储在redis上的CRUD操作 这就是我们getRequestedSession()中使用的findById() 可以看到里面就是对redis数据库的直接操作 总结本文主要介绍了springboot如何整合springsession实现session共享,也简单介绍了其中逻辑原理,具体的部分还是建议仔细阅读源码。 redis上的CRUD操作 [外链图片转存中…(img-guh79ZOd-1624583023491)] 这就是我们getRequestedSession()中使用的findById() 可以看到里面就是对redis数据库的直接操作 总结本文主要介绍了springboot如何整合springsession实现session共享,也简单介绍了其中逻辑原理,具体的部分还是建议仔细阅读源码。 |
CopyRight 2018-2019 实验室设备网 版权所有 |