spring mvc环境配置spring-data-redis进行应用多实例间session共享

mybatis+spring+springmvc+springsession + redis实现session共享配置 jdbc配置#hibernate.dialect=com.bky.util.Oracle10gDialect #driverClassName=oracle.jdbc.driver.OracleDriver #validationQuery=SELECT 1 FROM DUAL #jdbc_url=jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDR 阅读详情

一、redis 环境准备

  1. 打开redis配置文件redis.conf
  2. 修改redis.conf文件
    notify-keyspace-events Egx
    
  3. 重启redis服务

二、POM文件依赖引入

        <!-- session共享, 采用spring-session-data-redis依赖 -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <version>1.3.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.data</groupId>
                    <artifactId>spring-data-redis</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>1.7.1.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context-support</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

二、web.xml 配置

在所有filter的最前面,增加如下filter(不要改这个filter名称)

<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>
  </filter-mapping>

三、spring application context xml配置

增加如下配置

    <!-- 让Spring Session不再执行config命令 -->
	<util:constant static-field="org.springframework.session.data.redis.config.ConfigureRedisAction.NO_OP"/>

	<bean id="redisSessionSerializer"
		  class="com.some.company.CustomGenericFastJsonRedisSerializer" />

	<bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" />

	<bean id="sessionRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
		  p:keySerializer-ref="stringRedisSerializer"
		  p:hashKeySerializer-ref="stringRedisSerializer"
		  p:valueSerializer-ref="redisSessionSerializer"
		  p:hashValueSerializer-ref="redisSessionSerializer"
		  p:connectionFactory-ref="redisConnectionFactory" />

	<context:annotation-config />
	<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"
		  p:defaultRedisSerializer-ref="redisSessionSerializer" p:configureRedisAction="NO_OP" />

四、session 序列化器定制化

上面第三步有个定制化的序列化器, 用于处理session(本质是个map)中存储的,不容易做序列化的属性对象。

例如没有实现Serilizable接口的类, 或者说,使用通用的序列化方法,不太容易做序列化(反序列化)的对象。

需要自己定制序列化策略:

  1. 调用定制化策略, 得到包含某个session对象S的字符串A。
  2. 将字符串A按照标准的字符串序列化方式序列化到redis中。
  3. 反序列化时, 用标准的字符串反序列化方式从redis中反序列化出来字符串A。
  4. 从A中提取信息,用定制的反序列化策略,构造对应的session对象类S。

序列化元数据类

@Data
public class CustomGenericFastJsonRedisBean {
    // bean 序列化原始类全路径类名
    private String className;
    // 原始类定制序列化策略生成的字符串
    private String classContent;
    // 如果是列表对象,列表中元素的全路径类名
    private String arrayItemClass;
}

定制序列化

package com.some.company.util;

...

public class CustomGenericFastJsonRedisSerializer extends GenericJackson2JsonRedisSerializer {
    private static final Logger log = LoggerFactory.getLogger(CustomGenericFastJsonRedisSerializer.class);

    @Autowired
    private UserService userService;

    @Override
    public byte[] serialize(Object source) throws SerializationException {
        try {
            if (source == null) {
                log.info("source null");
                return new byte[0];
            } else {
                String classname = source.getClass().getName();
                CustomGenericFastJsonRedisBean customGenericFastJsonRedisBean = new CustomGenericFastJsonRedisBean();
                Gson gson = new Gson();
                String objectStrOrigin;
                if (StringUtils.equals("com.some.company.User", classname)) {
                    objectStrOrigin = Jackson2Helper.toJsonString(source);
                } else if (StringUtils.equals("org.springframework.security.core.context.SecurityContextImpl",
                        classname)) {
                    SecurityContextImpl securityContext = (SecurityContextImpl) source;
                    CasAuthenticationToken oneToGo = (CasAuthenticationToken) securityContext.getAuthentication();

                    objectStrOrigin = buildCasAuthenticationTokenStr(oneToGo);
                    log.info("redis class : >{}< bean content : >{}<", classname, objectStrOrigin);
                } else if (StringUtils.equals("java.util.ArrayList", classname)) {
                    ArrayList<?> oneList = (ArrayList<?>) source;
                    if (CollectionUtils.isNotEmpty(oneList)) {
                        String itemClassname = oneList.get(0).getClass().getName();
                        customGenericFastJsonRedisBean.setArrayItemClass(itemClassname);
                        objectStrOrigin = JSON.toJSONString(source);
                        log.info("redis class : >{}<", itemClassname);
                    } else {
                        objectStrOrigin = JSON.toJSONString(source);
                        log.info("redis class : Object");
                    }
                } else {
                    objectStrOrigin = gson.toJson(source);
                    log.info("redis class : >{}< bean content : >{}<", classname, objectStrOrigin);
                }
//                String objectStrOrigin = Jackson2Helper.toJsonString(source);
                customGenericFastJsonRedisBean.setClassName(classname);
                customGenericFastJsonRedisBean.setClassContent(objectStrOrigin);
                String objectStr = gson.toJson(customGenericFastJsonRedisBean);
                return super.serialize(objectStr);
            }
        } catch (Exception e) {
            log.warn("serialize session Object error!", e);
        }
        return new byte[0];
    }

