Spring boot 整合Redis及Redis共享Session

介绍

Redis是一个缓存消息中间件及具有丰富特性的键值存储系统。本文主要介绍Spring boot 如何使用redis做缓存,如何对redis缓存进行定制化配置(如key的有效期)以及spring boot 如何初始化redis做缓存,以及如何在Spring Boot项目中加入redis来实现对session的存储与管理。

Spring boot 集成Redis

pom依赖

 <!--redis配置开始-->     
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <!-- 具体版本号依赖parent版本 -->
        </dependency>
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
            <!-- 具体版本号依赖parent版本 -->
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.7</version>
        </dependency>
   <!--redis配置结束-->

配置信息(application.properties)

## Redis 配置
## Redis数据库索引(默认为0)
spring.redis.database=0
## Redis服务器地址
spring.redis.host=*.*.*.*
## Redis服务器连接端口
spring.redis.port=6379
## 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

### session的配置 start ############
# session的存储方式的类型配置
spring.session.store-type=redis
#spring.session.redis.namespace=
# session 存活时间
server.session.timeout=3000
### session的配置 end ############

Redis配置类

具体代码如下:



import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
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.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;

@Configuration
@EnableAutoConfiguration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {
    @Value("${spring.redis.host}")
    private String host;

    @Value("${spring.redis.port}")
    private int port;

    @Value("${spring.redis.timeout}")
    private int timeout;

    @Value("${spring.redis.database}")
    private int database;

    @Value("${spring.redis.password}")
    private String password;

    /**
     * 键的生成策略
     *
     * @return
     */
    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object o, Method method, Object... objects) {
                StringBuilder sb = new StringBuilder();
                sb.append(o.getClass().getName());
                sb.append(method.getName());
                for (Object obj : objects) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 连接redis的工厂类
     *
     * @return JedisConnectionFactory
     */
    @Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(host);
        factory.setPort(port);
        factory.setTimeout(timeout);
        factory.setPassword(password);
        factory.setDatabase(database);
        return factory;
    }

    /**
     * 配置CacheManager 管理cache
     *
     * @param redisTemplate
     * @return
     */
    @Bean
    public CacheManager cacheManager(RedisTemplate redisTemplate) {
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        cacheManager.setDefaultExpiration(60*60); // 设置key-value超时时间
        return cacheManager;
    }


    /**
     * 配置RedisTemplate
     * 设置添加序列化器
     * key 使用string序列化器
     * value 使用Json序列化器
     * 还有一种简答的设置方式,改变defaultSerializer对象的实现。
     *
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        //StringRedisTemplate的构造方法中默认设置了stringSerializer
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        //set key serializer
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        //set value serializer
        template.setDefaultSerializer(jackson2JsonRedisSerializer);

        template.setConnectionFactory(redisConnectionFactory());
        template.afterPropertiesSet();
        return template;

    }

}

注意:在RedisCacheConfig类中注解@Value读取springboot的默认配置文件信息中redis的相关配置的信息。
分析:缓存类继承的是CachingConfigurerSupport,它把读取的配置文件信息应用到类中。在这个类中keyGenerator()方法是key的生成策略,CacheManager()方法是缓存管理策略,redisConnectionFactory()是redis连接,redisTemplate()方法是redisTemplate配置信息,配置后使redis中能存储Java对象。
测试下配置是否成功:

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    @Test
    public void stringTest() {
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        valueOperations.set("hello", "redis");
        System.out.println("useRedisDao = " + valueOperations.get("hello"));
    }
}

简单封装的Redis工具类:

@Component
public class RedisUtils {

    @SuppressWarnings("rawtypes")
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 批量删除对应的value
     *
     * @param keys
     */
    public void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }

    /**
     * 批量删除key
     *
     * @param pattern
     */
    @SuppressWarnings("unchecked")
    public void removePattern(final String pattern) {
        Set<Serializable> keys = redisTemplate.keys(pattern);
        if (keys.size() > 0)
            redisTemplate.delete(keys);
    }

    /**
     * 删除对应的value
     *
     * @param key
     */
    @SuppressWarnings("unchecked")
    public void remove(final String key) {
        if (exists(key)) {
            redisTemplate.delete(key);
        }
    }

    /**
     * 判断缓存中是否有对应的value
     *
     * @param key
     * @return
     */
    @SuppressWarnings("unchecked")
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 读取缓存
     *
     * @param key
     * @return
     */
    @SuppressWarnings("unchecked")
    public Object get(final String key) {
        Object result = null;
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public boolean set(final String key, Object value) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 写入缓存
     *
     * @param key
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public boolean set(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

}

查询数据库时自动使用缓存,根据方法生成缓存,参考代码如下:

   @RequestMapping(value = "/getAddr",method = RequestMethod.GET,
            produces = "application/json; charset=utf-8")
    @Cacheable(value = "address-cache", key = "#id")
    // 设置缓存的名称,也可以通过key属性指定缓存的key,keyGenerator指定key生成策略器(keyGenerator一般推荐在重写CachingConfigurerSupport类里面的方法适合全局指定)
    @ResponseBody
    public Address getAddress(String id) {
        //模拟数据库查询出数据
        Address addr = new Address("001", "北京市", "海淀区");
        System.out.println("==========你看见这句话表示没有缓存时候打印出来的========");
        return addr;
    }

Session 共享

分布式系统中session共享有很多不错的解决方案,其中托管到缓存中是比较常见的方案之一,下面利用Session-spring-session-data-redis实现session共享。具体配置已在上面说明
下面测试session是否保存到redis中:

 @RequestMapping(value = "testSession",method = RequestMethod.GET,
            produces = "application/json; charset=utf-8")
    @ResponseBody
    public Map<String, Object> testSession(HttpServletRequest request) {
        HttpSession httpSession = request.getSession();
        // 设置session中的值
        httpSession.setAttribute("username", "session" + System.currentTimeMillis());
        Map<String, Object> rtnMap = new HashMap<>();
        Enumeration<String> attributeNames = request.getSession().getAttributeNames();
        while (attributeNames.hasMoreElements()) {
            String name = attributeNames.nextElement();
            rtnMap.put(name, httpSession.getAttribute(name));
        }
        rtnMap.put("sessionId", httpSession.getId());
        return rtnMap;
    }

访问http://localhost:8081/helloboot/api/testSession后,返回数据如下:

{
sessionId: "91f2f61d-d05c-4331-b084-b887e8a1c085",
username: "session1523442869503"
}

去Redis中查看,结果如下:
这里写图片描述
共享session
另外找一个机器,照着这个配置再来一遍,自动启用session共享,因为sessionId都存在了同一个redis中。大功就告成了!

©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值