場景
在SpringBoot項目中需要連接兩個Redis實例,並實現從A中獲取數據並存取到B中。
另外A中redis的地址和密碼不能外漏,則將A的地址和密碼寫在jar包中,B中redis參數可以在外置
配置文件application.yml中進行動態配置。
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。
實現
1、新建SpringBoot項目並添加依賴
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>2.3.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
2、完整的pom文件代碼
<?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 https://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.3.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>2.3.6.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
3、在配置文件application.properties中配置B的redis的參數
server.port=9090 spring.redis.user.host=另一個redis的地址 spring.redis.user.port=6379 spring.redis.user.password=123456
4、新建Redis的配置類
package com.example.demo.config; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import org.springframework.beans.factory.annotation.Value; 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.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.StringRedisSerializer; import redis.clients.jedis.JedisPoolConfig; @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { //order @Value("127.0.0.1") private String orderHost; @Value("6379") private String orderPort; @Value("123456") private String orderPassword; //user @Value("${spring.redis.user.host}") private String userHost; @Value("${spring.redis.user.port}") private String userPort; @Value("${spring.redis.user.password}") private String userPassword; private static final int MAX_IDLE = 200; //最大空閑連接數 private static final int MAX_TOTAL = 1024; //最大連接數 private static final long MAX_WAIT_MILLIS = 10000; //建立連接最長等待時間 //配置工廠 public RedisConnectionFactory connectionFactory(String host, int port, String password,int index) { RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); redisStandaloneConfiguration.setHostName(host); redisStandaloneConfiguration.setPort(port); redisStandaloneConfiguration.setPassword(password); redisStandaloneConfiguration.setDatabase(index); return new JedisConnectionFactory(redisStandaloneConfiguration); } //連接池配置 public JedisPoolConfig poolConfig(int maxIdle, int maxTotal, long maxWaitMillis, boolean testOnBorrow) { JedisPoolConfig poolConfig = new JedisPoolConfig(); poolConfig.setMaxIdle(maxIdle); poolConfig.setMaxTotal(maxTotal); poolConfig.setMaxWaitMillis(maxWaitMillis); poolConfig.setTestOnBorrow(testOnBorrow); return poolConfig; } @Bean("redisTemplateOrder") public RedisTemplate<Object, Object> redisTemplateOrder(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory(orderHost, Integer.parseInt(orderPort),orderPassword,0)); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); serializer.setObjectMapper(mapper); template.setValueSerializer(serializer); // 使用StringRedisSerializer來序列化和反序列化redis的key值 template.setKeySerializer(new StringRedisSerializer()); template.afterPropertiesSet(); return template; } @Bean("redisTemplateUser") public RedisTemplate<Object, Object> redisTemplateUser(RedisConnectionFactory connectionFactory) { RedisTemplate<Object, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory(userHost, Integer.parseInt(userPort),userPassword,0)); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); serializer.setObjectMapper(mapper); template.setValueSerializer(serializer); // 使用StringRedisSerializer來序列化和反序列化redis的key值 template.setKeySerializer(new StringRedisSerializer()); template.afterPropertiesSet(); return template; } }
注意:
這里連接的是兩個Redis,其中A的Redis命名為order,其參數直接在注解中固定賦值。
B的Redis命名為user,參數從配置文件中獲取。
這其中又用到了FastJson進行序列化的工具類FastJson2JsonRedisSerializer
package com.example.demo.config; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.serializer.SerializerFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.type.TypeFactory; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import org.springframework.util.Assert; import java.nio.charset.Charset; public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> { @SuppressWarnings("unused") private ObjectMapper objectMapper = new ObjectMapper(); public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); private Class<T> clazz; static { ParserConfig.getGlobalInstance().setAutoTypeSupport(true); } public FastJson2JsonRedisSerializer(Class<T> clazz) { super(); this.clazz = clazz; } @Override public byte[] serialize(T t) throws SerializationException { if (t == null) { return new byte[0]; } return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); } @Override public T deserialize(byte[] bytes) throws SerializationException { if (bytes == null || bytes.length <= 0) { return null; } String str = new String(bytes, DEFAULT_CHARSET); return JSON.parseObject(str, clazz); } public void setObjectMapper(ObjectMapper objectMapper) { Assert.notNull(objectMapper, "'objectMapper' must not be null"); this.objectMapper = objectMapper; } protected JavaType getJavaType(Class<?> clazz) { return TypeFactory.defaultInstance().constructType(clazz); } }
5、分別新建兩個Redis進行讀取操作的service類
RedisServiceOrder:
package com.example.demo; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @Component public class RedisServiceOrder { @Resource(name = "redisTemplateOrder") public RedisTemplate redisTemplate; /** * 緩存基本的對象,Integer、String、實體類等 * * @param key 緩存的鍵值 * @param value 緩存的值 */ public <T> void setCacheObject(final String key, final T value) { redisTemplate.opsForValue().set(key, value); } /** * 緩存基本的對象,Integer、String、實體類等 * * @param key 緩存的鍵值 * @param value 緩存的值 * @param timeout 時間 * @param timeUnit 時間顆粒度 */ public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit) { redisTemplate.opsForValue().set(key, value, timeout, timeUnit); } /** * 設置有效時間 * * @param key Redis鍵 * @param timeout 超時時間 * @returntrue=設置成功;false=設置失敗 */ public boolean expire(final String key, final long timeout) { return expire(key, timeout, TimeUnit.SECONDS); } /** * 設置有效時間 * * @param key Redis鍵 * @param timeout 超時時間 * @param unit 時間單位 * @returntrue=設置成功;false=設置失敗 */ public boolean expire(final String key, final long timeout, final TimeUnit unit) { return redisTemplate.expire(key, timeout, unit); } /** * 獲得緩存的基本對象。 * * @param key 緩存鍵值 * @return 緩存鍵值對應的數據 */ public <T> T getCacheObject(final String key) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); return operation.get(key); } /** * 刪除單個對象 * * @param key */ public boolean deleteObject(final String key) { return redisTemplate.delete(key); } /** * 刪除集合對象 * * @param collection 多個對象 * @return */ public long deleteObject(final Collection collection) { return redisTemplate.delete(collection); } /** * 緩存List數據 * * @param key 緩存的鍵值 * @param dataList 待緩存的List數據 * @return 緩存的對象 */ public <T> long setCacheList(final String key, final List<T> dataList) { Long count = redisTemplate.opsForList().rightPushAll(key, dataList); return count == null ? 0 : count; } /** * 獲得緩存的list對象 * * @param key 緩存的鍵值 * @return 緩存鍵值對應的數據 */ public <T> List<T> getCacheList(final String key) { return redisTemplate.opsForList().range(key, 0, -1); } /** * 緩存Set * * @param key 緩存鍵值 * @param dataSet 緩存的數據 * @return 緩存數據的對象 */ public <T> long setCacheSet(final String key, final Set<T> dataSet) { Long count = redisTemplate.opsForSet().add(key, dataSet); return count == null ? 0 : count; } /** * 獲得緩存的set * * @param key * @return */ public <T> Set<T> getCacheSet(final String key) { return redisTemplate.opsForSet().members(key); } /** * 緩存Map * * @param key * @param dataMap */ public <T> void setCacheMap(final String key, final Map<String, T> dataMap) { if (dataMap != null) { redisTemplate.opsForHash().putAll(key, dataMap); } } /** * 獲得緩存的Map * * @param key * @return */ public <T> Map<String, T> getCacheMap(final String key) { return redisTemplate.opsForHash().entries(key); } /** * 往Hash中存入數據 * * @param key Redis鍵 * @param hKey Hash鍵 * @param value 值 */ public <T> void setCacheMapValue(final String key, final String hKey, final T value) { redisTemplate.opsForHash().put(key, hKey, value); } /** * 獲取Hash中的數據 * * @param key Redis鍵 * @param hKey Hash鍵 * @return Hash中的對象 */ public <T> T getCacheMapValue(final String key, final String hKey) { HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash(); return opsForHash.get(key, hKey); } /** * 獲取多個Hash中的數據 * * @param key Redis鍵 * @param hKeys Hash鍵集合 * @return Hash對象集合 */ public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) { return redisTemplate.opsForHash().multiGet(key, hKeys); } /** * 獲得緩存的基本對象列表 * * @param pattern 字符串前綴 * @return 對象列表 */ public Collection<String> keys(String pattern) { return redisTemplate.keys(pattern); } /** * 獲得緩存的集合(模糊查詢) * * @param keys * @return */ public <T> List<T> getCacheList(Set keys) { return redisTemplate.opsForValue().multiGet(keys); } }
RedisServiceUser:
package com.example.demo; import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; @Component public class RedisServiceUser { @Resource(name = "redisTemplateUser") public RedisTemplate redisTemplate; /* * 緩存基本的對象,Integer、String、實體類等 * * @param key 緩存的鍵值 * @param value 緩存的值 */ public <T> void setCacheObject(final String key, final T value) { redisTemplate.opsForValue().set(key, value); } /** * 緩存基本的對象,Integer、String、實體類等 * * @param key 緩存的鍵值 * @param value 緩存的值 * @param timeout 時間 * @param timeUnit 時間顆粒度 */ public <T> void setCacheObject(final String key, final T value, final Long timeout, final TimeUnit timeUnit) { redisTemplate.opsForValue().set(key, value, timeout, timeUnit); } /** * 設置有效時間 * * @param key Redis鍵 * @param timeout 超時時間 * @returntrue=設置成功;false=設置失敗 */ public boolean expire(final String key, final long timeout) { return expire(key, timeout, TimeUnit.SECONDS); } /** * 設置有效時間 * * @param key Redis鍵 * @param timeout 超時時間 * @param unit 時間單位 * @returntrue=設置成功;false=設置失敗 */ public boolean expire(final String key, final long timeout, final TimeUnit unit) { return redisTemplate.expire(key, timeout, unit); } /** * 獲得緩存的基本對象。 * * @param key 緩存鍵值 * @return 緩存鍵值對應的數據 */ public <T> T getCacheObject(final String key) { ValueOperations<String, T> operation = redisTemplate.opsForValue(); return operation.get(key); } /** * 刪除單個對象 * * @param key */ public boolean deleteObject(final String key) { return redisTemplate.delete(key); } /** * 刪除集合對象 * * @param collection 多個對象 * @return */ public long deleteObject(final Collection collection) { return redisTemplate.delete(collection); } /** * 緩存List數據 * * @param key 緩存的鍵值 * @param dataList 待緩存的List數據 * @return 緩存的對象 */ public <T> long setCacheList(final String key, final List<T> dataList) { Long count = redisTemplate.opsForList().rightPushAll(key, dataList); return count == null ? 0 : count; } /** * 獲得緩存的list對象 * * @param key 緩存的鍵值 * @return 緩存鍵值對應的數據 */ public <T> List<T> getCacheList(final String key) { return redisTemplate.opsForList().range(key, 0, -1); } /** * 緩存Set * * @param key 緩存鍵值 * @param dataSet 緩存的數據 * @return 緩存數據的對象 */ public <T> long setCacheSet(final String key, final Set<T> dataSet) { Long count = redisTemplate.opsForSet().add(key, dataSet); return count == null ? 0 : count; } /** * 獲得緩存的set * * @param key * @return */ public <T> Set<T> getCacheSet(final String key) { return redisTemplate.opsForSet().members(key); } /** * 緩存Map * * @param key * @param dataMap */ public <T> void setCacheMap(final String key, final Map<String, T> dataMap) { if (dataMap != null) { redisTemplate.opsForHash().putAll(key, dataMap); } } /** * 獲得緩存的Map * * @param key * @return */ public <T> Map<String, T> getCacheMap(final String key) { return redisTemplate.opsForHash().entries(key); } /** * 往Hash中存入數據 * * @param key Redis鍵 * @param hKey Hash鍵 * @param value 值 */ public <T> void setCacheMapValue(final String key, final String hKey, final T value) { redisTemplate.opsForHash().put(key, hKey, value); } /** * 獲取Hash中的數據 * * @param key Redis鍵 * @param hKey Hash鍵 * @return Hash中的對象 */ public <T> T getCacheMapValue(final String key, final String hKey) { HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash(); return opsForHash.get(key, hKey); } /** * 獲取多個Hash中的數據 * * @param key Redis鍵 * @param hKeys Hash鍵集合 * @return Hash對象集合 */ public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) { return redisTemplate.opsForHash().multiGet(key, hKeys); } /** * 獲得緩存的基本對象列表 * * @param pattern 字符串前綴 * @return 對象列表 */ public Collection<String> keys(String pattern) { return redisTemplate.keys(pattern); } /** * 獲得緩存的集合(模糊查詢) * * @param keys * @return */ public <T> List<T> getCacheList(Set keys) { return redisTemplate.opsForValue().multiGet(keys); } }
6、編寫測試Controller進行測試
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/badao") public class TestController { @Autowired private RedisServiceOrder redisServiceOrder; @Autowired private RedisServiceUser redisServiceUser; @GetMapping("/test") public String list() { redisServiceOrder.setCacheObject("badao","公眾號:霸道的程序猿"); String badao = redisServiceOrder.getCacheObject("badao"); redisServiceUser.setCacheObject("copyBadao",badao); return "公眾號:霸道的程序猿"; } }
7、啟動項目並調用測試接口