随着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 {@BeanJedisConnectionFactory jedisConnectionFactory() {return new JedisConnectionFactory();}@BeanRedisTemplate< 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 {@Overridepublic 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" )@Overridepublic 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