一、使用Redis实现session共享

        Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。

使用外部的缓存设备来共享 Session,避免单个服务器节点挂掉而影响服务,共享数据都会放到外部缓存容器中。

       Spring 官方针对 Session 管理这个问题,提供了专门的组件 Spring Session,使用 Spring Session 在项目中集成分布式 Session 非常方便。Spring 为 Spring Session 和 Redis 的集成提供了组件:spring-session-data-redis。

        使用Redis实现共享session原理:

所有服务器的session信息都存储到了同一个Redis集群中,即所有的服务都将 Session 的信息存储到 Redis 集群中,无论是对 Session 的注销、更新都会同步到集群中,达到了 Session 共享的目的。

       导入依赖

<!-- Redis 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!-- Spring Session Redis 依赖-->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

        application.properties配置文件

# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/study?
           serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=3333
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Redis 不同应用程序项目配置同一个Redis服务器
# Redis 数据库索引(默认为0)
spring.redis.database=0  
# Redis 服务器地址
spring.redis.host=localhost
# Redis 服务器连接端口
spring.redis.port=6379  
# Redis 服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.shutdown-timeout=100
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.min-idle=0

        session像如下配置就好了

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class SessionConfig {
}

使用 Redis Session 之后,原 Spring Boot 中的 server.session.timeout 属性不再生效。

        仅仅需要这两步 Spring Boot 分布式 Session 就配置完成了。

        根据师傅的指导,我创建了两个相同的服务器,只是将SpringBoot启动的端口换掉(server.port=9090)。

二、测试

先创建一个User类,一定要实现序列化接口,因为session将数据存放到了Redis集群中,所以存入的数据也需要能够被序列化。

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
    private Long id;
    private String username;
    private String password;

    public static final User defaultUser() {
        return builder().id(1L).username("jay").password("3333").build();
    }
}
@RequestMapping("/index")
    public String index(HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user != null) {
            return "index message";
        }
        return "please login first";
    }

    @RequestMapping("/login")
    public String login(HttpServletRequest request, String username, String password) {
        User userFromDB = defaultUser();
        if (username.equals(userFromDB.getUsername())) {
            if (password.equals(userFromDB.getPassword())) {
                request.getSession().setAttribute("user", userFromDB);
                return "login success";
            }
        }
        return "login failure";
    }

    @RequestMapping("/logout")
    public String login(HttpServletRequest request) {
        request.getSession().removeAttribute("user");
        return "has already logout";
    }

       8080端口的服务器与9090端口的服务器连接的是同一个Redis服务器。所以8080端口的服务器与9090端口的服务器共享的是同一个session。在8080端口服务器登录后,在9090端口服务器是可以访问受限制资源的。
        同样,在9090端口上进行用户退出,然后再测试8080端口是否可以访问受限制资源,结果是用户退出后不可以访问受限制资源。

redis 对象共享 redis共享session原理_spring