spring boot学习5之session+redis解决session共享问题

          应用的集群部署或分布式部署,经常遇到session共享的问题,要么在nginx代理解决(比如ip hash),要么在tomcat的context.xml配置redis。spring boot也提供了session用redis解决共享的方法。

     

pom.xml

  1. <parent>  
  2.             <groupId>org.springframework.boot</groupId>  
  3.             <artifactId>spring-boot-starter-parent</artifactId>  
  4.             <version>1.5.2.RELEASE</version>  
  5.         </parent>  
  6.     
  7.     <dependencies>  
  8.         <dependency>  
  9.             <groupId>org.springframework.boot</groupId>  
  10.             <artifactId>spring-boot-starter-web</artifactId>  
  11.            <!--  <version>${spring_versin}</version> -->  
  12.   
  13.             <exclusions>  
  14.                 <exclusion>  
  15.                     <groupId>org.springframework.boot</groupId>  
  16.                     <artifactId>spring-boot-starter-tomcat</artifactId>  
  17.                 </exclusion>  
  18.             </exclusions>   
  19.   
  20.         </dependency>  
  21.         <dependency>  
  22.             <groupId>org.springframework.boot</groupId>  
  23.             <artifactId>spring-boot-starter-tomcat</artifactId>  
  24.             <!-- <version>${spring_versin}</version> -->  
  25.             <scope>provided</scope>  
  26.         </dependency>  
  27.           
  28.     <dependency>  
  29.             <groupId>org.springframework.boot</groupId>  
  30.             <artifactId>spring-boot-starter-redis</artifactId>  
  31.             <version>1.4.6.RELEASE</version>  
  32.         </dependency>  
  33.           
  34.   
  35.        <dependency>  
  36.         <groupId>org.springframework.session</groupId>  
  37.         <artifactId>spring-session-data-redis</artifactId>  
  38.           
  39.     </dependency>  
  40.   
  41.         </dependencies>  
  42.           

application.yml的配置

  1. logging:  
  2.   config: classpath:logback.xml  
  3.   path: d:/logs  
  4. server:  
  5.   port: 8080  
  6.   session-timeout: 60  
  7.   
  8. spring:  
  9.     redis:  
  10.        database: 0  
  11.        host: 127.0.0.1  
  12.        port: 6379  
  13.        password:  
  14.        timeout: 0  
  15.        pool:  
  16.            max-active: 8  
  17.            max-wait: -1  
  18.            max-idle: 8  
  19.            min-idle: 0  
  20.     session:  
  21.       store-type: none  

RedisSessionConfig.java

  1. package com.fei.springboot.config;  
  2.   
  3. import org.springframework.context.annotation.Configuration;  
  4. import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;  
  5.   
  6. @Configuration  
  7. //maxInactiveIntervalInSeconds 默认是1800秒过期,这里测试修改为60秒  
  8. @EnableRedisHttpSession(maxInactiveIntervalInSeconds=60)  
  9. public class RedisSessionConfig{  
  10.   
  11. }  

 如果不需要做特殊处理,只需直接使用注解@EnableRedisHttpSession即可,打开 @EnableRedisHttpSession源码,发现maxInactiveIntervalInSeconds  session的过期时间默认是1800秒即30分钟,如果需要修改,注解时进行修改即可。如果想对redisSession做一些特殊处理。看@EnableRedisHttpSession源码,头部的注释,也给出了一些方案。

