随着NoSQL解决方案在许多问题上越来越受欢迎,现代项目越来越多地考虑使用一些(或几种)NoSQL代替(或并排)传统RDBMS。
我已经在本 , 本和本文章中介绍了我在MongoDB上的经验。
在本文中,我想对Redis (高级键值存储)进行一些调整。
除了非常丰富的键值语义外, Redis还支持发布订阅消息和事务。
在本文中,我将仅介绍一下表面,并演示将Redis集成到Spring应用程序中有多么简单。
与往常一样,我们将从我们项目的Maven POM文件开始:
<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>
<groupid>com.example.spring</groupid>
<artifactid>redis</artifactid>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceencoding>UTF-8</project.build.sourceencoding>
<spring.version>3.1.0.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupid>org.springframework.data</groupid>
<artifactid>spring-data-redis</artifactid>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupid>cglib</groupid>
<artifactid>cglib-nodep</artifactid>
<version>2.2</version>
</dependency>
<dependency>
<groupid>log4j</groupid>
<artifactid>log4j</artifactid>
<version>1.2.16</version>
</dependency>
<dependency>
<groupid>redis.clients</groupid>
<artifactid>jedis</artifactid>
<version>2.0.0</version>
<type>jar</type>
</dependency>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-core</artifactid>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-context</artifactid>
<version>${spring.version}</version>
</dependency>
</dependencies>
</project>
Spring Data Redis是Spring Data框架下的另一个项目,可将Redis无缝注入到您的应用程序中。
有多个Java的Redis客户端,我选择Jedis是因为它稳定并且在撰写本文时由Redis团队推荐。
我们将从简单的配置开始,并首先介绍必要的组件。
然后,随着我们的前进,将对配置进行一些扩展以展示pub-sub功能。
得益于Java config的支持,我们将创建配置类,并对所有依赖项进行强类型化,不再使用XML:
package com.example.redis.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericToStringSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class AppConfig {
@Bean
JedisConnectionFactory jedisConnectionFactory() {
return new JedisConnectionFactory();
}
@Bean
RedisTemplate< String, Object > redisTemplate() {
final RedisTemplate< String, Object > template = new RedisTemplate< String, Object >();
template.setConnectionFactory( jedisConnectionFactory() );
template.setKeySerializer( new StringRedisSerializer() );
template.setHashValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
template.setValueSerializer( new GenericToStringSerializer< Object >( Object.class ) );
return template;
}
}
基本上,这是我们需要的所有假设,前提是我们拥有单个Redis服务器并以默认配置在localhost上运行。
让我们考虑几种常见的用例:将键设置为某个值,存储对象以及最终实现pub-sub。
存储和检索键/值对非常简单:
@Autowired private RedisTemplate< String, Object > template;
public Object getValue( final String key ) {
return template.opsForValue().get( key );
}
public void setValue( final String key, final String value ) {
template.opsForValue().set( key, value );
}
(可选)可以将密钥设置为过期( Redis的另一个有用功能),即让我们的密钥在1秒钟后过期:
public void setValue( final String key, final String value ) {
template.opsForValue().set( key, value );
template.expire( key, 1, TimeUnit.SECONDS );
}
可以将任意对象作为哈希(映射)保存到Redis中 ,以便保存某些类User的实例
public class User {
private final Long id;
private String name;
private String email;
// Setters and getters are omitted for simplicity
}
使用密钥模式“ user:<id>”进入Redis :
public void setUser( final User user ) {
final String key = String.format( "user:%s", user.getId() );
final Map< String, Object > properties = new HashMap< String, Object >();
properties.put( "id", user.getId() );
properties.put( "name", user.getName() );
properties.put( "email", user.getEmail() );
template.opsForHash().putAll( key, properties);
}
分别使用id可以轻松地检查和检索对象。
public User getUser( final Long id ) {
final String key = String.format( "user:%s", id );
final String name = ( String )template.opsForHash().get( key, "name" );
final String email = ( String )template.opsForHash().get( key, "email" );
return new User( id, name, email );
}
使用Redis可以完成很多工作,我强烈建议您看一下。
它当然不是灵丹妙药,但可以非常轻松地解决许多具有挑战性的问题。
最后,让我展示如何在Redis中使用发布订阅消息。
让我们在这里添加更多配置(作为AppConfig类的一部分):
@Bean
MessageListenerAdapter messageListener() {
return new MessageListenerAdapter( new RedisMessageListener() );
}
@Bean
RedisMessageListenerContainer redisContainer() {
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory( jedisConnectionFactory() );
container.addMessageListener( messageListener(), new ChannelTopic( "my-queue" ) );
return container;
}
消息侦听器定义的样式对于Spring用户应该非常熟悉:通常,与我们定义JMS消息侦听器所采用的方法相同。
缺少的部分是我们的RedisMessageListener类定义:
package com.example.redis.impl;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
public class RedisMessageListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] paramArrayOfByte) {
System.out.println( "Received by RedisMessageListener: " + message.toString() );
}
}
现在,当我们有了消息监听器时,让我们看看如何使用Redis将一些消息推送到队列中。
和往常一样,这很简单:
@Autowired private RedisTemplate< String, Object > template;
public void publish( final String message ) {
template.execute(
new RedisCallback< Long >() {
@SuppressWarnings( "unchecked" )
@Override
public Long doInRedis( RedisConnection connection ) throws DataAccessException {
return connection.publish(
( ( RedisSerializer< String > )template.getKeySerializer() ).serialize( "queue" ),
( ( RedisSerializer< Object > )template.getValueSerializer() ).serialize( message ) );
}
}
);
}
基本上可以快速入门,但是绝对足以爱上Redis 。
参考: Andriy Redko {devmind}博客上的JCG合作伙伴 Andrey Redko 结合使用Spring和Redis 。
翻译自: https://www.javacodegeeks.com/2012/06/using-redis-with-spring.html