本文代码已提交github: https://github.com/LCABC777/Springboot-redis
(1)Springboot中使用redis操作的两种方式:lettuce和jedis,两者在进行操作时都需要序列化器来实现序列化
(推荐使用jackson2JsonRedisSerializer,相比于JDK提供的序列化器和String序列化器长度更短),
lettuce和redis都是 redis的客户端。
(2)Springboot 1.x整合Spring-data-redis底层用的是jedis,Springboot 2.x整合spring-data-redis用的是lettuce,
jedis在多线程环境下是非线程安全的,使用了jedis pool连接池,为每个Jedis实例增加物理连接。
Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问。
本文的基本环境:
springboot: 2.x
redis版本:redis 3.0.0
linux系统:centos 6.5
jdk:1.8
(1)添加maven依赖
<!--web依赖-->
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<!--redis依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency> <!--junit依赖-->
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
<!--spring test测试依赖> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId>
</dependency>
(2)application.properties中redis数据源及lettuce客户端配置
#redis # 连接设置 spring.redis.database=0 spring.redis.host=192.168.18.128 spring.redis.port=6379 spring.redis.password=123456 spring.redis.timeout=10000ms # 连接池设置 spring.redis.lettuce.pool.max-idle=8 spring.redis.lettuce.pool.max-wait= spring.redis.lettuce.pool.min-idle=0 spring.redis.lettuce.pool.max-active=8
(3)redis模板(redisTemplate,提供对redis数据库的操作方法)及缓存管理器(cacheManager)配置
package com.lc.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.*; import javax.annotation.Resource; import java.time.Duration; import java.util.HashMap; import java.util.Map; @Configuration public class RedisConfig {
//lettuce客户端连接工厂 @Resource private LettuceConnectionFactory lettuceConnectionFactory;
//日志 private Logger logger=LoggerFactory.getLogger(RedisConfig.class);
//json序列化器 private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); //缓存生存时间 private Duration timeToLive = Duration.ofDays(1);
@Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
//redis缓存配置 RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(this.timeToLive) .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())) .disableCachingNullValues();
//缓存配置map Map<String,RedisCacheConfiguration> cacheConfigurationMap=new HashMap<>();
//自定义缓存名,后面使用的@Cacheable的CacheName cacheConfigurationMap.put("users",config); cacheConfigurationMap.put("default",config);
//根据redis缓存配置和reid连接工厂生成redis缓存管理器 RedisCacheManager redisCacheManager = RedisCacheManager.builder(connectionFactory) .cacheDefaults(config) .transactionAware() .withInitialCacheConfigurations(cacheConfigurationMap) .build(); logger.debug("自定义RedisCacheManager加载完成"); return redisCacheManager; }
//redisTemplate模板提供给其他类对redis数据库进行操作 @Bean(name = "redisTemplate") public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){ RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); redisTemplate.setKeySerializer(keySerializer()); redisTemplate.setHashKeySerializer(keySerializer()); redisTemplate.setValueSerializer(valueSerializer()); redisTemplate.setHashValueSerializer(valueSerializer()); logger.debug("自定义RedisTemplate加载完成"); return redisTemplate; }
//redis键序列化使用StrngRedisSerializer private RedisSerializer<String> keySerializer() { return new StringRedisSerializer(); }
//redis值序列化使用json序列化器 private RedisSerializer<Object> valueSerializer() { return new GenericJackson2JsonRedisSerializer(); }
//缓存键自动生成器 @Bean public KeyGenerator myKeyGenerator() { 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(); }; } }
(4)利用redisTemplate进行对redis数据库的操作
注入redisTemplate
@Autowired private RedisTemplate redisTemplate;
(5)使用redis的hash来存储map,并做缓存处理,用来验证是否成功
//添加hash,需要hash名和存储的键值对Map
public void setHash(String hashName,Map<String,String> map) { redisTemplate.opsForHash().putAll(hashName,map); }
//Springboot的启动器main方法上需要加上@EnableCaching开启缓存,使用了@Cacheable注解后,缓存的值将被存入redis数据库中
//缓存名可以为RedisConfig中自定义的缓存名,键生成器为RedisConig中自定义的键生成器,也可以自己自定义缓存key名 @Cacheable(cacheNames = "users",keyGenerator ="myKeyGenerator")
//从redis中获取map public Map<Object,Object> getHash(String hashName){ if (redisTemplate.hasKey(hashName)) { System.out.println(redisTemplate.opsForHash().entries(hashName)); return redisTemplate.opsForHash().entries(hashName); }else { return null; } }
(6)使用junit来测试缓存
import com.lc.Starter; import com.lc.service.RedisService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.HashMap; import java.util.Map; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Starter.class) public class MyTest { @Autowired private RedisService redisService; @Test public void hashTest(){ Map<String,String> map=new HashMap<>(); map.put("a879","1"); map.put("2131","23");
//redis中添加hash redisService.setHash("ccc",map);
//多次获取hash Map hash=redisService.getHash("ccc"); redisService.getHash("ccc");
redisService.getHash("ccc") if (hash!=null){ System.out.println(hash.toString()); } } }
(7)多次获取hash,测试结果只执行了两次打印方法,说明除了第一次都是从redis的缓存库中读取的缓存,而不是getHash中的redisTemplate.opsForHash().entries(hashName)
(8)从redisDesktop中可以清楚的看到redis的存储,setHash方法将ccc这个hash存入了redis库中,而getHash方法做缓存处理后,程序直接将包名+方法名+参数这个由keyGenertor自动生成的字符串作为key, Geneic json序列化器将要缓存类型在java中的包名和缓存的值组成json串作为value实现了缓存
本文代码已提交github: https://github.com/LCABC777/Springboot-redis