Spring data 使用使用Redis

本文介绍如何使用 Spring Data Redis 提供的 RedisTemplate 和 StringRedisTemplate 进行高效的数据访问。涵盖连接工厂配置、序列化器设置及针对不同数据结构的操作示例。

引用依赖

    compile("org.springframework.data:spring-data-redis:1.3.2.RELEASE")
    compile("com.fasterxml.jackson.core:jackson-databind:2.4.1.3")
    compile("redis.clients:jedis:2.5.2")
    testCompile("junit:junit-dep:4.11")

Spring Data的另外一个关键特性,也就是面向模板的数据访问,在使用Redis的时候,为我们提供帮助。

Spring Data Redis提供了四个连接工厂供我们选择。

JedisConnectionFactory
JredisConnectionFactory
LettuceConnectionFactory
SrpConnectionFactory

将连接工厂设置为Spring的Bean

@Configuration
public class RedisConfig {
    @Bean
    public RedisConnectionFactory redisCF() {
        JedisConnectionFactory c =new JedisConnectionFactory();
        c.setHostName("0.0.0.0");
        c.setPort(6379);
        return c;
    }
}
 使用RedisTemplate

如果不使用模板, 也可以直接存储数据

RedisConnection conn = cf.getConnection();
conn.set("key".getBytes(),"someValue".getBytes());

byte[] bytesValue = conn.get("key".getBytes());
System.out.println(new String(bytesValue));

Spring Data Redis以模板的形式提供了较高等级的数据访问方案。实际上,Spring Data Redis提供了两个模板:
RedisTemplate, StringRedisTemplate

RedisTemplate可以极大地简化Redis数据访问,能够让我们持久化各种类型的key和value,并不局限于字节数组。在认识到key和value通常是String类型之后,StringRedisTemplate扩展了RedisTemplate,只关注String类型。

使用RedisTemplate的方法是

RedisTemplate<String, Product> redis = new RedisTemplate<String, Product>();
redis.setConnectionFactory(cf);

如果项目中经常使用RedisTemplate或StringRedisTemplate的话,你可以考虑将其配置为bean,然后注入到需要的地方。如下就是一个声明RedisTemplate的简单@Bean方法:

    @Bean
    public RedisTemplate<String, Product> redisTemplate(RedisConnectionFactory cf) {
        RedisTemplate<String, Product> redis = new RedisTemplate<String, Product>();
        redis.setConnectionFactory(cf);
        return redis;
    }

RedisTemplate的很多功能是以子API的形式提供的,它们区分了单个值和集合值的场景:
这里写图片描述

