天天看點

springboot中redis的使用和分布式session共享問題

本文旨在解決分布式系統的session如何共享問題,大緻思路:session放入redis。其他解決方案:持久化、放cache等都可以,但是自從有了redis,這完全可以變的簡簡單單。

本文大緻分兩步:

1.springboot中如何使用redis。

2.redis如何解決session共享

pom依賴

<!--redis配置開始-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-redis</artifactId>
            <version>${spring-data-redis.version}</version>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>${jedis.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>
        <!--redis配置結束-->
           

添加redis配置類

該配置類同樣可以配置緩存失效時間等。
package com.mos.quote.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

/**
 * @author Administrator
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    @Bean
    public KeyGenerator KeyGenerator(){
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(method.getName());
            for (Object obj : params) {
                sb.append(obj.toString());
            }
            return sb.toString();
        };
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }

    @Bean
    public CacheManager cacheManager(RedisTemplate<String,String> redisTemplate) {
        RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
        //設定緩存過期時間
        rcm.setDefaultExpiration(600000);
        return rcm;
    }
}

           

配置redis服務

# Redis資料庫索引(預設為0)
spring.redis.database=0
# Redis伺服器位址
spring.redis.host=192.168.1.118
# Redis伺服器連接配接端口
spring.redis.port=6381
# Redis伺服器連接配接密碼(預設為空)
spring.redis.password=
# 連接配接池最大連接配接數(使用負值表示沒有限制)
spring.redis.pool.max-active=8
# 連接配接池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.pool.max-wait=-1
# 連接配接池中的最大空閑連接配接
spring.redis.pool.max-idle=8
# 連接配接池中的最小空閑連接配接
spring.redis.pool.min-idle=0
# 連接配接逾時時間(毫秒)
spring.redis.timeout=0
           

單元測試

  1. set值(字元串)
@Test
    public void put(){
        stringRedisTemplate.opsForValue().set("test001","test001");
        Assert.assertEquals("test001", stringRedisTemplate.opsForValue().get("test001"));
    }
           
往redis放一個key為test001、value為test001的值,然後檢視redis
springboot中redis的使用和分布式session共享問題

key=test001

  1. set值(object)
@Test
    public void testObj() throws Exception {
        SysUser user=new SysUser();
        user.setId("123456");
        user.setName("張三");
        ValueOperations<String, SysUser> operations=redisTemplate.opsForValue();
        operations.set("user1", user);
        operations.set("user2", user,5, TimeUnit.SECONDS);
        Thread.sleep(6000);
        Assert.assertFalse(redisTemplate.hasKey("user2"));
    }
           
往redis分别放key為user1和user2的對象,user2設定5秒失效,線程等待6秒再完成,期望結果:redis中有user1,沒有user2,bingo!!!
springboot中redis的使用和分布式session共享問題

ObjTest

解決session共享

使用spring-session-data-redis實作session共享,pom中引入該依賴(上文已添加),添加SessionConfig配置類。

對,沒看錯,隻需要這個就夠了。最長有效時間根據自己情況随意配置即可。

package com.mos.quote.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

/**
 * @author Administrator
 */
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 3000)
public class SessionConfig {
}
           

測試

寫一個簡單Controller,如下

@RequestMapping("testSessionTimeOut")
    public String testSessionTimeOut(String id,HttpSession session,Model model){
        Area area = areaService.getById(id);
        System.out.println("sessionId-------->"+session.getId());
        model.addAttribute("area",JSON.toJSONString(area));
        session.setAttribute("area",JSON.toJSONString(area));
        return "demo/test1";
    }
           
這裡可以看到sessionId:
springboot中redis的使用和分布式session共享問題

sessionId

看redis中,可以看到失效時間,sessionId等
springboot中redis的使用和分布式session共享問題

共享session

另外找一個機器,照着這個配置再來一遍,自動啟用session共享,因為sessionId都存在了同一個redis中。奏是這麼簡單。挽起袖子開始幹吧。