迁移至Spring Session 3与Hazelcast 5后HttpSession序列化类找不到问题
Spring Boot 3.2+Hazelcast 5.3迁移中的序列化与类加载问题
问题概述
正在将基于Spring Boot 2.7+Hazelcast 4.2的应用迁移至Spring Boot 3.2+Hazelcast 5.3(含JCache Hazelcast提供器)。原版本通过FilterRegistrationBean注册Hazelcast WebFilter,但因缺少Jakarta导入无法兼容Spring Boot 3,遂改用Spring Session Hazelcast 3配置。发起请求后先抛出序列化异常,启用User Code Deployment后又出现会话作用域类找不到的错误。
第一个错误:序列化异常
com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassNotFoundException: org.springframework.session.hazelcast.SessionUpdateEntryProcessor at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:96) at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:85) at (...) Caused by: java.lang.ClassNotFoundException: org.springframework.session.hazelcast.SessionUpdateEntryProcessor at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) (...)
第二个错误:会话作用域类找不到
com.hazelcast.core.HazelcastException: java.lang.NoClassDefFoundError: com/g4iner/ExampleCache$Companion at com.hazelcast.internal.util.ExceptionUtil.lambda$static$0(ExceptionUtil.java:48)
当前配置与代码
使用Spring Boot 3.2.6、Hazelcast 5.3.7客户端,Docker Compose部署Hazelcast 5.3.7服务端。
Docker Compose(Hazelcast服务端)
version: "3" services: hazelcast: image: hazelcast/hazelcast:5.3.7-slim-jdk17 environment: - HZ_USERCODEDEPLOYMENT_ENABLED=true ports: - "5701:5701"
Maven依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>3.2.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> <version>3.2.6</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-core</artifactId> <version>3.2.3</version> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-hazelcast</artifactId> <version>3.2.3</version> </dependency> <dependency> <groupId>javax.cache</groupId> <artifactId>cache-api</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast-spring</artifactId> <version>5.3.7</version> </dependency> <dependency> <groupId>com.hazelcast</groupId> <artifactId>hazelcast</artifactId> <version>5.3.7</version> </dependency> </dependencies>
应用配置(application.yml)
spring: cache: type: jcache jcache: provider: com.hazelcast.client.cache.HazelcastClientCachingProvider hazelcast: config: classpath:hazelcast-client.xml
Hazelcast客户端配置(hazelcast-client.xml)
<hazelcast-client xmlns="http://www.hazelcast.com/schema/client-config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.hazelcast.com/schema/client-config http://www.hazelcast.com/schema/client-config/hazelcast-client-config-5.3.xsd"> <cluster-name>dev</cluster-name> <instance-name>hazelcast-client</instance-name> <user-code-deployment enabled="true"> <classNames> <className>org.springframework.session.hazelcast.SessionUpdateEntryProcessor</className> <className>org.springframework.session.Session</className> <className>org.springframework.session.MapSession</className> </classNames> </user-code-deployment> <network> <cluster-members> <address>localhost:5701</address> </cluster-members> </network> </hazelcast-client>
Spring Session配置类(HazelcastSessionConfiguration.kt)
@EnableHazelcastHttpSession @Configuration open class HazelcastSessionConfiguration { @Bean @SpringSessionHazelcastInstance open fun hazelcastInstance(): HazelcastInstance { val clientConfig = ClientConfig() clientConfig.networkConfig.addAddress("localhost:5701") clientConfig.userCodeDeploymentConfig.setEnabled(true).addClass(Session::class.java) .addClass(MapSession::class.java).addClass(SessionUpdateEntryProcessor::class.java) return HazelcastClient.newHazelcastClient(clientConfig) } // example config from Spring docs for Server - what and how do I need for docker instance? @Bean open fun hazelcastConfig(): Config { val config = Config() val attributeConfig = AttributeConfig() .setName(HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE) .setExtractorClassName(PrincipalNameExtractor::class.java.name) config.getMapConfig(HazelcastIndexedSessionRepository.DEFAULT_SESSION_MAP_NAME) .addAttributeConfig(attributeConfig) .addIndexConfig( IndexConfig(IndexType.HASH, HazelcastIndexedSessionRepository.PRINCIPAL_NAME_ATTRIBUTE) ) config.setClusterName("dev") config.networkConfig.setPublicAddress("localhost:5701") val serializerConfig = SerializerConfig() serializerConfig.setImplementation(HazelcastSessionSerializer()).setTypeClass(MapSession::class.java) config.serializationConfig.addSerializerConfig(serializerConfig) return config } }
尝试过的方案
- 有无
hazelcastConfigBean的配置都试过 - 更换Hazelcast版本为5.4或4.2
- 手动创建
hazelcastInstanceBean
以上方案均无效。
疑问
请问遗漏了哪些配置?正确的客户端与服务端配置方式是什么?
内容的提问来源于stack exchange,提问作者G4iner
相关产品推荐
相关产品推荐