注解@interface EnableRedisHttpSession的源码

  1. /* 
  2.  * Copyright 2014-2016 the original author or authors. 
  3.  * 
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  * you may not use this file except in compliance with the License. 
  6.  * You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, 
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  * See the License for the specific language governing permissions and 
  14.  * limitations under the License. 
  15.  */  
  16.   
  17. package org.springframework.session.data.redis.config.annotation.web.http;  
  18.   
  19. import java.lang.annotation.Documented;  
  20. import java.lang.annotation.Retention;  
  21. import java.lang.annotation.Target;  
  22.   
  23. import org.springframework.context.annotation.Configuration;  
  24. import org.springframework.context.annotation.Import;  
  25. import org.springframework.data.redis.connection.RedisConnectionFactory;  
  26. import org.springframework.session.SessionRepository;  
  27. import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;  
  28. import org.springframework.session.data.redis.RedisFlushMode;  
  29.   
  30. /** 
  31.  * Add this annotation to an {@code @Configuration} class to expose the 
  32.  * SessionRepositoryFilter as a bean named "springSessionRepositoryFilter" and backed by 
  33.  * Redis. In order to leverage the annotation, a single {@link RedisConnectionFactory} 
  34.  * must be provided. For example: <pre> 
  35.  * <code> 
  36.  * {@literal @Configuration} 
  37.  * {@literal @EnableRedisHttpSession} 
  38.  * public class RedisHttpSessionConfig { 
  39.  * 
  40.  *     {@literal @Bean} 
  41.  *     public JedisConnectionFactory connectionFactory() throws Exception { 
  42.  *         return new JedisConnectionFactory(); 
  43.  *     } 
  44.  * 
  45.  * } 
  46.  * </code> </pre> 
  47.  * 
  48.  * More advanced configurations can extend {@link RedisHttpSessionConfiguration} instead. 
  49.  * 
  50.  * @author Rob Winch 
  51.  * @since 1.0 
  52.  * @see EnableSpringHttpSession 
  53.  */  
  54. @Retention(java.lang.annotation.RetentionPolicy.RUNTIME)  
  55. @Target({ java.lang.annotation.ElementType.TYPE })  
  56. @Documented  
  57. @Import(RedisHttpSessionConfiguration.class)  
  58. @Configuration  
  59. public @interface EnableRedisHttpSession {  
  60.     int maxInactiveIntervalInSeconds() default 1800;  
  61.   
  62.     /** 
  63.      * <p> 
  64.      * Defines a unique namespace for keys. The value is used to isolate sessions by 
  65.      * changing the prefix from "spring:session:" to 
  66.      * "spring:session:<redisNamespace>:". The default is "" such that all Redis 
  67.      * keys begin with "spring:session". 
  68.      * </p> 
  69.      * 
  70.      * <p> 
  71.      * For example, if you had an application named "Application A" that needed to keep 
  72.      * the sessions isolated from "Application B" you could set two different values for 
  73.      * the applications and they could function within the same Redis instance. 
  74.      * </p> 
  75.      * 
  76.      * @return the unique namespace for keys 
  77.      */  
  78.     String redisNamespace() default "";  
  79.   
  80.     /** 
  81.      * <p> 
  82.      * Sets the flush mode for the Redis sessions. The default is ON_SAVE which only 
  83.      * updates the backing Redis when 
  84.      * {@link SessionRepository#save(org.springframework.session.Session)} is invoked. In 
  85.      * a web environment this happens just before the HTTP response is committed. 
  86.      * </p> 
  87.      * <p> 
  88.      * Setting the value to IMMEDIATE will ensure that the any updates to the Session are 
  89.      * immediately written to the Redis instance. 
  90.      * </p> 
  91.      * 
  92.      * @return the {@link RedisFlushMode} to use 
  93.      * @since 1.1 
  94.      */  
  95.     RedisFlushMode redisFlushMode() default RedisFlushMode.ON_SAVE;  
  96. }  

spring boot中的session redis配置就如此简单。

写个controller测试下

  1. package com.fei.springboot.controller;  
  2.   
  3. import javax.servlet.http.HttpServletRequest;  
  4.   
  5. import org.springframework.stereotype.Controller;  
  6. import org.springframework.web.bind.annotation.RequestMapping;  
  7. import org.springframework.web.bind.annotation.ResponseBody;  
  8.   
  9. @Controller  
  10. @RequestMapping("/")  
  11. public class TestController {  
  12.   
  13.     @RequestMapping(value="/getSessionId")  
  14.     @ResponseBody  
  15.     public String getSessionId(HttpServletRequest request){  
  16.           
  17.         Object o = request.getSession().getAttribute("springboot");  
  18.         if(o == null){  
  19.             o = "spring boot 牛逼了!!!有端口"+request.getLocalPort()+"生成";  
  20.             request.getSession().setAttribute("springboot", o);  
  21.         }  
  22.           
  23.         return "端口=" + request.getLocalPort() +  " sessionId=" + request.getSession().getId() +"<br/>"+o;  
  24.     }  
  25.       
  26. }  

写个启动类

  1. package com.fei.springboot;  
  2.   
  3. import org.springframework.boot.SpringApplication;  
  4. import org.springframework.boot.autoconfigure.EnableAutoConfiguration;  
  5. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  6. import org.springframework.boot.builder.SpringApplicationBuilder;  
  7. import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;  
  8. import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;  
  9. import org.springframework.boot.web.support.SpringBootServletInitializer;  
  10. import org.springframework.context.annotation.ComponentScan;  
  11.   
  12. @EnableAutoConfiguration  
  13. @ComponentScan(basePackages={"com.fei.springboot"})  
  14. @SpringBootApplication  
  15. public class Application extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer{  
  16.   
  17.      @Override    
  18.     protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {    
  19.         return application.sources(Application.class);    
  20.     }    
  21.   
  22.        
  23.      public static void main(String[] args) throws Exception {  
  24.             SpringApplication.run(Application.class, args);  
  25.         }  
  26.   
  27.     public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {  
  28.     //  configurableEmbeddedServletContainer.setPort(9090);  
  29.     }  
  30. }  

修改application.yml中的server.port的端口为80,执行启动类,然后修改为8080,再次执行启动类。

浏览器测试

http://127.0.0.1/getSessionId

得得的结果是

  1. 端口=80 sessionId=3312d8db-a8dc-4df3-bc3a-628c311c0b4a  
  2. spring boot 牛逼了!!!有端口80生成  
http://127.0.0.1:8080/getSessionId
得到的结果是

  1. 端口=8080 sessionId=3312d8db-a8dc-4df3-bc3a-628c311c0b4a  
  2. spring boot 牛逼了!!!有端口80生成  

使用redis-client,查看



  注意事项:

如果启动时发现报错:

ERR Unsupported CONFIG parameter: notify-keyspace-events; nested exception is redis.clients.jedis.exceptions.JedisDataException


这是因为redis服务器版本和jar包版本不一致造成的。


比如说,我这用的spring-session-data-redis版本是1.3.0,到maven 仓库中查询http://mvnrepository.com/


发现redis是2.8.1,看了下我用的服务器是2.6的,我立刻下载了个最新版的3.x,我是本地测试的,用window的。更换redis服务器后,不再报错了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值