本文代碼已提交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