Bootstrap

Spring中使用Redis

Spring中使用Redis

1. 配置环境

 <!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>

​ 这里值得注意的是:jar包和spring版本兼容的问题,笔者使用的jar包版本是1.7.2,而Spring的版本是4.3.2。如果使用其他版本的话,可能存在不兼容的问题。

2. 测试连接

@Test
    //测试是否连接成功
    public void testConn(){
        Jedis jedis = new Jedis("localhost",6379);
//        jedis.auth("password");//如果由密码的话
        int i = 0;
        try{
            long start = System.currentTimeMillis();//开始时间
            while (true){
                long end = System.currentTimeMillis();
                if (end - start >= 1000){
                    break;
                }
                i++;
                jedis.set("test"+i,i+"");
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            jedis.close();
        }
        System.out.println("Jedis每秒操作:"+i+"次");
    }

运行结果:

Jedis每秒操作:23564

3. 使用Redis连接池

​ Java Redis的连接池提供了类:redis.clients.jedis.JedisPool 用来创建Redis的连接池对象。使用这个对象,需要使用类:redis.clients.jedis.JedisPoolConfig来对连接池进行配置,如代码所示:

@Test
    //配置连接池
    public void testJedisPool(){
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        //最大空闲数
        poolConfig.setMaxIdle(50);
        //最大连接数
        poolConfig.setMaxTotal(100);
        //最大等待毫秒数
        poolConfig.setMaxWaitMillis(20000);
        //使用配置创建连接池
        JedisPool jedisPool = new JedisPool(poolConfig,"localhost");
        //从连接池获取单个连接对象
        Jedis jedis = jedisPool.getResource();
        //如果需要密码
//        jedis.auth("password");
    }

4. RedisTemplate

​ 由于Redis只能提供基于字符串型的操作,而在Java中 使用的却以类对象为主,所以需要Redis存储的字符串和Java对象进行互相转换。好在Spring对这些进行了封装和支持,它提供了序列化的设计框架和一些序列化的类,使用后可以通过序列化把Java对象封装,使得Redis能把器存储起来,并且在读的时候,再把由序列化过的字符串转化位Java对象。这样在Java中使用Redis就更简单了,所以更多的时候可以使用SPring提供的RedisTemplate的机制来使用Redis

​ 使用RedisTemplate需要下载Spring-data-redis.jar,开头已经将对应maven坐标导入。下面看如何配置。

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <property name="maxIdle" value="50"/><!-- 最大空闲数 -->
        <property name="maxTotal" value="100"/><!-- 最大连接数 -->
        <property name="maxWaitMillis" value="20000"/><!-- 最大等待时间 -->
    </bean>
    <!-- 在使用RedisTemplate之前需要配置Spring所提供的连接工厂
     以:JedisConnectionFactory为例-->
    <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="localhost"/>
        <property name="port" value="6379"/>
        <property name="poolConfig" ref="poolConfig"/>
    </bean>

    <!--对POJO的序列化存储配置 -->
    <!-- 配置Spring RedisTemplate -->
    <!-- value的序列化器 
    JdkSerializationRedisSerializer序列化器是对Java对象进行序列化以存储进Redis所需要的-->
    <bean id="jdkSerializationRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
    <!-- key的序列化器 -->
    <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
    <!-- 配置Spring RedisTemplate -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="connectionFactory"/>
        <property name="keySerializer" ref="stringRedisSerializer"/>
        <property name="valueSerializer" ref="jdkSerializationRedisSerializer"/>
    </bean>

5. 使用Redis保存Java类对象

  1. 创建Account类,实现序列化接口。
public class Account implements Serializable {
    private Integer id;
    private Integer uid;
    private Double money;
    ***get/set***
}
  1. 使用RedisTemplate实现保存
@Test
    public void testJedisTemplate(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        RedisTemplate template = ac.getBean("redisTemplate", RedisTemplate.class);
        Account account = new Account();
        account.setId(8);
        account.setUid(50);
        account.setMoney(4000D);
        template.opsForValue().set("account_1",account);
        Account account1 = (Account) template.opsForValue().get("account_1");
        System.out.println(account1);
    }

​ 注意:以上的操作都是基于RedisTemplate、基于连接池的操作,换句话说,并不能保证每次使用RedisTemplate是操作同一个 对Redis的连接。比如:

template.opsForValue().set("account_1",account);
Account account1 = (Account) template.opsForValue().get("account_1");

​ set和get方法看起来简单,但是它可能就来自于同一个Redis连接池不同Redis的连接,为了使得所有的操作都来自于同一个连接,可以使用SessionCallback或者RedisCallback这两个接口,更多的时候使用的是SessionCallback这个接口,通过这个接口就可以把多个命令放入到同一个Redis连接中去执行,如下:

@Test
    //使用SessionCallback接口。
    //目的:使多个命令放入到同一个Redis连接中
    public void testSessionCallback(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        RedisTemplate template = ac.getBean("redisTemplate", RedisTemplate.class);
        Account account = new Account();
        account.setId(9);
        account.setUid(50);
        account.setMoney(4000D);
        SessionCallback callback = new SessionCallback() {
            @Override
            public Object execute(RedisOperations ops) throws DataAccessException {
                ops.boundValueOps("account_2").set(account);
                return (Account)ops.boundValueOps("account_2").get();
            }
        };
        Account saveAccount = (Account)template.execute(callback);
        System.out.println(saveAccount);
    }
    //这样使得set和get命令就能够保证在同一个连接池的同一个Redis连接池进行操作。
;