Spring Boot(八)集成Spring Cache 和 Redis
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Spring Boot(八)集成Spring Cache 和 Redis,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含13303字,纯文字阅读大概需要20分钟。
内容图文
![Spring Boot(八)集成Spring Cache 和 Redis](/upload/InfoBanner/zyjiaocheng/1277/723e0104448242e3b703ab4b40752c6a.jpg)
在Spring Boot中添加spring-boot-starter-data-redis依赖:
< dependency > < groupId >org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
在application.properties中指定redis服务器IP、端口和密码、连接数等:
# Redis服务器地址 spring.redis.host=127.0.0.1 # Redis服务器连接端口 使用默认端口6379可以省略配置 #spring.redis.port=6379 # Redis服务器连接密码(默认为空) #spring.redis.password= # 连接池最大连接数(如果配置<=0,则没有限制 ) spring.redis.jedis.pool.max-active=8
使用StringRedisTemplate 和RedisTemplate
StringRedisTemplate是Spring Boot内置的操作Redis的API实现类,另外还有一个API实现类是RedisTemplate。StringRedisTemplate的API假定所有的数据类型化都是字符类型,即key和value都是字符串类型,对于常见额SpringBoot应用系统,使用字符串操作也已经足够了,而且能方便的通过客户端管理工具管理。StringRedisTemplate继承RedisTemplate,与RedisTemplate不同的是重新设置了序列化策略,使用StringRedisSerialier类来序列化key-value,包括List、Hash、Set等数据结构。
1 @RunWith(SpringRunner.class) 2@SpringBootTest 3publicclass SpringbootCacheApplicationTests { 4 5 @Autowired 6 StringRedisTemplate stringRedisTemplate; //操作 k-v 字符串 7 8 @Autowired 9 RedisTemplate redisTemplate; //k- v 都是对象1011/**12 * redis 常见 13 * String(字符串) List(列表) Set(集合) Hash(散列) ZSet(有序集合) 14*/1516@Test17publicvoid test1() { 18 stringRedisTemplate.opsForValue().append("StringKey", "字符串数值"); 19 String value = stringRedisTemplate.opsForValue().get("StringKey"); 20 System.out.println(value); 21 } 22@Test 23publicvoid test2() { 2425 Product product = productMapper.getProductById(4L); 26 redisTemplate.opsForValue().set("produxtid4",product); 2728} 29 }
spring-boot-autoconfigure-2.0.4.RELEASE.jar包中RedisAutoConfiguration.java已经自动声明了两个redis操作bean:
RedisAutoConfiguration.java实现代码:
因此我们只要在使用的地方注入即可:
@Autowired StringRedisTemplate stringRedisTemplate; // 操作 k-v 字符串 @Autowired RedisTemplate redisTemplate; // k- v 都是对象
StringRedisTemplate 提供opsForValue用来操作key-value,如上面的示例,另外还提供了一系列opsForHash()、opsForList()、opsForSet()、opsForZSet()等方法用来操作不同结构类型的数据。
运行上面的测试方法,查看redis客户端:
可以发现,出现了一些无法识别的字符,查看RedisTemplate源码可这个是由于默认使用了JDK的序列化机制,而StringRedisTemplate没有出乱码是因为它修改了序列化器
StringRedisTemplate实现:
![技术分享图片](/img/jia.gif)
![技术分享图片](/img/jian.gif)
1 public class StringRedisTemplate extends RedisTemplate<String, String> { 2 3/** 4 * Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)} 5 * and {@link #afterPropertiesSet()} still need to be called. 6*/ 7public StringRedisTemplate() { 8 RedisSerializer<String> stringSerializer = new StringRedisSerializer(); 9 setKeySerializer(stringSerializer); 10 setValueSerializer(stringSerializer); 11 setHashKeySerializer(stringSerializer); 12 setHashValueSerializer(stringSerializer); 13 } 1415/**16 * Constructs a new <code>StringRedisTemplate</code> instance ready to be used. 17 * 18 * @param connectionFactory connection factory for creating new connections 19*/20public StringRedisTemplate(RedisConnectionFactory connectionFactory) { 21this(); 22 setConnectionFactory(connectionFactory); 23 afterPropertiesSet(); 24 } 2526protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) { 27returnnew DefaultStringRedisConnection(connection); 28 } 29 }
RedisTemplate实现,截取默认序列化器相关源码:
![技术分享图片](/img/jia.gif)
![技术分享图片](/img/jian.gif)
1 @Override 2 public void afterPropertiesSet() { 3 4 super .afterPropertiesSet(); 5 6 boolean defaultUsed = false; 7 8if (defaultSerializer == null) { 9//默认序列化器使用JdkSerializationRedisSerializer10 defaultSerializer = new JdkSerializationRedisSerializer( 11 classLoader != null ? classLoader : this.getClass().getClassLoader()); 12 } 1314if (enableDefaultSerializer) { 1516if (keySerializer == null) { 17 keySerializer = defaultSerializer; 18 defaultUsed = true; 19 } 20if (valueSerializer == null) { 21 valueSerializer = defaultSerializer; 22 defaultUsed = true; 23 } 24if (hashKeySerializer == null) { 25 hashKeySerializer = defaultSerializer; 26 defaultUsed = true; 27 } 28if (hashValueSerializer == null) { 29 hashValueSerializer = defaultSerializer; 30 defaultUsed = true; 31 } 32 } 3334if (enableDefaultSerializer && defaultUsed) { 35 Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized"); 36 } 3738if (scriptExecutor == null) { 39this.scriptExecutor = new DefaultScriptExecutor<>(this); 40 } 4142 initialized = true; 43 }
既然RedisTemplate的默认序列化器不是很方便在redis管理工具中查看,我们可以自己定义一个RedisTemplate实例,修改默认的序列化器。
实现方式如下,定义一个配置类,重新注入一个RedisTemplate操作bean:
1 @Configuration 2 public class MyRedisConfig { 3 4 @Bean(name = "redisTemplate") 5public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){ 6 7 RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); 8//参照StringRedisTemplate内部实现指定序列化器 9 redisTemplate.setConnectionFactory(redisConnectionFactory); 10 redisTemplate.setKeySerializer(keySerializer()); 11 redisTemplate.setHashKeySerializer(keySerializer()); 12 redisTemplate.setValueSerializer(valueSerializer()); 13 redisTemplate.setHashValueSerializer(valueSerializer()); 1416return redisTemplate; 17 } 1819private RedisSerializer<String> keySerializer() { 20returnnew StringRedisSerializer(); 21 } 22//使用Jackson序列化器23private RedisSerializer<Object> valueSerializer() { 24returnnew GenericJackson2JsonRedisSerializer(); 25 } 26 }
重新运行上面的测试代码,可以发现redis客户端中已经可以正常的显示json格式数据了。
SpringBoot集成redis + spring cache
Spring Cache集成redis的运行原理:
Spring缓存抽象模块通过CacheManager来创建、管理实际缓存组件,当SpringBoot应用程序引入spring-boot-starter-data-redi依赖后吗,容器中将注册的是CacheManager实例RedisCacheManager对象,RedisCacheManager来负责创建RedisCache作为缓存管理组件,由RedisCache操作redis服务器实现缓存数据操作。实际测试发现默认注入的RedisCacheManager操作缓存用的是RedisTemplate<Object, Object>,因此我们需要自定义cacheManager,替换掉默认的序列化器。
实现代码:
添加mybatis和redis依赖:
< dependency > < groupId >org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
添加mapper映射:
1 @Mapper 2 public interface ProductMapper { 3 @Select("select * from tb_product where product_id=#{id}") 4 Product getProductById(Long id); 5 6 @Update("update tb_product set product_name=#{productName},product_desc=#{productDesc} WHERE product_id=#{productId}") 7int updateProduct(Product product); 8 9 @Delete("delete from tb_product where product_id=#{id}") 10void deleteProductById(Long id); 1112 @Select("select * from tb_product where product_name=#{productName}") 13 Product getProductByName(String productName); 14 }
Service:
1 package com.sl.cache.service; 2 import com.sl.cache.entity.Product; 3 import com.sl.cache.mapper.ProductMapper; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.cache.annotation.CacheConfig; 6 import org.springframework.cache.annotation.CacheEvict; 7 import org.springframework.cache.annotation.CachePut; 8 import org.springframework.cache.annotation.Cacheable; 9 import org.springframework.cache.annotation.Caching; 10 import org.springframework.stereotype.Service; 11 12 @Service 13 @CacheConfig(cacheNames = "product") 14publicclass ProductService { 15 @Autowired 16private ProductMapper productMapper; 1718 @Cacheable(cacheNames = "product1",key = "#root.methodName+‘[‘+#id+‘]‘") 19//@Cacheable(cacheNames = {"product1","product2"})// 默认key为参数,多个参数SimpleKey [arg1,arg2] 20//@Cacheable(cacheNames = "product",key = "#root.methodName+‘[‘+#id+‘]‘") 21//@Cacheable(cacheNames = "product",keyGenerator = "myKeyGenerator") 22//@Cacheable(cacheNames = "product",key = "#root.methodName+‘[‘+#id+‘]‘",condition="#a0>10",unless = "#a0==11") //或者condition="#id>10")23public Product getProductById(Long id){ 24 Product product =productMapper.getProductById(id); 25 System.out.println(product); 26return product; 27 } 2829 @CachePut(value="product",key = "#result.productId",condition = "#result!=null") 30public Product updateProduct(Product product){ 31int count = productMapper.updateProduct(product); 32 System.out.println("影响行数:"+count); 33if(count>0){ 34return product; 35 }else{ 36returnnull; 37 } 38 } 3940//@CacheEvict(value="product",key="#id") 41//@CacheEvict(value="product",allEntries = true) //清楚所有缓存42 @CacheEvict(value="product",allEntries = true,beforeInvocation = true) //清楚所有缓存43publicboolean deleteProductById(Long id) { 44 productMapper.deleteProductById(id); 45returntrue; 46 } 4748//含有CachePut注解,所以执行这个方法时一定会查询数据库,及时有cacheable注解49 @Caching( 50 cacheable = {@Cacheable(value="product",key="#productName")}, 51 put = { 52 @CachePut(value="product",key="#result.productId"), 53 @CachePut(value="product",key="#result.productName") 54 } 55 ) 56public Product getProductByName(String productName){ 5758 Product product =productMapper.getProductByName(productName); 5960return product; 61 } 62 }
Controller:
package com.sl.cache.controller; import com.sl.cache.entity.Product; import com.sl.cache.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class ProductController { @Autowired private ProductService productService; @GetMapping("/product/{id}") public Product getProduct(@PathVariable("id") Long id) { Product product = productService.getProductById(id); return product; } //prooduct?productid=1&productName= & @GetMapping("/product") public Product updateProduct(Product product) { productService.updateProduct(product); return product; } @GetMapping("/delproduct") public String delProduct(@RequestParam(value="id") Long id) { productService.deleteProductById(id); return "ok"; } @GetMapping("/product/name/{productName}") public Product getEmpByLastName(@PathVariable("productName") String productName){ return productService.getProductByName(productName); } }
自定义cacheManager实现:
1 package com.sl.cache.config; 2 import com.sl.cache.entity.Product; 3 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 4 import org.springframework.cache.CacheManager; 5 import org.springframework.cache.config.CacheManagementConfigUtils; 6 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Configuration; 8 import org.springframework.context.annotation.Primary; 9 import org.springframework.data.redis.cache.RedisCacheConfiguration; 10 import org.springframework.data.redis.cache.RedisCacheManager; 11 import org.springframework.data.redis.cache.RedisCacheWriter; 12 import org.springframework.data.redis.connection.RedisConnectionFactory; 13 import org.springframework.data.redis.core.RedisTemplate; 14 import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; 15 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 16 import org.springframework.data.redis.serializer.RedisSerializationContext; 17 import org.springframework.data.redis.serializer.RedisSerializer; 18 import org.springframework.data.redis.serializer.StringRedisSerializer; 19 20 import java.net.UnknownHostException; 21 import java.time.Duration; 22 23 @Configuration 24 public class MyRedisConfig { 25 26 @Bean(name = "redisTemplate") 27public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){ 2829 RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>(); 3031 redisTemplate.setConnectionFactory(redisConnectionFactory); 32 redisTemplate.setKeySerializer(keySerializer()); 33 redisTemplate.setHashKeySerializer(keySerializer()); 34 redisTemplate.setValueSerializer(valueSerializer()); 35 redisTemplate.setHashValueSerializer(valueSerializer()); 36return redisTemplate; 37 } 3839 @Primary 40 @Bean 41public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){ 42//缓存配置对象43 RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig(); 4445 redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30L)) //设置缓存的默认超时时间:30分钟46 .disableCachingNullValues() //如果是空值,不缓存47 .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer())) //设置key序列化器48 .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer((valueSerializer()))); //设置value序列化器4950return RedisCacheManager 51 .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) 52 .cacheDefaults(redisCacheConfiguration).build(); 53 } 54private RedisSerializer<String> keySerializer() { 55returnnew StringRedisSerializer(); 56 } 5758private RedisSerializer<Object> valueSerializer() { 59returnnew GenericJackson2JsonRedisSerializer(); 60 } 61 }
启用缓存,添加mybatis Mapper映射扫描:
1 @MapperScan("com.sl.cache.mapper") 2@SpringBootApplication 3@EnableCaching 4publicclass SpringbootCacheApplication { 5 6publicstaticvoid main(String[] args) { 7 SpringApplication.run(SpringbootCacheApplication.class, args); 8 9 } 10 }
原文:https://www.cnblogs.com/ashleyboy/p/9595584.html
内容总结
以上是互联网集市为您收集整理的Spring Boot(八)集成Spring Cache 和 Redis全部内容,希望文章能够帮你解决Spring Boot(八)集成Spring Cache 和 Redis所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。