分布式下的session
- 在分布式项目下
- 项目中使用
在分布式项目下
session是一种会话状态,是储存在服务器上的,可以区分每个用户。浏览器会保存着对应的信息。浏览器保存的叫cookie。用户访问,浏览器会带上cookie让服务器识别。
如果是单体项目,session是在一个服务器下,所有的用户信息都保存在一个服务器,好做区分。
但是如果在分布式情况下,一个大的系统有很多模块,比如电商项目,有登录权限模块,商品模块,商品检索模块… 每个模块都是在不同的服务器上部署的,如果用户进行登录,session只在一个服务器上保存,其它服务器并不能同步。
痛点:解决session共享的问题。
这里就可以把session存储到一个公用的地方,各个模块都能取到的地方。如数据库, NoSql redis… 等。
而spring session框架正好能解决这个问题,更加简化我们的操作。
项目中使用
可以照着官网来。
pom.xml
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- https://docs.spring.io/spring-session/docs/2.2.2.RELEASE/reference/html5/guides/boot-redis.html --><!-- 使用redis管理session --><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId></dependency>
配置类
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.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;/*** @author echo lovely* @date 2021/9/26 17:35* @description session 配置*/@EnableRedisHttpSession
@Configuration
public class HttpSessionConfig {// cookie 存储规则 确保在*.domain.com 同一个域名下及子域名@Beanpublic CookieSerializer cookieSerializer() {DefaultCookieSerializer serializer = new DefaultCookieSerializer();serializer.setCookieName("JSESSIONID");// 设置子域共享sessionserializer.setDomainName("yourdomain.com");return serializer;}// RedisSerializer@Beanpublic RedisSerializer<Object> springSessionDefaultRedisSerializer() {// 使用json方式序列化.. 保存用户的session信息return new GenericJackson2JsonRedisSerializer();}}
yaml配置, 配置session以redis存储
spring:redis:host: 192.168.56.10port: 6379session:store-type: redistimeout: 30m
springmvc使用的话,还是使用HttpSession, 设置值就行了。
这个httpSession会经过过滤器,过滤将请求和响应用装饰器模式包装。
原理
public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {// 原生requestpublic SessionRepositoryRequestWrapper(HttpServletRequest original) {super(original);}public HttpSession getSession() {return getSession(true);}public HttpSession getSession(boolean createNew) {// create an HttpSession implementation from Spring Session}// ... other methods delegate to the original HttpServletRequest ...
}
经过过滤器后被包装。
public class SessionRepositoryFilter implements Filter {public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {HttpServletRequest httpRequest = (HttpServletRequest) request;SessionRepositoryRequestWrapper customRequest =new SessionRepositoryRequestWrapper(httpRequest);chain.doFilter(customRequest, response, chain);}// ...
}