前言:

session共享策略有很多,常见的有粘性复制,高并发下效率查。tomcat-redis-session-manager无疑是一个挺好的方案,缺点要配置tomcat,有点复杂。最优的方案莫过于使用Spring-Session无缝整合redis,只要项目修改即可。

测试项目结构:

项目结构很简单:

Test.java 就是一个页面跳转,传输一下sessionid

@Controller
public class Test {
@RequestMapping("/test")
public String test(HttpSession session, HttpServletRequest request) {
request.setAttribute("id", session.getId());
return "index";
} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

index.jsp 单纯的打印一下sessionid

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%-- <%@ page isELIgnored ="false" %> --%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>"> <title>My JSP 'TestUpload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head> <body>
我的session:${id}
<br> sessionid=<%=session.getId()%> </body>
</html>

当项目部署到nginx上的两个tomcat上时,每次访问地址,打印出来的sessionId都发生变化,这样在一些登录的操作中,用户明明在tomcatA上登录了,但是用户的其他操作负载到了TomcatB中,然而B不知道用户已经在A登录了,又让用户登录一次,这样用户体验极差。使用Spring-Session就是把用户的session缓存到redis中,让大家都从redis中获取用户session,这样就保证了session的共享。

使用Spring-Session

  • pom.xml 增加依赖
<!-- 使用Spring Session来解决Session共享问题  -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.3.0.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>biz.paluch.redis</groupId>
<artifactId>lettuce</artifactId>
<version>3.5.0.Final</version>
</dependency>
  • web.xml增加配置
<!-- Spring session -->
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • Spring.xml增加配置

    作用是导入redis配置redis.properties,导入新建的一个配置文件spring-session.xml
<context:property-placeholder location="classpath:db.properties,classpath*:redis.properties" ignore-unresolvable="true"/>
...
<import resource="classpath:spring-session.xml"/>
  • 1
  • 2
  • 3
  • 新增配置spring-session.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> <!-- 创建名为springSessionRepositoryFilter 的Spring Bean,继承自Filter。 springSessionRepositoryFilter替换容器默认的HttpSession支持为Spring
Session, 将Session实例存放在Redis中 -->
<bean id="redisHttpSessionConfiguration"
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration" /> <!-- 使用LettuceConnectionFactory -->
<bean
class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory">
<property name="hostName" value="${redis.ip}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.password}" />
</bean> <!-- 也可以将使用LettuceConnectionFactory改成使用JedisConnectionFactory,两者保留其一就好 -->
<!--<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> -->
<!--<property name="hostName" value="${redis.ip}"/> -->
<!--<property name="port" value="${redis.port}"/> -->
<!--<property name="password" value="${redis.password}"/> -->
<!--</bean> --> <!-- 让Spring Session不再执行config命令 -->
<!-- <util:constant
static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP" /> --> </beans>
  • 增加redis.properties

redis.ip=193.112.76.194

redis.port=6379

redis.password=xxxxxx

redis.pool.maxTotal=10

redis.pool.minIdle=4

redis.pool.maxIdle=8

redis.pool.testOnBorrow=true

发布到服务器上。访问index页面。无论刷新多少次结果都一样。session没变

我的session:a4b2fe35-aaa5-40c2-a7de-b1d60180ca04

sessionid=a4b2fe35-aaa5-40c2-a7de-b1d60180ca04

使用redis客户端查看

刚好有个seession一致。

原理:

DelegatingFilterProxy拦截器拦截, springSessionRepositoryFilter替换容器默认的HttpSession支持为SpringSession每个请求都会访问它。

使用Spring-Session共享使用Session的更多相关文章

  1. Tomcat 集群 + Redis Session 共享出现 Session 瞬间失效问题

    写在前面的话 写这篇博客出于公司最近要迁移到新的云上面且对之前的资源,架构做一个升级. 本来是一个不大的项目,旧环境旧一个 TOMCAT 跑起来,不过出于高可用考虑,新环境决定使用 TOMCAT 集群 ...

  2. shiro源码篇 - shiro的session共享,你值得拥有

    前言 开心一刻 老师对小明说:"乳就是小的意思,比如乳猪就是小猪,乳名就是小名,请你用乳字造个句" 小明:"我家很穷,只能住在40平米的乳房" 老师:" ...

  3. Shiro权限管理框架(二):Shiro结合Redis实现分布式环境下的Session共享

    首发地址:https://www.guitu18.com/post/2019/07/28/44.html 本篇是Shiro系列第二篇,使用Shiro基于Redis实现分布式环境下的Session共享. ...

