SpringBoot整合Redis-最佳实践

前言

Spring Boot对很多NoSQL数据库提供了自动化配置的支持,包括为Redis,MongoDB,Neo4j,Elasticsearch,Solr Cassandra、Couchbase和LDAP。本文主要介绍,SpringBoot整合Redis的配置以及本人在SpringBoot项目中使用Redis遇到的问题和解决方法。

Redis

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,Spring Boot为Lettuce和Jedis客户端库提供了基本的自动配置,并提供了由它们提供的抽象Spring Data Redis。本文选取Jedis进行介绍。

引入依赖

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

参数配置

spring:
  redis:
    database: 0
    host: localhost
    port: 6379
    password: 123456
    timeout: 2000
    jedis:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

具体参数配置可以参考:org.springframework.boot.autoconfigure.data.redis.RedisProperties

应用测试

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Test
    public void testStringRedis() throws Exception {
        stringRedisTemplate.opsForValue().set("aaa", "111");
        Assert.assertEquals("111", stringRedisTemplate.opsForValue().get("aaa"));

    }
}

上面简单的测试演示了如何通过SpringBoot自动配置的StringRedisTemplate对象进行Redis的读写操作,该对象从命名中就可确定支持的是String类型。如果有使用过spring-data-redis一定熟悉RedisTemplate<K, V>接口,StringRedisTemplate就相当于RedisTemplate<String, String>的实现。源码如下:

public class StringRedisTemplate extends RedisTemplate<String, String> {

  /**
   * Constructs a new <code>StringRedisTemplate</code> instance. {@link #setConnectionFactory(RedisConnectionFactory)}
   * and {@link #afterPropertiesSet()} still need to be called.
   */
  public StringRedisTemplate() {
    setKeySerializer(RedisSerializer.string());
    setValueSerializer(RedisSerializer.string());
    setHashKeySerializer(RedisSerializer.string());
    setHashValueSerializer(RedisSerializer.string());
  }

  /**
   * Constructs a new <code>StringRedisTemplate</code> instance ready to be used.
   *
   * @param connectionFactory connection factory for creating new connections
   */
  public StringRedisTemplate(RedisConnectionFactory connectionFactory) {
    this();
    setConnectionFactory(connectionFactory);
    afterPropertiesSet();
  }

  protected RedisConnection preProcessConnection(RedisConnection connection, boolean existingConnection) {
    return new DefaultStringRedisConnection(connection);
  }
}

除了String类型,实战中我们还经常会在Redis中存储对象,这时候我们就会想是否可以使用类似RedisTemplate<String, Person>来初始化并进行操作。

 

实战应用

  • 创建要存储的对象:Person
@Data
public class Person implements Serializable {
    private static final long serialVersionUID = -3958394023121991038L;

    private String username;
    private long age;

    public Person() {
    }

    public Person(String username, long age) {
        this.username = username;
        this.age = age;
    }

}

 

  • 配置针对Person的RedisTemplate实例
@Configuration
public class RedisConfig {

    @Bean
    JedisConnectionFactory jedisConnectionFactory() {
        return new JedisConnectionFactory();
    }

    @Bean
    public RedisTemplate<String, Person> personRedisTemplate() {
        RedisTemplate<String, Person>  personRedisTemplate = new RedisTemplate();
        personRedisTemplate.setConnectionFactory(jedisConnectionFactory());
        // 设置key序列化和反序列化类型
        personRedisTemplate.setKeySerializer(new StringRedisSerializer());
        // 设置value序列化和反序列化类型
        personRedisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Person.class));
        return personRedisTemplate;
    }
}

注意:在实例化RedisTemplate可以不用指定其序列化和反序列化的类型,默认是JdkSerializationRedisSerializer

Spring提供了多个序列化类型,按照项目需求灵活选取,如下:

image.png

 

  • 创建Person的缓存操作类
@Repository
public class PersonCache {
    @Autowired
    private RedisTemplate personRedisTemplate;

    protected ValueOperations<String, Person> valueOperations;

    @PostConstruct
    public void init() {
        valueOperations = personRedisTemplate.opsForValue();
    }

    public void add(Person person) {
        valueOperations.set(person.getUsername(), person, 10L, TimeUnit.MINUTES);
    }

    public Person load(String key) {
        return valueOperations.get(key);
    }
}
  • 测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {

    @Autowired
    private PersonCache personCache;

    @Test
    public void testPersonCache() {
        Person person = new Person("张三", 10000);
        personCache.add(person);
        person = new Person("李四", 10001);
        personCache.add(person);

        Assert.assertEquals(10001, personCache.load("李四").getAge());
    }
}

至此SpringBoot整合Redis及简单是用演示结束。但是在实际项目中我们需要缓存的对象往往不只一个,如果我们还想保存缓存其它对象,这里只需要在RedisConfig配置类里实例化对应的RedisTemplate,例如加一个Cilent对象,添加如下代码:

@Bean
public RedisTemplate<String, Client> clientRedisTemplate() {
  RedisTemplate<String, Client> clientRedisTemplate = new RedisTemplate();
  clientRedisTemplate.setConnectionFactory(jedisConnectionFactory());
  clientRedisTemplate.setConnectionFactory(jedisConnectionFactory());
  clientRedisTemplate.setKeySerializer(new StringRedisSerializer());
  clientRedisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Client.class));
  return clientRedisTemplate;
}

 

遇到的坑

  1. SpringBoot默认会装配一个RedisTemplate实例,名称为redisTemplate,自己实例化RedisTemplate避免与SpringBoot默认装配的实例混淆。
  2. 不推荐的使用方式,如下:
// 示例代码一
@Autowired
private RedisTemplate redisTemplate;
protected ValueOperations<String, App> valueOperations;

@PostConstruct
public void init() {
  valueOperations = redisTemplate.opsForValue();
  redisTemplate.setKeySerializer(new StringRedisSerializer());
  // 使用JDK自带的序列化
  redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
  // 省略操作代码

}
// 示例代码二
@Autowired
private RedisTemplate redisTemplate;
protected ValueOperations<String, Map> valueOperations;

@PostConstruct
public void init() {
  valueOperations = redisTemplate.opsForValue();
  redisTemplate.setKeySerializer(new StringRedisSerializer());
  // 使用JSON序列化
  redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Map.class));
}

示例代码一和示例代码二中都使用@Autowired注入redisTemplate(SpringBoot自动装配的),这样两个地方使用的是同一个RedisTemplate实例,这样就可能造成反序列化失败

  1. 在设置序列化为Json时,如果报 java: 无法访问com.fasterxml.jackson.databind.JavaType错误,需要添加spring-boot-starter-json依赖:
<dependency>    

    <groupId>org.springframework.boot</groupId>  

    <artifactId>spring-boot-starter-json</artifactId>

</dependency>

我的代码中没有报错是因为spring-boot-starter-web中引用了spring-boot-starter-json

image.png

代码示例

github:https://github.com/shallynever/SpringBootStudy/tree/master/SpringBootRedis

 

 

【ZhoujEndless】至此!感觉您的阅读,如有任何问题,欢迎打扰!如有表述错误,劳烦指出!

参考文章:http://blog.didispace.com/springbootredis/

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值