简单DEMO, 因为例子比较简单, 就不一一解释


    @Test
    public void workingWithSimpleValues() {

    //region Description
        //直接使用 Connection
        RedisConnection conn = cf.getConnection();
        conn.set("key".getBytes(), "someValue".getBytes());

        byte[] bytesValue = conn.get("key".getBytes());
        System.out.println(new String(bytesValue));
    //endregion


        Product product = new Product();
        product.setSku("9781617291203");
        product.setName("Spring in Action");
        product.setPrice(39.99f);

        //简单使用
        redis.opsForValue().set(product.getSku(), product);

        Product found = redis.opsForValue().get(product.getSku());
        assertEquals(product.getSku(), found.getSku());
        assertEquals(product.getName(), found.getName());
        assertEquals(product.getPrice(), found.getPrice(), 0.005);
    }

    @Test
    public void workingWithLists() {
        Product product = new Product();
        product.setSku("9781617291203");
        product.setName("Spring in Action");
        product.setPrice(39.99f);

        Product product2 = new Product();
        product2.setSku("9781935182436");
        product2.setName("Spring Integration in Action");
        product2.setPrice(49.99f);

        Product product3 = new Product();
        product3.setSku("9781935182955");
        product3.setName("Spring Batch in Action");
        product3.setPrice(49.99f);

        //使用List的值
        redis.opsForList().rightPush("cart", product);
        redis.opsForList().rightPush("cart", product2);
        redis.opsForList().rightPush("cart", product3);

        assertEquals(3, redis.opsForList().size("cart").longValue());

        Product first = redis.opsForList().leftPop("cart");
        Product last = redis.opsForList().rightPop("cart");

        assertEquals(product.getSku(), first.getSku());
        assertEquals(product.getName(), first.getName());
        assertEquals(product.getPrice(), first.getPrice(), 0.005);

        assertEquals(product3.getSku(), last.getSku());
        assertEquals(product3.getName(), last.getName());
        assertEquals(product3.getPrice(), last.getPrice(), 0.005);

        assertEquals(1, redis.opsForList().size("cart").longValue());
    }

    @Test
    public void workingWithLists_range() {
        for (int i = 0; i < 30; i++) {
            Product product = new Product();
            product.setSku("SKU-" + i);
            product.setName("PRODUCT " + i);
            product.setPrice(i + 0.99f);
            redis.opsForList().rightPush("cart", product);
        }

        assertEquals(30, redis.opsForList().size("cart").longValue());

        List<Product> products = redis.opsForList().range("cart", 2, 12);
        for (int i = 0; i < products.size(); i++) {
            Product product = products.get(i);
            assertEquals("SKU-" + (i + 2), product.getSku());
            assertEquals("PRODUCT " + (i + 2), product.getName());
            assertEquals(i + 2 + 0.99f, product.getPrice(), 0.005);
        }
    }

    @Test
    public void performingOperationsOnSets() {
        Product product = new Product();
        product.setSku("9781617291203");
        product.setName("Spring in Action");
        product.setPrice(39.99f);

        redis.opsForSet().add("cart", product);
        assertEquals(1, redis.opsForSet().size("cart").longValue());
    }

    @Test
    public void performingOperationsOnSets_setOperations() {
        for (int i = 0; i < 30; i++) {
            Product product = new Product();
            product.setSku("SKU-" + i);
            product.setName("PRODUCT " + i);
            product.setPrice(i + 0.99f);
            redis.opsForSet().add("cart1", product);
            if (i % 3 == 0) {
                redis.opsForSet().add("cart2", product);
            }
        }

        Set<Product> diff = redis.opsForSet().difference("cart1", "cart2");
        Set<Product> union = redis.opsForSet().union("cart1", "cart2");
        Set<Product> isect = redis.opsForSet().intersect("cart1", "cart2");

        assertEquals(20, diff.size());
        assertEquals(30, union.size());
        assertEquals(10, isect.size());

        Product random = redis.opsForSet().randomMember("cart1");
        // not sure what to assert here...the result will be random
        assertNotNull(random);
    }

    @Test
    public void bindingToAKey() {
        Product product = new Product();
        product.setSku("9781617291203");
        product.setName("Spring in Action");
        product.setPrice(39.99f);

        Product product2 = new Product();
        product2.setSku("9781935182436");
        product2.setName("Spring Integration in Action");
        product2.setPrice(49.99f);

        Product product3 = new Product();
        product3.setSku("9781935182955");
        product3.setName("Spring Batch in Action");
        product3.setPrice(49.99f);

        //注意,我们只在一个地方使用了条目的key,也就是调用boundListOps()的时候。对返回
        // 的BoundListOperations执行的所有操作都会应用到这个key上。

        BoundListOperations<String, Product> cart = redis.boundListOps("cart");
        cart.rightPush(product);
        cart.rightPush(product2);
        cart.rightPush(product3);

        assertEquals(3, cart.size().longValue());

        Product first = cart.leftPop();
        Product last = cart.rightPop();

        assertEquals(product.getSku(), first.getSku());
        assertEquals(product.getName(), first.getName());
        assertEquals(product.getPrice(), first.getPrice(), 0.005);

        assertEquals(product3.getSku(), last.getSku());
        assertEquals(product3.getName(), last.getName());
        assertEquals(product3.getPrice(), last.getPrice(), 0.005);

        assertEquals(1, cart.size().longValue());
    }
 使用key和value的序列化器

当某个条目保存到Redis key-value存储的时候,key和value都会使用Redis的序列化器(serializer)进行序列化。Spring Data Redis提供了多个这样的序列化器,包括:

GenericToStringSerializer:使用Spring转换服务进行序列化;
JacksonJsonRedisSerializer:使用Jackson 1,将对象序列化为JSON;
Jackson2JsonRedisSerializer:使用Jackson 2,将对象序列化为JSON;
JdkSerializationRedisSerializer:使用Java序列化;
OxmSerializer:使用Spring O/X映射的编排器和解排器(marshaler和unmarshaler)实现序列化,用于XML序列化;
StringRedisSerializer:序列化String类型的key和value。

这些序列化器都实现了RedisSerializer接口,如果其中没有符合需求的序列化器,那么你还可以自行创建。

例如,假设当使用RedisTemplate的时候,我们希望将Product类型的value序列化为JSON,而key是String类型。RedisTemplate的setKeySerializer()和setValueSerializer()方法就需要如下所示:

    @Test
    public void settingKeyAndValueSerializers() {
        // need a local version so we can tweak the serializer
        RedisTemplate<String, Product> redis = new RedisTemplate<String, Product>();
        redis.setConnectionFactory(cf);
        redis.setKeySerializer(new StringRedisSerializer());
        redis.setValueSerializer(new Jackson2JsonRedisSerializer<Product>(Product.class));
        redis.afterPropertiesSet(); // if this were declared as a bean, you wouldn't have to do this

        Product product = new Product();
        product.setSku("9781617291203");
        product.setName("Spring in Action");
        product.setPrice(39.99f);

        redis.opsForValue().set(product.getSku(), product);

        Product found = redis.opsForValue().get(product.getSku());
        assertEquals(product.getSku(), found.getSku());
        assertEquals(product.getName(), found.getName());
        assertEquals(product.getPrice(), found.getPrice(), 0.005);

        StringRedisTemplate stringRedis = new StringRedisTemplate(cf);
        String json = stringRedis.opsForValue().get(product.getSku());
        assertEquals("{\"sku\":\"9781617291203\",\"name\":\"Spring in Action\",\"price\":39.99}", json);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值