xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>
由于大部分Redis鍵值對存儲都是鍵值均為字符串,因此sdr做了兩個擴展,即StringRedisConnection以及StringRedisTemplate,兩個擴展均采用StringRedisSerializer。
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>
@Autowired
private StringRedisTemplate redisTemplate;
public void addLink(String userId, URL url) {
redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
RedisTemplate以及其子類都允許開發者通過RedisCallback直接跟Redis通信,在callback中,開發者獲得RedisConnection。StringRedisTemplate在callback中可以獲得StringRedisConnection,需要強制轉換。
利用Redis實現Jms的發布和訂閱的功能:
發布信息:可以通過RedisConnection或者RedisTemplate來實現。
redisConnection.publish(byte[] msg,byte[] channel);
template.convertAndSend("hello!","world");
接收消息:在接受放,可以訂閱根據頻道名來訂閱一個或多個頻道或者通過模式匹配。模式匹配非常有用,因為它不僅允許一個命令創建多個訂閱,也能監聽在訂閱創建之后產生的新的頻道(只要匹配指定的模式)。
在低層面上,RedisConnection提供subscribe和pSubscribe(根據模式匹配)方法,多個頻道和模式可以一起作為參數,RedisConnection也提供了getSubscription和isSubscribed方法。當用jedis連接器時,訂閱命令是同步的,因此會產生堵塞,會導致該線程一直等待消息,只有當訂閱取消的時候,才釋放線程,采用unsubcribe或pUnsubscribe來取消同線程的訂閱。為了處理訂閱消息,需要實現MessageListener callback,每次當新的消息達到時,會調用callback執行onMessage方法,該方法能夠獲得消息,頻道,以及匹配的模式。
由于MessageListener的天然堵塞,底層面的消息接收不太被人接受,而且它要求處理連接和線程的管理,為了規避這個問題,sdr提供RedisMessageListenerContainer,它被用來接受從Redis頻道傳來的消息并注入MessageListener,RedisMessageListenerContainer負責相應接受消息的線程并派發到處理的監聽器中。
<?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:redis="http://www.springframework.org/schema/redis"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd">
<!-- the default ConnectionFactory -->
<redis:listener-container>
<!-- the method attribute can be skipped as the default method name is "handleMessage" -->
<redis:listener ref="listener" method="handleMessage" topic="chatroom" />
</redis:listener-container>
<bean id="listener" class="redisexample.DefaultMessageDelegate"/>
...
<beans>
redis對事務提供支持,包括multi,exec,discard命令,這些命令也能用于RedisTemplate,然后redisTemplate不保證用相同的連接在同一個事務執行所有操作。sdr提供SessionCallback接口用于同線程的多操作執行。
Redis支持管道(pipelining),管道可以發送多個命令到服務端無需等待反饋然后讀取單一步的反饋。管道在你需要一行發送多個命令是提升性能,比如對相同的列表增加多個元素。如果不關注管道操作的結果,則可以調用RedisTemplate標準的excute方法,傳遞true作為pipeline參數。excutePipelined方法執行RedisCallback或者sessionCallback,然后返回結果。
List<Object> results = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
for(int i=0; i< batchSize; i++) {
stringRedisConn.rPop("myqueue");
}
return null;//必須返回null
}
});//results為myqueue的value。
Redis2.6以及更高的版本支持通過eval和evalsha命令執行lua script。sdr封裝代碼執行,串行化以及利用代碼緩存。scripts能夠通過RedisTemplate的execute方法來運行,RedisTemplate用一個可配置的ScriptExecutor來執行提供的代碼。缺省的ScriptExecutor通過獲取代碼的sha1,嘗試運行evalsha,失敗后執行eval。
lua script一般用于原子操作且命令的行為被另外的命令結果所影響。
配置:
<bean id="script" class="org.springframework.data.redis.core.script.DefaultRedisScript">
<property name="location" value="classpath:META-INF/scripts/checkandset.lua"/>
<property name="resultType" value="java.lang.Boolean"/>
</bean>
java代碼:
@Autowired
RedisScript<Boolean> script;
public boolean checkAndSet(String expectedValue, String newValue) {
return redisTemplate.execute(script, Collections.singletonList("key"),
expectedValue, newValue);
}
lua script:
-- checkandset.lua
local current = redis.call('GET', KEYS[1])
if current == ARGV[1]
then
redis.call('SET', KEYS[1], ARGV[2])
return true
end
return false
redis支持類存放在org.springframework.data.redis.support,RedisSet和RedisZSet提供Redis支持的intersection以及union等方法。RedisList可以實現Queue以及Deque來實現FIFO和LiFO。
配置:
<bean id="queue" class="org.springframework.data.redis.support.collections.DefaultRedisList">
<constructor-arg ref="redisTemplate"/>
<constructor-arg value="queue-key"/>
</bean>
代碼:
// injected
private Deque<String> queue;
public void addTag(String tag) {
queue.push(tag);
}
Sdr提供了一個spring3.1 cache abstraction的實現。配置:
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:template-ref="redisTemplate"/>