在分布式项目下
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 同一个域名下及子域名
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("JSESSIONID");
// 设置子域共享session
serializer.setDomainName("yourdomain.com");
return serializer;
}
// RedisSerializer
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
// 使用json方式序列化.. 保存用户的session信息
return new GenericJackson2JsonRedisSerializer();
}
}
yaml配置, 配置session以redis存储
spring:
redis:
host: 192.168.56.10
port: 6379
session:
store-type: redis
timeout: 30m
springmvc使用的话,还是使用HttpSession, 设置值就行了。
这个httpSession会经过过滤器,过滤将请求和响应用装饰器模式包装。
public class SessionRepositoryRequestWrapper extends HttpServletRequestWrapper {
// 原生request
public 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);
}
// ...
}