现在越来越流行使用分布式集群方式部署应用,这就带来一个问题,session无法共享。而使用Spring Session可以将session抽离出来,存放到像是redis的数据库中,这样就不会受到集群分布的影响。
以存储在redis中的Spring Session为例
对于分布式的项目,Spring Session的配置应该放在公共模块中。
首先是依赖的导入:
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
接着是配置文件中的配置:
spring.session.store-type=redis
#默认就是30分钟
server.servlet.session.timeout=30m
配置文件的编写:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
@EnableRedisHttpSession
@Configuration
public class GulimallSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
//放大作用域
cookieSerializer.setDomainName("gulimall.com");
cookieSerializer.setCookieName("GULISESSION");
return cookieSerializer;
}
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
return new GenericJackson2JsonRedisSerializer();
}
}
以上设置domainname的原因是因为比如我登录之后,如果不设置扩大域名,则这个session只能在当前域里使用(假设当前域名为“auth.gulimall.com”),那么设置了扩大域名后就可以在整个域里(包括子域进行session的使用)
将需要保存的对象序列化:
import lombok.Data;
import lombok.ToString;
@ToString
@Data
public class MemberResponseVo implements Serializable {
private static final long serialVersionUID = 5573669251256409786L;
private Long id;
/**
* 会员等级id
*/
private Long levelId;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 昵称
*/
private String nickname;
/**
* 手机号码
*/
private String mobile;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String header;
/**
* 性别
*/
private Integer gender;
/**
* 生日
*/
private Date birth;
/**
* 所在城市
*/
private String city;
/**
* 职业
*/
private String job;
/**
* 个性签名
*/
private String sign;
/**
* 用户来源
*/
private Integer sourceType;
/**
* 积分
*/
private Integer integration;
/**
* 成长值
*/
private Integer growth;
/**
* 启用状态
*/
private Integer status;
/**
* 注册时间
*/
private Date createTime;
/**
* 社交登录UID
*/
private String socialUid;
/**
* 社交登录TOKEN
*/
private String accessToken;
/**
* 社交登录过期时间
*/
private long expiresIn;
}
别忘记在需要用到session的启动类上加上注解:
@EnableRedisHttpSession //整合redis作为session存储
然后就可以进行操作了
@GetMapping("/login")
public String login(HttpSession session){
//前置操作得到想存的内容data
session.setAttribute("loginUser",data);
//后置操作
return "SUCCESS";
}
进行登录操作后,查看网页可以看到
进入同一域的不同子域,可以发现都会有名为GULISESSION的session以供使用