redis是一款非常流行的Nosql,提供的功能非常強大,本節不再贅述。
本文簡單介紹Spring Data框架提供的spring_data_redis模塊,所提供的強大功能。雖然,spring_data_redis不具體負責與redis通信,但提供了豐富的外圍功能。
主要包含以下內容
搭建測試環境
序列工具
認識RedisConnectionFactory&RedisTemplate
1.搭建測試環境
1.1 pom.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> <!-- Your own application should inherit from spring-boot-starter-parent --> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.5.RELEASE</version> </parent> <groupId>com.hellodb.springdata</groupId> <artifactId>redisdemo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> </dependency> <!-- 客戶端 --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> </dependency> <dependency> <groupId>biz.paluch.redis</groupId> <artifactId>lettuce</artifactId> <version>3.2.Final</version> </dependency> <!--序列化工具 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
1.2配置XML
jedis-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Jedis ConnectionFactory --> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:port="6379" p:hostName="192.168.163.146"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="jedisConnectionFactory"></property> </bean> </beans>
lettuce-context.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Jedis ConnectionFactory --> <bean id="lettuceConnectionFactory" class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory" p:port="6379" p:hostName="192.168.163.146"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="lettuceConnectionFactory"></property> </bean> </beans>
實際環境中,只需要選擇一個客戶端即可。當然,各個客戶端的使用場景有所區別,這兒就不深入討論了。
JedisRedisTemplateTest.java :使用jedis客戶端
@RunWith(SpringJUnit4Cla***unner.class) @ContextConfiguration("classpath:jedis-context.xml") public class JedisRedisTemplateTest { @Resource RedisTemplate redisTemplate; @Test public void testOpsForValue() { String redisKey1 = "jedis_redis_key_1"; String originValue = "redis by jedis!"; Jackson2JsonRedisSerializer<String> serializer = new Jackson2JsonRedisSerializer(String.class); redisTemplate.setKeySerializer(serializer); redisTemplate.setValueSerializer(serializer); redisTemplate.opsForValue().set(redisKey1, originValue); redisStoredValue = redisTemplate.opsForValue().get(redisKey1); assertEquals(redisStoredValue, originValue); } }
LettuceRedisTemplateTest.java :使用lettuce客戶端
@RunWith(SpringJUnit4Cla***unner.class) @ContextConfiguration("classpath:lettuce-context.xml") public class LettuceRedisTemplateTest{ @Resource RedisTemplate redisTemplate; @Test public void testOpsForValue() { String redisKey1 = "lettuce_redis_key_1"; String originValue = "redis by lettuce!"; Jackson2JsonRedisSerializer<String> serializer = new Jackson2JsonRedisSerializer(String.class); redisTemplate.setKeySerializer(serializer); redisTemplate.setValueSerializer(serializer); redisTemplate.opsForValue().set(redisKey1, originValue); redisStoredValue = redisTemplate.opsForValue().get(redisKey1); assertEquals(redisStoredValue, originValue); } }
對比兩個測試用例, 測試用例方法,基本一致,很清晰的感受到spring data redis框架帶來的擴展性。修改底層redis客戶端實現技術,而不會影響到上層現有方法(如redisTemplate方法)
運行2個用例結果
127.0.0.1:6379> keys * 1) "\"lettuce_redis_key_1\"" 2) "\"jedis_redis_key_1\"" 127.0.0.1:6379> get "\"lettuce_redis_key_1\"" "\"redis by lettuce!\"" 127.0.0.1:6379> get "\"jedis_redis_key_1\"" "\"redis by jedis!\""
現在環境搭建完畢。
2.序列工具
從框架的角度來看,Redis中存儲的數據只是字節數。雖然Redis本身支持各種類型,但大多數情況下,這些指的是數據存儲的方式,而不是它所代表的格式。由用戶決定信息是否轉換爲字符串或任何其他對象。用戶(自定義)類型和原始數據(反之亦然)之間的轉換通過RedisSerializer接口(包org.springframework.data.redis.serializer)在Spring Data Redis中處理,顧名思義,它負責處理序列化過程。Spring data redis提供了多個序列化工具。
2.1 RedisSerializer API
//對象到字節數組(二進制數據)的基本接口序列化和反序列化 public interface RedisSerializer<T> { /** *將給定對象序列化爲二進制數據 */ byte[] serialize(T t) throws SerializationException; /** * 從給定的二進制數據反序列化對象。 */ T deserialize(byte[] bytes) throws SerializationException; }
2.2 內置序列化實現
org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
org.springframework.data.redis.serializer.GenericToStringSerializer
org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
org.springframework.data.redis.serializer.JacksonJsonRedisSerializer
org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
org.springframework.data.redis.serializer.OxmSerializer
org.springframework.data.redis.serializer.StringRedisSerializer
2.3 RedisSerializer使用場景
在RedisTemplate,RedisMessageListenerContainer,DefaultStringRedisConnection使用。
比如RedisTemplate。
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V> { ... / ** * @return是否應使用默認的序列化程序。 如果沒有,任何序列化不明確集將會 *保持爲空,值將不會被序列化或反序列化。 * / public boolean isEnableDefaultSerializer(){ return enableDefaultSerializer; } / ** * @param enableDefaultSerializer是否應使用默認的序列化程序。 如果沒有,任何serializer不 *展示集將保持爲空,值將不會被序列化或反序列化。 * / public void setEnableDefaultSerializer(boolean enableDefaultSerializer){ this.enableDefaultSerializer = enableDefaultSerializer; } / ** *返回此模板使用的默認序列化程序。 *: * @return模板默認序列化 * / public RedisSerializer <?> getDefaultSerializer(){ return defaultSerializer; } / ** *設置要用於此模板的默認序列化程序。 所有序列化(期望 * @link #setStringSerializer(RedisSerializer))初始化爲此值,除非顯式設置。 默認爲 * @link JdkSerializationRedisSerializer。 *: * @param serializer默認序列化程序使用 * / public void setDefaultSerializer(RedisSerializer <?> serializer){ this.defaultSerializer = serializer; } / ** *設置此模板使用的密鑰序列化程序。 默認爲@link #getDefaultSerializer()。 *: * @param serializer此模板使用的密鑰序列化程序。 * / public void setKeySerializer(RedisSerializer <?> serializer){ this.keySerializer = serializer; } / ** *返回此模板使用的密鑰序列化程序。 *: * @返回此模板使用的密鑰序列化程序。 * / public RedisSerializer <?> getKeySerializer(){ return keySerializer; } / ** *設置此模板使用的值序列化程序。 默認爲@link #getDefaultSerializer()。 *: * @param serializer此模板使用的值序列化程序。 * / public void setValueSerializer(RedisSerializer <?> serializer){ this.valueSerializer = serializer; } / ** *返回此模板使用的值序列化程序。 *: * @返回此模板使用的值序列化程序。 * / public RedisSerializer <?> getValueSerializer(){ return valueSerializer; } ... }
2.4 測試
上面的JedisRedisTemplateTest 使用的序列化工具Jackson2JsonRedisSerializer。
127.0.0.1:6379> keys * 1) "\"jedis_redis_key_1\"" 127.0.0.1:6379> get "\"jedis_redis_key_1\"" "\"redis by jedis!\""
改用StringRedisSerializer,操作redis後效果
127.0.0.1:6379> flushdb OK 127.0.0.1:6379> keys * 1) "jedis_redis_key_1" 127.0.0.1:6379> get jedis_redis_key_1 "redis by jedis!"
3.認識RedisConnectionFactory&RedisTemplate
通過這個結構,可以實現客戶端工具的無縫切換。
RedisConnection | 與Redis服務器的連接。 作爲各種Redis客戶端庫(或驅動程序)的通用抽象。 | |
RedisConnectionFactory | 線程安全的Redis連接工廠。 | |
RedisTemplate | 幫助類,簡化了Redis數據訪問模板代碼。 | |
RedisTemplate模板提供了操作視圖(根據Redis命令引用進行分組),它提供豐富的,一般化的接口,用於對某種類型或某個鍵(通過KeyBound接口)進行處理,如下所述
操作視圖:Operational views
Interface | Description |
Key Type Operations | |
ValueOperations | Redis string (or value) operations |
ListOperations | Redis list operations |
SetOperations | Redis set operations |
ZSetOperations | Redis zset (or sorted set) operations |
HashOperations | Redis hash operations |
HyperLogLogOperations | Redis HyperLogLog operations like (pfadd, pfcount,…) |
Key Bound Operations | |
BoundValueOperations | Redis string (or value) key bound operations |
BoundListOperations | Redis list key bound operations |
BoundSetOperations | Redis set key bound operations |
BoundZSetOperations | Redis zset (or sorted set) key bound operations |
BoundHashOperations | Redis hash key bound operations |