欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RedisTemplate常用集合使用说明(一)

程序员文章站 2022-06-23 10:29:02
...

   在这里我使用的是spring-boot框架组合的redisTemplate的jar包spring-boot-starter-data-redis,采用POM的方式引入,引入代码如下:

 

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

  RedisTemplate主要支持String,List,Hash,Set,ZSet这几种方式的参数,其对应的方法分别是opsForValue()、opsForList()、opsForHash()、opsForSet()、opsForZSet()。下面分别介绍这几个方法的使用。

 

  在介绍之前,首先说下RedisTemplate的序列化方法,在RedisTemplate类下有一个继承了该类的StringRedisTemplate类,该类主要用于opsForValue()方法的String类型的实现,而且这2个类的内部实现不一样,如果是使用RedisTemplate类作为连接Redis的工具类,如果不使用opsForValue方法的话,我们可以这样初始化序列化方法:

 

ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setKeySerializer(template.getStringSerializer());
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);

 如果需要使用opsForValue()方法的话,我们就必须使用如下的序列化方法:

 

 

ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om); 
//在使用String的数据结构的时候使用这个来更改序列化方式
RedisSerializer<String> stringSerializer = new StringRedisSerializer();
template.setKeySerializer(stringSerializer );
template.setValueSerializer(stringSerializer );
template.setHashKeySerializer(stringSerializer );
template.setHashValueSerializer(stringSerializer );

   当然如果想使用RedisTemplate方法作为bean来使用,必须按照如下的方式实现代码(这里介绍的都是通过使用spring-boot方式进行使用):

1.  我们可以在application.properties文件定义如下的redis连接:

 

	#配置缓存redis
spring.redis.database=8
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.keytimeout=1000
spring.redis.timeout=0

2. 使用RedisTemplate类来设置bean文件:

 

 

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @author liaoyubo
 * @version 1.0 2017/8/1
 * @description
 */
@Configuration
public class RedisConfig {

    @Value("${spring.redis.host}")
    private String hostName;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String passWord;
    @Value("${spring.redis.pool.max-idle}")
    private int maxIdl;
    @Value("${spring.redis.pool.min-idle}")
    private int minIdl;
    @Value("${spring.redis.database}")
    private int database;
    @Value("${spring.redis.keytimeout}")
    private long keytimeout;
    @Value("${spring.redis.timeout}")
    private int timeout;

    /*@Bean
    public JedisConnectionFactory redisConnectionFactory() {
        JedisConnectionFactory factory = new JedisConnectionFactory();
        factory.setHostName(hostName);
        factory.setPort(port);
        factory.setTimeout(timeout); //设置连接超时时间
        return factory;
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        StringRedisTemplate template = new StringRedisTemplate(factory);
        setSerializer(template); //设置序列化工具,这样ReportBean不需要实现Serializable接口
        template.afterPropertiesSet();
        return template;
    }
    private void setSerializer(StringRedisTemplate template) {
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
    }*/

    @Bean
    public RedisConnectionFactory redisConnectionFactory(){
        JedisPoolConfig poolConfig=new JedisPoolConfig();
        poolConfig.setMaxIdle(maxIdl);
        poolConfig.setMinIdle(minIdl);
        poolConfig.setTestOnBorrow(true);
        poolConfig.setTestOnReturn(true);
        poolConfig.setTestWhileIdle(true);
        poolConfig.setNumTestsPerEvictionRun(10);
        poolConfig.setTimeBetweenEvictionRunsMillis(60000);
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(poolConfig);
        jedisConnectionFactory.setHostName(hostName);
        if(!passWord.isEmpty()){
            jedisConnectionFactory.setPassword(passWord);
        }
        jedisConnectionFactory.setPort(port);
        jedisConnectionFactory.setDatabase(database);
        return jedisConnectionFactory;
    }
    @Bean
    public RedisTemplate<String, Object> redisTemplateObject() throws Exception {
        RedisTemplate<String, Object> redisTemplateObject = new RedisTemplate<String, Object>();
        redisTemplateObject.setConnectionFactory(redisConnectionFactory());
        setSerializer(redisTemplateObject);
        redisTemplateObject.afterPropertiesSet();
        return redisTemplateObject;
    }



