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"/>