本章介紹SpringBoot與Redis整合,對緩存不太瞭解的能夠參考【SpringBoot】SpringBoot 緩存(十八)html
Redis安裝參考:【Redis】安裝及簡單使用java
一、SpringBoot Web項目搭建,參考【SpringBoot】SpringBoot 緩存(十八)node
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.test</groupId> 8 <artifactId>test-springboot-cache</artifactId> 9 <version>1.0-SNAPSHOT</version> 10 11 <parent> 12 <groupId>org.springframework.boot</groupId> 13 <artifactId>spring-boot-starter-parent</artifactId> 14 <version>2.1.8.RELEASE</version> 15 </parent> 16 17 <properties> 18 19 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 20 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 21 <java.version>1.8</java.version> 22 </properties> 23 24 <dependencies> 25 26 <dependency> 27 <groupId>org.springframework.boot</groupId> 28 <artifactId>spring-boot-starter-web</artifactId> 29 </dependency> 30 31 <dependency> 32 <groupId>org.springframework.boot</groupId> 33 <artifactId>spring-boot-starter-data-redis</artifactId> 34 </dependency> 35 36 37 <dependency> 38 <groupId>org.mybatis.spring.boot</groupId> 39 <artifactId>mybatis-spring-boot-starter</artifactId> 40 <version>2.0.1</version> 41 </dependency> 42 43 44 45 <!-- mysql --> 46 <dependency> 47 <groupId>mysql</groupId> 48 <artifactId>mysql-connector-java</artifactId> 49 <version>8.0.12</version> 50 </dependency> 51 52 <dependency> 53 <groupId>org.springframework.boot</groupId> 54 <artifactId>spring-boot-starter-test</artifactId> 55 <scope>test</scope> 56 </dependency> 57 58 </dependencies> 59 60 61 <!-- SpringBoot打包插件,能夠將代碼打包成一個可執行的jar包 --> 62 <build> 63 <plugins> 64 <plugin> 65 <groupId>org.springframework.boot</groupId> 66 <artifactId>spring-boot-maven-plugin</artifactId> 67 </plugin> 68 </plugins> 69 </build> 70 71 </project>
二、引入SpringBoot的redis啓動器mysql
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-data-redis</artifactId> 4 </dependency>
查看依賴,啓動器依賴了jedisweb
1 <dependency> 2 <groupId>redis.clients</groupId> 3 <artifactId>jedis</artifactId> 4 <version>${jedis}</version> 5 <optional>true</optional> 6 </dependency>
三、application.yml配置redis鏈接地址redis
redis單機配置spring
1 spring: 2 redis: 3 # 主機地址 4 host: 127.0.0.1 5 # 默認端口 6 port: 6379 7 # 密碼 8 password:123456
redis集羣模式配置sql
spring: redis: database: 0 # Redis數據庫索引(默認爲0) #host: 192.168.1.8 #port: 6379 password: 123456 timeout: 10000 # 鏈接超時時間(毫秒) pool: max-active: 8 # 鏈接池最大鏈接數(使用負值表示沒有限制) max-idle: 8 # 鏈接池中的最大空閒鏈接 max-wait: -1 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) min-idle: 0 # 鏈接池中的最小空閒鏈接 cluster: nodes: - 192.168.1.8:9001 - 192.168.1.8:9002 - 192.168.1.8:9003
redis哨兵模式配置數據庫
spring: redis: database: 0 # Redis數據庫索引(默認爲0) #host: 192.168.1.8 #port: 6379 password: 123456 timeout: 10000 # 鏈接超時時間(毫秒) pool: max-active: 8 # 鏈接池最大鏈接數(使用負值表示沒有限制) max-idle: 8 # 鏈接池中的最大空閒鏈接 max-wait: -1 # 鏈接池最大阻塞等待時間(使用負值表示沒有限制) min-idle: 0 # 鏈接池中的最小空閒鏈接 sentinel: master: mymaster # master名稱 nodes: - 192.168.1.8:9001 - 192.168.1.8:9002 - 192.168.1.8:9003
四、查看RedisAutoConfiguration類,此類事redis的自動配置來,能夠看到它自動註冊了redisTemplate和stringRedisTemplate,2個類apache
1 @Configuration 2 @ConditionalOnClass(RedisOperations.class) 3 @EnableConfigurationProperties(RedisProperties.class) 4 @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class }) 5 public class RedisAutoConfiguration { 6 7 @Bean 8 @ConditionalOnMissingBean(name = "redisTemplate") 9 public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) 10 throws UnknownHostException { 11 RedisTemplate<Object, Object> template = new RedisTemplate<>(); 12 template.setConnectionFactory(redisConnectionFactory); 13 return template; 14 } 15 16 @Bean 17 @ConditionalOnMissingBean 18 public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) 19 throws UnknownHostException { 20 StringRedisTemplate template = new StringRedisTemplate(); 21 template.setConnectionFactory(redisConnectionFactory); 22 return template; 23 } 24 25 }
五、編寫測試類,使用redisTemplate和stringRedisTemplate操做數據庫
1 package com.test.springboot.cache; 2 3 import com.test.springboot.cache.bean.Employee; 4 import com.test.springboot.cache.mapper.EmployeeMapper; 5 import org.junit.Test; 6 import org.junit.runner.RunWith; 7 import org.springframework.beans.factory.annotation.Autowired; 8 import org.springframework.boot.test.context.SpringBootTest; 9 import org.springframework.data.redis.core.RedisTemplate; 10 import org.springframework.data.redis.core.StringRedisTemplate; 11 import org.springframework.test.context.junit4.SpringRunner; 12 13 import javax.sound.midi.Soundbank; 14 15 @RunWith(SpringRunner.class) 16 @SpringBootTest 17 public class TestApplication { 18 19 @Autowired 20 EmployeeMapper employeeMapper; 21 22 // 操做k-v都是字符串的 23 @Autowired 24 StringRedisTemplate stringRedisTemplate; 25 26 // 操做k-v都是對象 27 @Autowired 28 RedisTemplate redisTemplate; 29 30 31 @Test 32 public void test01(){ 33 // 給redis中保存數據 34 stringRedisTemplate.opsForValue().append("msg", "hello world"); 35 System.out.println(stringRedisTemplate.opsForValue().get("msg")); 36 } 37 38 // 測試保存對象 39 @Test 40 public void test02(){ 41 42 Employee emp = employeeMapper.getEmpById(1); 43 redisTemplate.opsForValue().set("emp-02", emp); 44 System.out.println(redisTemplate.opsForValue().get("emp-01")); 45 } 46 47 } 48
注意:
測試方法test02中,保存對象時,會對Employee對象序列化,保存到redis中,因此Employee類必須實現Serializable接口,不然會報錯,下圖爲emp對象保存在redis中的數據。
a、本身將對象轉爲json(此種就時將對象轉成json字符串)
b、redisTmplate默認規則
分析redisTmplate默認規則:在RedisAutoConfiguration類中,RedisTemplate是經過簡單的new出來的,其中defaultSerializer默認序列化器是使用JDK自帶的,查看RedisTemplate類
1 public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V>, BeanClassLoaderAware { 2 3 ... 4 5 public RedisTemplate() {} 6 7 @Override 8 public void afterPropertiesSet() { 9 10 super.afterPropertiesSet(); 11 12 boolean defaultUsed = false; 13 14 if (defaultSerializer == null) { 15 // 使用jdk自帶的解析器 16 defaultSerializer = new JdkSerializationRedisSerializer( 17 classLoader != null ? classLoader : this.getClass().getClassLoader()); 18 } 19 20 ... 21 22 } 23 24 ... 25 }
若是想將數據以json的方式保存在redis中,須要本身注入一個redisTemplate,且此redisTemplate使用json的序列化器。
1 @Bean 2 public RedisTemplate<Object, Object> jsonRedisTemplate(RedisConnectionFactory redisConnectionFactory) 3 throws UnknownHostException { 4 5 RedisTemplate<Object, Object> template = new RedisTemplate<>(); 6 template.setConnectionFactory(redisConnectionFactory); 7 // 使用json的序列化器 8 template.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class)); 9 return template; 10 }
測試,使用jsonRedisTemplate來操做對象
1 @Autowired 2 RedisTemplate jsonRedisTemplate; 3 4 5 // 測試保存對象 6 @Test 7 public void test02(){ 8 9 Employee emp = employeeMapper.getEmpById(1); 10 // 給redis中保存對象 11 // 默認若是保存對象,使用jdk序列號機制,序列化的數據保存在redis中 12 jsonRedisTemplate.opsForValue().set("emp-02", emp); 13 System.out.println(jsonRedisTemplate.opsForValue().get("emp-02")); 14 }
結果以下:
redisTemplate.opsForValue();//操做字符串 redisTemplate.opsForHash();//操做hash redisTemplate.opsForList();//操做list redisTemplate.opsForSet();//操做set redisTemplate.opsForZSet();//操做有序set
一、使用debug=true的模式啓動項目,查看日誌,發現RedisCacheConfiguration匹配上了,而默認的
二、 查看RedisCacheConfiguration類,能夠看到,在容器不存在CacheManager的時候,它就會自動注入了RedisCacheManager,經過前一章(【SpringBoot】SpringBoot 緩存(十八))SpringBoot緩存的學習,知道CacheManager是用來管理緩存的Cache的。其中CacheManager也是使用的JDK自動的序列化器
@Configuration @ConditionalOnClass(RedisConnectionFactory.class) @AutoConfigureAfter(RedisAutoConfiguration.class) @ConditionalOnBean(RedisConnectionFactory.class) // 條件在不存在CacheManager Bean的時候生效 @ConditionalOnMissingBean(CacheManager.class) @Conditional(CacheCondition.class) class RedisCacheConfiguration { private final CacheProperties cacheProperties; private final CacheManagerCustomizers customizerInvoker; private final org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration; RedisCacheConfiguration(CacheProperties cacheProperties, CacheManagerCustomizers customizerInvoker, ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration) { this.cacheProperties = cacheProperties; this.customizerInvoker = customizerInvoker; this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable(); } // 注入CacheManager @Bean public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, ResourceLoader resourceLoader) { RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(determineConfiguration(resourceLoader.getClassLoader())); List<String> cacheNames = this.cacheProperties.getCacheNames(); if (!cacheNames.isEmpty()) { builder.initialCacheNames(new LinkedHashSet<>(cacheNames)); } return this.customizerInvoker.customize(builder.build()); } private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration( ClassLoader classLoader) { if (this.redisCacheConfiguration != null) { return this.redisCacheConfiguration; } Redis redisProperties = this.cacheProperties.getRedis(); org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration .defaultCacheConfig(); config = config.serializeValuesWith( // 使用默認的JDK序列化器 SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader))); if (redisProperties.getTimeToLive() != null) { config = config.entryTtl(redisProperties.getTimeToLive()); } if (redisProperties.getKeyPrefix() != null) { config = config.prefixKeysWith(redisProperties.getKeyPrefix()); } if (!redisProperties.isCacheNullValues()) { config = config.disableCachingNullValues(); } if (!redisProperties.isUseKeyPrefix()) { config = config.disableKeyPrefix(); } return config; } }
三、測試緩存,使用@Cacheable標籤,以下,調用getEmp方法,查看緩存內容
1 @Cacheable(cacheNames="emp", key = "emp#id" /*keyGenerator = "myKeyGenerator"*/) 2 public Employee getEmp(Integer id){ 3 System.out.println("===查詢" + id + "號員工"); 4 return employeeMapper.getEmpById(id); 5 }
緩存內容以下,存儲的也是emp對象的序列化結果
四、本身注入一個CacheManager的Bean,而且使用json序列化的方式
1 /** 2 * 緩存管理器 3 */ 4 @Bean 5 public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { 6 7 //初始化一個RedisCacheWriter 8 RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory); 9 10 //設置CacheManager的值序列化方式爲json序列化 11 RedisSerializer<Object> jsonSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class); 12 RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair 13 .fromSerializer(jsonSerializer); 14 RedisCacheConfiguration defaultCacheConfig=RedisCacheConfiguration.defaultCacheConfig() 15 .serializeValuesWith(pair); 16 17 //設置默認超過時時間是30秒 18 defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); 19 //初始化RedisCacheManager 20 return new RedisCacheManager(redisCacheWriter, defaultCacheConfig); 21 22 }
五、測試緩存,使用@Cacheable標籤,以下,測試時,先將原有緩存狀況,避免影響測試,調用getEmp方法,查看緩存內容