    private void setSerializer(RedisTemplate<String, Object> template) {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(
                Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        /*template.setKeySerializer(template.getStringSerializer());
        template.setValueSerializer(jackson2JsonRedisSerializer);
        template.setHashValueSerializer(jackson2JsonRedisSerializer);*/
        //在使用String的数据结构的时候使用这个来更改序列化方式
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        template.setKeySerializer(stringSerializer );
        template.setValueSerializer(stringSerializer );
        template.setHashKeySerializer(stringSerializer );
        template.setHashValueSerializer(stringSerializer );

    }

}

 3.  创建启动类App

 

 

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author liaoyubo
 * @version 1.0 2017/7/31
 * @description
 */
@SpringBootApplication
public class App {

    public static void main(String [] args){
        SpringApplication.run(App.class);
    }

}

  通过以上步骤我们就可以以bean的注入方式正常使用RedisTemplate模板类了,如果没有安装Redis,请到https://redis.io/download官网下载需要的Redis。下面依次主要介绍RedisTemplate集合以及pipelinemulti的使用,官网地址是http://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/RedisTemplate.html。注入RedisTemplate方法如下:

 

 

 

@Autowired
private RedisTemplate<String,Object> redisTemplate;

 一、pipeline介绍

 

      Pipelineredis提供的一种通道功能,通常使用pipeline的地方是不需要等待结果立即返回的时候,使用pipeline的好处是处理数据的速度更快因为它专门开辟了一个管道来处理数据(具体的对比可以参考网上的文章),它是单向的,从客户端向服务端发送数据,当管道关闭链接时将会从服务端返回数据,再次期间是无法获取到服务端的数据的。

   因为这个例子的需要,我们把RedisConfig.java类的序列化的方式修改为:

 

template.setKeySerializer(template.getStringSerializer());
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);

 下面是一个基本的使用示例:

import com.springRedis.App;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;


/**
 * @author liaoyubo
 * @version 1.0 2017/7/31
 * @description
 */

@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class PipelineTest {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Test
    public void testPipeLine(){
        redisTemplate.opsForValue().set("a",1);
        redisTemplate.opsForValue().set("b",2);
        redisTemplate.executePipelined(new RedisCallback<Object>() {
            @Override
            public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
                redisConnection.openPipeline();
                for (int i = 0;i < 10;i++){
                    redisConnection.incr("a".getBytes());
                }
                System.out.println("a:"+redisTemplate.opsForValue().get("a"));
                redisTemplate.opsForValue().set("c",3);
                for(int j = 0;j < 20;j++){
                    redisConnection.incr("b".getBytes());
                }
                System.out.println("b:"+redisTemplate.opsForValue().get("b"));
                System.out.println("c:"+redisTemplate.opsForValue().get("c"));
                redisConnection.closePipeline();
                return null;
            }
        });
        System.out.println("b:"+redisTemplate.opsForValue().get("b"));
        System.out.println("a:"+redisTemplate.opsForValue().get("a"));
    }

}

 二、multiexec

 

   这2个方法是RedisTemplate.java类提供的事务方法。在使用这个方法之前必须开启事务才能正常使用。例子如下:

 

import com.springRedis.App;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

/**
 * @author liaoyubo
 * @version 1.0 2017/8/4
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class MultiTest {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Test
    public void testMulti(){
        ValueOperations<String,Object> valueOperations = redisTemplate.opsForValue();
        redisTemplate.setEnableTransactionSupport(true);
        //在未提交之前是获取不到值得,同时再次循环报错
        while (true){
            redisTemplate.watch("multiTest");
            redisTemplate.multi();
            valueOperations.set("multiTest",1);
            valueOperations.increment("multiTest",2);
            Object o = valueOperations.get("multiTest");
            List list = redisTemplate.exec();
            System.out.println(list);
            System.out.println(o);
        }

    }

}

           在使用exec()方法的时候,没有带入参数,使用的是默认的序列化方法,同时提供了一个exec(RedisSerializer<?> valueSerializer)方法,这个方法可以自己定义序列化方法,如Jackson2JsonRedisSerializer。

       后面将一次介绍RedisTemplate集合的使用。