Spring Session 共享 Session 取值正常,Redis 里是乱码

在使用 Spring Session 进行分布式会话管理时,我们可能会遇到一个问题:尽管从 Redis 中获取到的 Session 信息是可用的,但其值却变成了乱码。这篇文章将介绍该问题的原因,并提供解决方案。

问题背景

Spring Session 是一个用于管理分布式会话的解决方案,它支持将会话数据存储在 Redis、MongoDB、JDBC 等后端存储中。当我们使用 Redis 作为后端存储时,有时会出现从 Redis 中获取到的 Session 值是乱码的情况。

例如,我们使用 Spring Session 配置了一个基于 Redis 的分布式会话管理器,并在一个服务中创建了一个 HttpSession 对象,并将一个字符串值存储到 Session 中。然后,在另一个服务中,我们通过相同的 Session ID 从 Redis 中获取这个 Session 对象。但是,我们发现字符串值变成了乱码。

问题原因

这个问题的原因是 Redis 使用了序列化来存储 Session 对象的值。默认情况下,Spring Session 使用了 JdkSerializationRedisSerializer 来进行序列化。但是,JdkSerializationRedisSerializer 是使用 Java 自带的序列化机制,它将对象序列化成二进制字节流。由于二进制字节流是不可读的,所以当我们从 Redis 中获取到这些字节流时,我们看到的是乱码。

解决方案

为了解决这个问题,我们需要修改 Spring Session 的序列化方式,使其能够以可读的形式存储和获取 Session 对象的值。一个常用的解决方案是使用 Jackson2JsonRedisSerializer,它使用 JSON 格式来序列化和反序列化对象。

首先,我们需要添加 Jackson 相关的依赖。在 Maven 项目中,我们可以在 pom.xml 文件中添加以下依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
</dependency>

接下来,我们需要修改 Spring Session 的配置,以使用 Jackson2JsonRedisSerializer。下面是一个示例的 Spring Boot 配置文件:

# Redis 配置
spring.redis.host=localhost
spring.redis.port=6379

# Spring Session 配置
spring.session.store-type=redis
spring.session.redis.namespace=example-session

# 使用 Jackson2JsonRedisSerializer 进行序列化和反序列化
spring.session.redis.serializer=jackson

在上面的配置中,我们将 spring.session.redis.serializer 属性设置为 "jackson",以启用 Jackson2JsonRedisSerializer。这样,当我们从 Redis 中获取 Session 对象时,其值将是可读的 JSON 字符串。

示例代码

下面是一个使用 Spring Session 进行分布式会话管理的示例代码:

@RestController
public class SessionController {

    @Autowired
    private HttpSession httpSession;

    @GetMapping("/setSession")
    public String setSession() {
        httpSession.setAttribute("message", "Hello, World!");
        return "Session set successfully!";
    }

    @GetMapping("/getSession")
    public String getSession() {
        return (String) httpSession.getAttribute("message");
    }
}

在上面的代码中,我们使用 httpSession.setAttribute 方法将一个字符串值存储到 Session 中,并使用 httpSession.getAttribute 方法从 Session 中获取该值。

结论

在使用 Spring Session 进行分布式会话管理时,如果从 Redis 中获取到的 Session 值是乱码,我们可以使用 Jackson2JsonRedisSerializer 来解决这个问题。通过修改 Spring Session 的配置,将其序列化方式改为使用 JSON 格式,我们可以在 Redis 中以可读的形式存储和获取 Session 对象的值。

希望本文能够帮助你解决 Spring Session 共享 Session 取值正常,Redis 里是乱码的问题。如果你有任何疑问或建议,请随时在下方留言,我们将尽力为你解答。