  4. 用redis实现TOMCAT集群下的session共享

    上篇实现了 LINUX中NGINX反向代理下的TOMCAT集群(http://www.cnblogs.com/yuanjava/p/6850764.html) 这次我们在上篇的基础上实现session ...

  5. 关于session共享的解决方法

    当网站业务规模和访问量的逐步增大,原本由单台服务器.单个域名组成的网站架构可能已经无法满足发展需要 此时会购买更多的服务器,并且以频道化的方式启用多个二级子域名,然后根据业务功能将网站分别部署在独立的 ...

  6. Session的使用与Session共享问题

    Session的使用与Session共享问题 Session方法 getId():获取sessionId,这个id不一定是数字,比方说它用字符串来表示唯一标识,所以它返回值是String; boole ...

  7. 如何实现集群中的 session 共享存储?

    Session 是运行在一台服务器上的,所有的访问都会到达我们的唯一服务器上,这 样我们可以根据客户端传来的 sessionID,来获取 session,或在对应 Session 不 存在的情况下(s ...

  8. 基于Spring Boot/Spring Session/Redis的分布式Session共享解决方案

    分布式Web网站一般都会碰到集群session共享问题,之前也做过一些Spring3的项目,当时解决这个问题做过两种方案,一是利用nginx,session交给nginx控制,但是这个需要额外工作较多 ...

  9. [Spring] spring-session + JedisPool 实现 session 共享

    1.至少导入四个jar包: jedis spring-session spring-data-redis commons-pool2 2.bean配置 <?xml version="1 ...

  10. 单点登录实现(spring session+redis完成session共享)

    一.前言 项目中用到的SSO,使用开源框架cas做的.简单的了解了一下cas,并学习了一下 单点登录的原理,有兴趣的同学也可以学习一下,写个demo玩一玩. 二.工程结构 我模拟了 sso的客户端和s ...

随机推荐

  1. Android最简单的实例 :环境搭建及HelloWorld

    Android开发之旅:环境搭建及HelloWorld 2010-04-12 00:45 by 吴秦, 883961 阅读, 140 评论, 收藏,  编辑 ——工欲善其事必先利其器 引言 本系列适合 ...

  2. D. Artsem and Saunders 数学题

    http://codeforces.com/contest/765/problem/D 这题的化简,不能乱带入,因为复合函数的带入,往往要严格根据他们的定义域的 题目要求出下面两个函数 g[h(x)] ...

  3. OAuth2.0认证流程是如何实现的?

    导读 大家也许都有过这样的体验,我们登录一些不是特别常用的软件或网站的时候可以使用QQ.微信或者微博等账号进行授权登陆.例如我们登陆豆瓣网的时候,如果不想单独注册豆瓣网账号的话,就可以选择用微博或者微 ...

  4. css3 transform + deviceorientation实现图片旋转效果

    1. 陀螺仪deviceorientation的使用,参考<关于陀螺仪deviceorientation>https://segmentfault.com/a/11900000071838 ...

  5. 21全志r58m平台的framework在使用过程中会莫名的崩溃掉

    21全志r58m平台的framework在使用过程中会莫名的崩溃掉 2018/10/25 16:20 版本:V1.0 开发板:SC5806 1.系统编译: rootroot@cm88:/home/ww ...

  6. openmv第一次调试

    2018-09-19  20:14:51 import sensor, image, time import car import json import time from pyb import U ...

  7. SQL——时间戳

    mysql 低版本,date.datetime.timestamp 无法精确到毫秒 可以舍弃时间类型字段,用 bigint 来代替,如果用字符串类型代替,还是比较担心排序的时候只是根据第一个字母进行排 ...

  8. Delphi win10 asssertion failure

    Delphi2007 原来安装在Win7 下 运行正常, 自从升级到Win10 ,新建工程运行然后关闭报错, 报错信息如下: ---------------------------bds.exe - ...

  9. vue路由细节探讨

    1.使用router-link 不会让页面刷新,使用a标签会使页面刷新.2.router-link 里面的to="/路由地址" tag=""自定义标签" ...

  10. iTOP-4418/6818开发板支持锂电池供电方案

    iTOP-4418/6818开发板支持的是官方推荐的AXP228电池管理,动态调频,更稳定可靠,支持充放电电路与电量计(库化计), 广泛应用于各种电子产品中. 4418开发板中锂电池充放电接口,适用于 ...