<!-- # 【SpringBoot】多 Redis 接入 --> <!-- spring-boot-multi-redis --> *spring-boot-starter-data-redis* 默认仅支持配置一个 *redis* 服务(*spring.redis.xxx*)。若要配置多个,则需要手动添加相关的配置代码。 [spring-boot-with-multi-redis][1] 就是一个多 *redis* 的 *spring-boot* 示例,不过是基于 *1.4.0.RELEASE* 版的,部分配置方法在新版本中已经没有了。 下面是基于 *2.2.13.RELEASE* 版的 `CacheManager` 配置示例代码,另外由于不再使用 *RedisTemplate* 的注入,如果没有其它地方使用,相关的配置代码也可以删除。 ```java @Configuration @EnableCaching public class MyRedisCacheConfiguration extends CachingConfigurerSupport { @Primary @Bean(name = "userCacheManager") public CacheManager userCacheManager(@Qualifier("userRedisConnectionFactory") RedisConnectionFactory cf) { RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(cf); RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext .SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext .SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) .entryTtl(Duration.ofMinutes(30)); return new RedisCacheManager(redisCacheWriter, cacheConfiguration); } @Bean(name = "roleCacheManager") public CacheManager roleCacheManager(@Qualifier("roleRedisConnectionFactory") RedisConnectionFactory cf) { RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(cf); RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext .SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext .SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) .entryTtl(Duration.ofMinutes(30)); return new RedisCacheManager(redisCacheWriter, cacheConfiguration); } } ``` ## 附1. 示例代码 ### *pom.xml* 这里稍有不同的是需要单独添加 *jedis* 依赖,否则会报 *找不到 `redis.clients.jedis.JedisPoolConfig` 的类文件* 的异常。 ```xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.13.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>me.liujiajia</groupId> <artifactId>multi-redis-sample</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- Spring --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web-services</artifactId> </dependency> <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- Jedis --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project> ``` ### *application.yml* ```yaml server: port: 10101 spring: application: name: Multi-Redis-Application redis: user: host: 127.0.0.1 port: ${redis.port:6379} database: 10 password: 123456 role: host: 127.0.0.1 port: ${redis.port:6379} database: 12 password: 123456 ``` ### *MultiRedisApplication.java* ```java package me.liujiajia.sample.redis.multi; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MultiRedisApplication { public static void main(String[] args) { SpringApplication.run(MultiRedisApplication.class, args); } } ``` ### *RedisProperty.java* 这里使用 *lombok* 的 `@Data` 注解来简化代码。 ```java package me.liujiajia.sample.redis.multi.property; import lombok.Data; @Data public class RedisProperty { private String host; private int port; private int database; private String password; } ``` ### *RoleRedisProperty.java* ```java package me.liujiajia.sample.redis.multi.property; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "spring.redis.role") public class RoleRedisProperty extends RedisProperty { } ``` ### *UserRedisProperty.java* ```java package me.liujiajia.sample.redis.multi.property; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Configuration @ConfigurationProperties(prefix = "spring.redis.user") public class UserRedisProperty extends RedisProperty { } ``` ### *MyRedisConnectionConfiguration.java* ```java package me.liujiajia.sample.redis.multi.config; import lombok.RequiredArgsConstructor; import me.liujiajia.sample.redis.multi.property.RoleRedisProperty; import me.liujiajia.sample.redis.multi.property.UserRedisProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; @Configuration @RequiredArgsConstructor public class MyRedisConnectionConfiguration { private final UserRedisProperty userRedisProperty; private final RoleRedisProperty roleRedisProperty; @Primary @Bean(name = "userRedisConnectionFactory") public RedisConnectionFactory userRedisConnectionFactory() { RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(); redisConfiguration.setHostName(userRedisProperty.getHost()); redisConfiguration.setPort(userRedisProperty.getPort()); redisConfiguration.setDatabase(userRedisProperty.getDatabase()); redisConfiguration.setPassword(userRedisProperty.getPassword()); return new JedisConnectionFactory(redisConfiguration); } @Bean(name = "roleRedisConnectionFactory") public RedisConnectionFactory roleRedisConnectionFactory() { RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(); redisConfiguration.setHostName(roleRedisProperty.getHost()); redisConfiguration.setPort(roleRedisProperty.getPort()); redisConfiguration.setDatabase(roleRedisProperty.getDatabase()); redisConfiguration.setPassword(roleRedisProperty.getPassword()); return new JedisConnectionFactory(redisConfiguration); } } ``` ### *MyRedisCacheConfiguration.java* ```java package me.liujiajia.sample.redis.multi.config; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import org.springframework.data.redis.serializer.StringRedisSerializer; import java.time.Duration; @Configuration @EnableCaching public class MyRedisCacheConfiguration extends CachingConfigurerSupport { @Primary @Bean(name = "userCacheManager") public CacheManager userCacheManager(@Qualifier("userRedisConnectionFactory") RedisConnectionFactory cf) { RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(cf); RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext .SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext .SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) .entryTtl(Duration.ofMinutes(30)); return new RedisCacheManager(redisCacheWriter, cacheConfiguration); } @Bean(name = "roleCacheManager") public CacheManager roleCacheManager(@Qualifier("roleRedisConnectionFactory") RedisConnectionFactory cf) { RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(cf); RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() .serializeKeysWith(RedisSerializationContext .SerializationPair.fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext .SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())) .entryTtl(Duration.ofMinutes(30)); return new RedisCacheManager(redisCacheWriter, cacheConfiguration); } } ``` ### *MyRedisTemplateConfiguration.java* 提取了 *RedisTemplate* 的配置到单独的类,需要时可以选用。 ```java package me.liujiajia.sample.redis.multi.config; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration @RequiredArgsConstructor public class MyRedisTemplateConfiguration { @Primary @Bean(name = "userStringRedisTemplate") public StringRedisTemplate userStringRedisTemplate(@Qualifier("userRedisConnectionFactory") RedisConnectionFactory cf) { return new StringRedisTemplate(cf); } @Primary @Bean(name = "userRedisTemplate") public RedisTemplate userRedisTemplate(@Qualifier("userRedisConnectionFactory") RedisConnectionFactory cf) { StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(cf); setSerializer(stringRedisTemplate); return stringRedisTemplate; } @Bean(name = "roleStringRedisTemplate") public StringRedisTemplate roleStringRedisTemplate(@Qualifier("roleRedisConnectionFactory") RedisConnectionFactory cf) { return new StringRedisTemplate(cf); } @Bean(name = "roleRedisTemplate") public RedisTemplate roleRedisTemplate(@Qualifier("roleRedisConnectionFactory") RedisConnectionFactory cf) { StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(cf); setSerializer(stringRedisTemplate); return stringRedisTemplate; } private void setSerializer(RedisTemplate<String, String> template) { template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer()); template.setKeySerializer(new StringRedisSerializer()); template.setHashKeySerializer(new GenericJackson2JsonRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); } } ``` ### *UserService.java* ```java package me.liujiajia.sample.redis.multi.service; public interface UserService { int getUser(int id); int getRole(int id); } ``` ### *UserServiceImpl.java* 使用 `@Cacheable` 注解来缓存方法的返回值,*cacheNames* 属性指定缓存键值的前缀,*cacheManager* 指定 *Bean* 的名称。调用有 `@Cacheable` 的方法时,会优先使用缓存中的结果。 另外还可以使用 `@CachePut` 注解更新缓存,使用 `@CacheEvict` 注解删除缓存。 ```java package me.liujiajia.sample.redis.multi.service.impl; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import me.liujiajia.sample.redis.multi.service.UserService; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @RequiredArgsConstructor @Service @Slf4j public class UserServiceImpl implements UserService { @Override @Cacheable(cacheNames = "user", cacheManager = "userCacheManager") public int getUser(int id) { log.info("return user id = {}", id); return id; } @Override @Cacheable(cacheNames = "role", cacheManager = "roleCacheManager") public int getRole(int id) { log.info("return role id = {}", id); return id; } } ``` ### *MultiRedisTests.java* 添加了几个简单的测试代码。 ```java package me.liujiajia.sample.redis.multi; import me.liujiajia.sample.redis.multi.service.UserService; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.StringRedisTemplate; import javax.annotation.Resource; @SpringBootTest public class MultiRedisTests { @Autowired private UserService userService; @Resource private StringRedisTemplate userStringRedisTemplate; @Resource private StringRedisTemplate roleStringRedisTemplate; @Test public void getUserCahce() { int userId = userService.getUser(1); Assertions.assertEquals(userId, 1); } @Test public void getRoleCahce() { int roleId = userService.getRole(1); Assertions.assertEquals(roleId, 1); } @Test public void getUserCahceByTemplate() { int userId = userService.getUser(10); String cachedUserId = userStringRedisTemplate.opsForValue().get("user::10"); Assertions.assertEquals(cachedUserId, String.valueOf(userId)); } @Test public void getRoleCahceByTemplate() { int roleId = userService.getRole(12); String cachedRoleId = roleStringRedisTemplate.opsForValue().get("role::12"); Assertions.assertEquals(cachedRoleId, String.valueOf(roleId)); } } ``` [1]:https://github.com/idreamshen/spring-boot-with-multi-redis (idreamshen / spring-boot-with-multi-redis) Loading... 版权声明:本文为博主「佳佳」的原创文章,遵循 CC 4.0 BY-NC-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://www.liujiajia.me/2021/5/25/spring-boot-multi-redis Commented by 算了,,没事 on 2021-05-31 回复 你这是工作多久了啊。 提交
算了,,没事
on 2021-05-31 回复