    @HibernateSessionAround
    @Override
    public Object deserialize(@Nullable byte[] bytes) {
        Object deserialObj = null;
        try {
            if (bytes == null || bytes.length <= 0) {
                log.warn("bytes empty");
            } else {
                String outStr = super.deserialize(bytes, String.class);
                if (StringUtils.isBlank(outStr)) {
                    log.warn("empty outStr");
                } else {
                    Gson gson = new Gson();
                    CustomGenericFastJsonRedisBean customGenericFastJsonRedisBean =
                            gson.fromJson(outStr, CustomGenericFastJsonRedisBean.class);

                    if (customGenericFastJsonRedisBean == null) {
                        log.warn("customGenericFastJsonRedisBean is null");
                    } else {
                        String redisOutClassName = customGenericFastJsonRedisBean.getClassName();
                        String redisOutContent = customGenericFastJsonRedisBean.getClassContent();
                        String arrayItemClass = customGenericFastJsonRedisBean.getArrayItemClass();
                        if (StringUtils.isBlank(redisOutClassName)) {
                            log.warn("customGenericFastJsonRedisBean class name null");
                        } else {
                            Class redisOutClass = Class.forName(redisOutClassName);
                            if (StringUtils.equals("com.some.company.User", redisOutClassName)) {
                                com.some.company.User userOrigin =
                                        Jackson2Helper.parsonObject(redisOutContent,
                                                new TypeReference<com.some.company.User.User>() { } );

                                if (userOrigin != null) {
                                    Long userId = userOrigin.getId();
                                    com.some.company.User user = userService.findByUserId(userId);
                                    log.info("user dept name {}", user.getDeptName());
                                    deserialObj = user;
                                } else {
                                    deserialObj = null;
                                }

                                log.info("redisOutClassName: >{}<, redisOutContent: >{}<",
                                        redisOutClassName, redisOutContent);

                            } else if (StringUtils.equals(
                                    "org.springframework.security.core.context.SecurityContextImpl",
                                    redisOutClassName)) {
                                JSONObject jsonObject = JSON.parseObject(redisOutContent);
                                CasAuthenticationToken casAuthenticationToken =
                                        buildCasAuthenticationToken(jsonObject);
                                SecurityContextImpl securityContext = new SecurityContextImpl();
                                securityContext.setAuthentication(casAuthenticationToken);
                                deserialObj = securityContext;
                            } else if (StringUtils.equals("java.util.ArrayList", redisOutClassName)) {
                                if (StringUtils.isNotBlank(arrayItemClass)) {
                                    Class redisOutClassArray = Class.forName(arrayItemClass);
                                    deserialObj = JSON.parseArray(redisOutContent, redisOutClassArray);
                                    log.info("arrayItemClass : >{}<", arrayItemClass);
                                } else {
                                    deserialObj = JSON.parseArray(redisOutContent, Object.class);
                                    log.info("arrayItemClass : >Object<");
                                }
                            } else {
                                deserialObj = gson.fromJson(redisOutContent, redisOutClass);
                                log.info("redisOutClassName: >{}<, redisOutContent: >{}<",
                                        redisOutClassName, redisOutContent);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.warn("deserialize session Object error!", e);
        }
        return deserialObj;
    }

    private String buildCasAuthenticationTokenStr(CasAuthenticationToken oneToGo) {
        JSONObject jsonObject = new JSONObject();
        ...
        return JSON.toJSONString(jsonObject);
    }

    private CasAuthenticationToken buildCasAuthenticationToken(JSONObject jsonObject) {
        ...
        CasAuthenticationToken casAuthenticationToken =
                new CasAuthenticationToken("an_id_for_this_auth_provider_only",
                        principal,
                        credentials,
                        grantedAuthorityList,
                        userDetails,
                        assertionImpl);
        return casAuthenticationToken;
    }

}

五、总结

理论上,用spring data redis 做 session共享,可以根据自己工程的鉴权场景,做任意的序列化定制,来支持服务多实例间session共享。

实现Spring+SpringMVC+Hibernate+Redis的Session共享Demo Spring框架是一个全面的Java平台,为现代Java应用开发提供了基础。它的核心是依赖注入(DI)和面向切面编程(AOP)。通过控制反转(IoC),Spring管理对象的创建和生命周期,简化了对象之间的依赖关系。而AOP允许开发者通过声明方式定义横切关注点,如日志、事务管理等。ORM(Object-Relational Mapping)即对象关系映射,是一种技术思想,用于实现面向对象语言中的对象与关系数据库中的表之间的映射。 阅读详情

相关推荐

利用LTspice设计Pt100测温电路

是一种广泛使用的温度传感器,它属于(RTD, Resistance Temperature Detector)的类型,通常用于温度测量。在0°C时,的电阻值为100欧姆,且它的电阻值会随着温度的升高而升高。PT100热电阻温度阻值对应表)因此可以根据这一特性来检测出环境温度。

2301_77033628的博客 2417

springmvc框架下使用spring-session-data-redis集成redis实现session共享

1、安装redis 具体过程不再讲 2、配置redis bind 127.0.0.1 192.168.1.100 #指定redis绑定的主机地址 port 6379 #指定访问redis服务端的端口 timeout 1800 #指定客户端连接redis服务器时,当闲置的时间为多少(如1800秒)时,关闭连接。 这个很重要 如果不设置的话,redis连接数会越来越大,直到最大值后报异常 ...

lgklm的专栏 1790

SolidWorks有限元分析流程

对于很多专业,在进行设计完成后,为了缩短开发周期,往往需要配合仿真结果进行,机械行业更是如此。平时大家多采用专业有限元仿真软件进行仿真分析,如ANSYS;不过SolidWorks软件因为制图简单,同时存在专用的有限元仿真模块Simulation,对于初学者往往更加适用,下面简单介绍下SolidWorks Simulation仿真流程。 1. 分析流程 关键步骤如下: **(1)创建算例;**对模型的每次分析都是一个算例,一个模型可以包含多个算例。 **(2)应用材料;**指定模型的材料属性,如铝合金、钢材等

DYH_BK的博客 3万+

SpringBootMVC使用Redis持久化保存Session

在下载安装配置好redis之后,我们就可以使用redis持久化保存session了.那么我们要怎么做呢?

qq_62592809的博客 620

07- Rossmann商店销售预测 (Xgboost集成算法) (项目七)

Rossmann在欧洲国家经营着3000多家日化用品超市。目前,Rossmann商店经理的任务是提前6周预测他们的日销售额。商店的销售受到许多因素的影响,包括促销、竞争、学校和国家假日、季节性和地域性。由于数以千计的管理者根据自己的特殊情况预测销售,结果的准确性可能会有很大的差异。 因此使用机器学习算法对销量进行预测,Rossmann要求预测德国1115家商店的6周日销售额。可靠的销售预测使商店经理能够制定有效的员工时间表,提高生产力和积极性。

March_A的博客 2462

ios生成海报使用dom-to-image中toPng报错isTrusted:true

主要是ios中safari浏览器解析错误,引起的报错,主要引起原因toPng会调用toSvg,toSvg直接将html标签内容通过svg中foreignObject标签直接包裹,然后转base64, 通过data:image/svg+xml;解决办法:二次生成(调用两次),判断ios or 安卓,生成第一次生成,不用参数,例如:scale: 3,在第二次生成再进行清晰度操作,避免多次生成,引起性能消耗。以上种种很多案例,使用canvase进行转换的,标签丢失,直接toPng版本的,兼容性问题。

weixin_44601570的博客 2105

SprinMvc+Redis 实现session共享

一.session共享的应用场景    每个客户端与服务器交互时生成会话的sessionID是唯一,同个客户端在访问不同的域名:主域名、子域名、跨站点域名或跨服务器域名,会有不同的sessionID,有些应用程序会在session存放用户的状态和信息,同个应用程序的客户端需访问不同的服务端项目,为了使用户在登入后能够在规定时间内保持登入状态,需要进行session共享,多个的项目之间可以使用同个...

Aron的博客 3456

安卓刷Windows太难?这款手机平板双系统刷机工具,小白也能轻松拿捏!(小白福音!手机平板专用,一键搞定安卓刷 Windows 双系统!)

安卓刷Windows太难?这款手机平板双系统刷机工具,小白也能轻松拿捏!(小白福音!手机平板专用,一键搞定安卓刷 Windows 双系统!)

XiaoqiangClub的博客 4676

Spring MVC 使用 Spring Session 实现 Session 共享-Redis

使用Spring Session 通过 Redis 实现 Session 共享,用于多实例应用Spring Session 官方文档https://docs.spring.io/spring-session/docs/2.0.0.M4/reference/html5/#introduction Session 共享的简单原理 用户第一次访问应用时,应用会创建一个新的 Session,并且会将 S

啦啦啦啦 la 6893

cesium 深度图(获取区域最高最低点位)

文章摘要: Cesium深度图技术可用于获取区域地形高程数据,核心实现步骤包括:1)通过离屏相机构建独立渲染环境,使用正交投影确保采样精度;2)采用离屏渲染技术获取均匀分布的地形点数据。关键技术点包含多边形外包矩形计算、后台相机配置(5km高度正交投影)、1024×1024像素离屏视图设置,以及深度数据解析(RGBA格式转换和三维坐标还原)。该方法避免了主视图干扰,可精准获取区域内地形高程信息,为填挖方分析等应用提供基础数据支持。

God's asylum的博客 283

【YOLO系列】YOLOv8详解:模型结构、损失函数、训练方法及代码实现

YOLOv8是Ultralytics团队2023年推出的高效目标检测框架,在速度与精度平衡、多任务支持和易用性方面实现突破。模型采用改进的CSPDarknet主干网络、C2f模块和SPPF加速结构,结合PAN-FPN特征融合和解耦检测头设计,支持目标检测、实例分割和关键点检测任务。创新性地使用CIoU定位损失、Focal Loss置信度损失和动态样本分配策略,显著提升检测性能。实验表明,YOLOv8较前代模型mAP提升5-10%,在TensorRT加速下可达1000FPS,提供5种尺寸灵活选择,成为实时目标

一碗白开水一 2779

技术栈入门------SpringSession

技术栈入门------SpringSession

我从不打没有准备的仗! 9040

S7-1500 PLC与多台S7-200SMART PLC进行PROFINET通信的快捷方法

S7-1500 PLC与多台S7-200SMART PLC进行PROFINET通信的快捷方法

Robot_PLC_HMI_Automation 5687

spring-session-data-redis session更新失效问题解决

本文目录结构: 一、问题复现 二、问题排查 三、问题解决一、问题复现现在的项目都由原先的单体架构向分布式架构演变,在这个过程中就会存在session共享的问题。单体架构只有一个JVM,所以内存中的数据可以共享,session直接保存在内存中,重启服务会导致session丢失,用户登录失效。分布式架构下基本都存在多个微服务,或者微服务集群,且版本迭代速度快,这些服务有各自的JVM,因此无法实现内存共享,这时就需要借助第三方存储空间()来实现内存共享,并且重启服务不会丢失session,能够保持用户登录态。将s

xiaoming的博客 3814

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Spring Session Data Redis 配置中遇到的坑

说道Session共享,从网上搜索,有几种实现方式,比较普遍的 Tomcat Session Redis,这种是需要在tomcat容器里增加几个jar包,并修改Tomcat里的content.xml增加一条语句,实现session共享,此方法依赖于 tomcat. 还有一种是 Spring-Session-Data-Redis,此方法对servlet容器都有效,不局限于tomcat,也是比较

ankeway的博客 3万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

使用spring session redis做session共享

适用范围:springmvc项目,分布式集群。 1.安装redis,不赘述,参见具体安装文档。  或点击这里查看步骤:http://stamen.iteye.com/blog/1903867/ 2.所依赖的jar包,我们这边功能用到的三个jar包信息如下: redis.clients jedis 2.8.1 org.springframewor

smartdt的博客 541

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

spring-session使用配置redis

spring-session使用配置(分布式共享session配置) 1. 添加依赖    dependency> groupId>org.springframework.sessiongroupId> artifactId>spring-session-data-redisartifactId> version>1.2.0.RELEASEvers

linbren的专栏 549

Spring MVC集成Spring Data Reids和Spring Session实现Session共享出现:No bean named 'springSessionRepositoryFilt...

出现这个问题:No bean named 'springSessionRepositoryFilter' available的的原因: 1、Spring MVC加载了多个配置文件导致的,并不是版本问题。 2、如果使用org.springframework.web.context.ContextLoaderListener进行加载其它XML文件时,那么配置Redis和Session必须...

angou6476的博客 259

深入解析Spring Session分布式会话管理:从HTTP无状态到Redis存储实战

在Web开发中,HTTP协议的无状态特性是构建交互式应用的基础挑战,会话(Session)机制正是为了解决这一问题而诞生。其核心原理是通过服务端生成唯一Session ID并与客户端Cookie关联,从而在多次请求间维持用户状态。随着应用架构演进至分布式与微服务,传统的服务器内存存储方案面临扩展性瓶颈,此时将会话状态外置到共享存储成为关键技术方向。Spring Session作为主流解决方案,通过过滤器拦截并替换原生HttpSession实现,将会话数据持久化至Redis等外部存储,实现了应用实例的无状态化

weixin_33882452的博客 379

利用spring session解决共享Session问题

spring-session使用配置(分布式共享session配置) 1. 添加依赖    dependency> groupId>org.springframework.sessiongroupId> artifactId>spring-session-data-redisartifactId> version>1.2.0.RELEASEversion> dep

Seven__________7的博客 1176

Spring MVC集成Spring Data Reids和Spring Session实现Session共享

说明:Spring MVC中集成Spring Data Redis和Spring Session时版本是一个坑点,比如最新版本的Spring Data Redis已经不包含Jedis了,需要自行引入。且最新版本的2.0.1会与Spring MVC 4.1.4有冲突,估计写法错了。所以要明确引入的Spring MVC版本和Spring Data Redis和Spring Session版本...

angou6476的博客 124

学习Spring-Session+Redis实现session共享

1、添加依赖<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-data-redis</artifactId> <version>1.2.1.RELEASE</version> </dependency> <dependency> <groupId>redis.c

B-Tree 729

Spring-Session+Redis实现session共享

1、添加依赖 &lt;dependency&gt; &lt;groupId&gt;org.springframework.data&lt;/groupId&gt; &lt;artifactId&gt;spring-data-redis&lt;/artifactId&gt; &lt;version&gt;2.0.9.RELEASE&lt;/version&gt; &amp

kongtong2004的专栏 302

Spring整合redis(jedis)实现Session共享

今天来记录一下自己在整合框架过程中所遇到的问题:    在用redis实现session共享时,项目启动报 No bean named 'springSessionRepositoryFilter' is defined 异常    在调用缓存工具类的时候显示注入的JedisPool为Null...

zengyunt的博客 1520

实现spring Session与redis数据的存储

spring Session实现了对redis内存数据库的实现,从而实现的互联网系统服务接待Session值的共享;今天我们讲讲如何实现此功能:         1.加载对应的包:spring-session-1.0.2.RELEASE.jar、spring-data-redis-1.4.2.RELEASE.jar、jedis-2.5.2.jar、commons-pool2-2.2.jar;

岁月沉淀,积累财富 1946
上一篇: awk用法
下一篇: linux常用命令备份
一装到底
博客等级 码龄18年 13粉丝 26原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值