zoukankan      html  css  js  c++  java
  • 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,不要停止我们的脚步。继续努力!
  • 相关阅读:
    Codeforces 158E Phone Talks:dp
    Codeforces 453B Little Pony and Harmony Chest:状压dp【记录转移路径】
    Codeforces 358D Dima and Hares:dp【只考虑相邻元素】
    Codeforces 478D Red-Green Towers:dp
    Codeforces 219D Choosing Capital for Treeland:Tree dp
    sublime text3配置c++环境和一些插件
    2019 wannafly winter camp day5-8代码库
    Wannafly Winter Camp Day8(Div1,onsite) E题 Souls-like Game 线段树 矩阵乘法
    2019 wannafly winter camp day1-4代码库
    Wannafly Winter Camp Day5 Div1 E题 Fast Kronecker Transform 转化为NTT或FFT
  • 原文地址:https://www.cnblogs.com/jinronga/p/13940925.html
Copyright © 2011-2022 走看看