SpringSesion共享使用、自定义Session作用域

SpringSesion共享使用、自定义Session作用域

通常情况下,Tomcat、Jetty等Servlet容器,会默认将Session保存在内存中。如果是单个服务器实例的应用,将Session保存在服务器内存中是一个非常好的方案。但是这种方案有一个缺点,就是不利于扩展。

目前越来越多的应用采用分布式部署,用于实现高可用性和负载均衡等。那么问题来了,如果将同一个应用部署在多个服务器上通过负载均衡对外提供访问,如何实现Session共享?

实际上实现Session共享的方案很多,其中一种常用的就是使用Tomcat、Jetty等服务器提供的Session共享功能,将Session的内容统一存储在一个数据库(如MySQL)或缓存(如Redis)中。

下面我们将在springcloud微服务项目中,使用第三方存储服务保存(redis),但是如果是直接使用redis,要求对我们的代码进行修改。所以使用spring session。spring session的原理是对我们的request和response进行了包装。因为session的获取是request.getSession() ,所以包装了请求体,而cookie的设置需要设置到response中所以也包装了响应体。spring session很完美的解决了代码重构的问题。还能对接不同的存储中间件,不仅仅限于redis。子域共享问题。自定义cookie的响应信息。设置cookie 的作用域domean 只能是当前域名或者父域名。domean 是子域名可以拿到父域名的信息,domean是父域名不能拿到子域名的信息。

代码

spring session guide

Sample Applications that use Spring Boot session redis guide

Sample Applications that use Spring Java-based configuration session redis guide

[HttpSession with Redis JSON serialization](https://github.com/spring-projects/spring-session/tree/2.1.12.RELEASE/samples/boot/redis-json)

依赖

<!-- 整合spring session完成session 共享问题 -->
<dependency>
  <groupId>org.springframework.session</groupId>
  <artifactId>spring-session-data-redis</artifactId>
</dependency>
<!-- redis -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置文件

# redis的连接信息
spring.redis.host=192.168.1.10
spring.redis.port=6379
# 将session数据保存到redis中
spring.session.store-type=redis
spring.session.redis.flush-mode=on_save
spring.session.redis.namespace=spring:session

启用自动配置(启动类配置 )

@EnableRedisHttpSession // 整合redis作为session存储,就是通过filter包装了我们的请求体和响应体
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class GulimallAuthServerApplication {

	public static void main(String[] args) {
		SpringApplication.run(GulimallAuthServerApplication.class, args);
	}

}

Spring sessioin 中redis的序列化、cookie的自定义设置

/**
 *
 * Description:设置Session作用域、自定义cookie序列化机制
 * date:2020/11/5
 */
@Configuration
public class GlMallSessionConfig {

	@Bean
	public CookieSerializer cookieSerializer(){
		DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
		// 明确的指定Cookie的作用域
		cookieSerializer.setDomainName("gulimall.com");
		cookieSerializer.setCookieName("FIRESESSION");
		return cookieSerializer;
	}

	/**
	 * 自定义序列化机制
	 * 这里方法名必须是:springSessionDefaultRedisSerializer
	 */
	@Bean
	public RedisSerializer<Object> springSessionDefaultRedisSerializer(){
		return new GenericJackson2JsonRedisSerializer();
	}
}
---存入session(统一存储到redis,进行服务之间进行共享Session)
@PostMapping("/login")
public String login(UserLoginVo userLoginVo, RedirectAttributes redirectAttributes, HttpSession session){

    //远程登录
    R login = memberFeignService.login(userLoginVo);

    if (login.getCode()==0){
        //登录成功
        MeberRespVo meberRespVo = login.getData("data", new TypeReference<MeberRespVo>() {
        });
        //存入session(统一存储到redis,进行服务之间进行共享Session)
        session.setAttribute("loginUser",meberRespVo);
        return "redirect:http://gulimall.com";
    }else {

        HashMap<String, String> errors = new HashMap<>();
        errors.put("errors",login.getData("msg",new TypeReference<String>(){}));
        redirectAttributes.addFlashAttribute("errors",errors);

        return "redirect:http://auth.gulimall.com/login.html";
    }
}

在获取session的时候不同服务只需要在获取 redis中session的key即可(session.loginUser.nickname)loginUser为key。

注意:需要使用共享Session的服务都要进行 以上的配置,不然使用不了存在 redis中的Session。

Spring Session原理

Session核心原理:
1)、@EnableRedisHttpSession导入RedisHttpSessionConfiguration配置
1、给容器添加了一个组件RedisIndexedSessionRepository
RedisIndexedSessionRepository:redis操作session。session的增删改查封装类
2、SessionRepositoryFilter --》Filter: session存储的过滤器,每个请求都必须经过filter
1、创建的时候 ,就自动从容器中获取SessionRepository
2、原始的request,response都被包装。SessionRequestWrapper,SeesionRepositoryResponseWrapper
3、以后获取session。request.getSession();
//SessionRepositoryRequestWrapper
4、wrappedRequest.getSession()==>SessionRepositry中获取的。
装饰者模式:把原生的请求封装成自己的
Seesion会自动延期,redis中也是有过期时间的



#### 暑假到现在很久没更新了 因为在学校没时间(好吧其实就是因为自己懒哈哈,在学校安逸过头了)、今天刚弄完谷粒商城分布式Session共享的问题,想要更加详细的知识关注:https://gitee.com/jinronga/guilimall,不要停止我们的脚步。继续努力!
原文地址:https://www.cnblogs.com/jinronga/p/13940925.html