学习springBoot(6)Redis整合

428 阅读4分钟

Redis简介

Redis百度百科

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。 Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。 [1] Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )
 |`-._`-...-` __...-.``-._|'` _.-'|
 |    `-._   `._    /     _.-'    |
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

看了下别人的文章说是在springboot 2.X 中 redis 的底层不在是Jedis,换成了Lettuce, Lettuce和Jedis的都是连接Redis Server的客户端程序。Jedis在实现上是直连redis server,多线程环境下非线程安全,除非使用连接池,为每个Jedis实例增加物理连接。Lettuce基于Netty的连接实例(StatefulRedisConnection),可以在多个线程间并发访问,且线程安全,满足多线程环境下的并发访问,同时它是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。

导入JAR包

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!--加入一个fastJSON-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.46</version>
</dependency>

添加配置文件


  #配置redis
  redis:
   #数据库索引
    database: 0 # Redis默认情况下有16个分片,这里配置具体使用的分片,默认是0
    host: 127.0.0.1
    port: 6379
    password: pass1234
    lettuce:
      pool:
          #最大连接数
        max-active: 8
          #最大阻塞等待时间(负数表示没限制)
        max-wait: -1
          #最大空闲
        max-idle: 8
          #最小空闲
        min-idle: 0
      #连接超时时间
    timeout: 1000

StringRedisTemplate : 只支持String 字符串的存储,如果我们要是想要存储对象的话,就需要自定义RedisTemplate(Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。)

RedisTemplate配置如下:

通过这个配置类,会在applicationContex配置文件中注册这个bean,不然会报错(xxx....'org.springframework.data.redis.core.RedisTemplate' that could not be found.),找不到RedisTemplate。

@Configuration
@AutoConfigureAfter(RedisCacheAutoConfiguration.class)
public class RedisCacheAutoConfiguration extends CachingConfigurerSupport {

    //缓存管理器
    @Bean
    public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Serializable> template = new RedisTemplate<>();
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

RedisTemplate中定义了对5种数据结构操作

redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set

下面上测试代码,这就不写测试类了,直接用之前的代码改一下:

需要注意的是,要想使用RedisTemplate 存储对象,我们的实体类需要 implements Serializable 接口

@Controller
@RequestMapping("/book")
public class BookController {
    private static Logger logger = LoggerFactory.getLogger(BookController.class);

    @Autowired
    private BookService bookService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;

    /**
     * 查询图书
     * @return
     */
    @RequestMapping(value="/list/{id}")
    @ResponseBody
    public Book list(@PathVariable(value = "id") Integer id){
        Book book = bookService.findById(id);
        stringRedisTemplate.opsForValue().set("test","测试");
        redisCacheTemplate.opsForValue().set("book",book);
        
        Book book1 = (Book) redisCacheTemplate.opsForValue().get("book");
        
        logger.info(stringRedisTemplate.opsForValue().get("test"));
        
        logger.info("[对象缓存结果] - [{}]", book1);

        logger.info("[对象缓存结果] - [{}]", JSONObject.toJSON(book1).toString());

        return book;
    }

}

结果如下:

我们看到stringRedisTemplate 的存取很简单,没什么问题,

但是第一个打印出来的”对象缓存结果“直接输出Java类的实例,会自动调用getClass().getName() + '@' + Integer.toHexString(hashCode()),也就是每个Java类自带的toString()方法的具体内容。 @后面的表示十六进制的哈希值。 要想输出具体的属性值,需要我们在实体类中重写一下 toString() 方法。

第二个”对象缓存结果“ 我们通过JSON的序列化可以正常输出。