博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Spring Boot】18.集成redis
阅读量:7142 次
发布时间:2019-06-28

本文共 13457 字,大约阅读时间需要 44 分钟。

hot3.png

简介

redis是什么相信大家都有具体的了解,不了解的同学最好先去官方网站查阅学习。

我们之前讲到的缓存系统,默认使用的是ConcurrentMapCacheManager==ConcurrentMapCache,默认开启的是SimpleCacheConfiguration配置,我们之前分析过,他还支持其他的很多缓存配置,包括我们要讲到的redis。

通过将redis集成到我们的缓存系统,我们就可以轻松的通过reids的客户端查询对应的缓存信息,实现了缓存信息的可视化。

印象笔记 —— redis是一个比传统数据库更轻量,但却拥有强大功能的“数据库”,一般在应用中充当缓存组件,例如作为数据库和应用程序上层的中间件、提供session会话信息保存等。

1 reids基础环境搭建

  1. 安装redis 传统安装redis的方法,我们就不多说了,我们使用之前用的docker安装redis.
  • 拉取redis
docker pull redis
  • 启动reids
docker run -d -p 6379:6379 --name redis redis
  • 查看结果
docker ps

输出

439e18fd2ea6        rabbitmq:3-management                                 "docker-entrypoint..."   5 days ago          Up 5 days           4369/tcp, 5671/tcp, 0.0.0.0:5672->5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp   rabbit3d9ee1d941b0        redis                                                 "docker-entrypoint..."   5 days ago          Up 5 days           0.0.0.0:6379->6379/tcp                                                                       redis402fbb3778ad        docker.elastic.co/elasticsearch/elasticsearch:6.5.3   "/usr/local/bin/do..."   5 days ago          Up 5 days           0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp                                               loving_carsone3ef44911869        mariadb                                               "docker-entrypoint..."   5 days ago          Up 5 days           0.0.0.0:3306->3306/tcp                                                                       mysql59f9c80d269b        tomcat                                                "catalina.sh run"        5 days ago          Up 5 days           0.0.0.0:8080->8080/tcp                                                                       goofy_swartz

之前我已经装好了redis,我们可以看到redis已经在我们端口6379上映射好了,接下来就可以使用redis客户端连接并查看我们自己的redis了。

  1. 安装redis客户端 redis客户端有很多,不过比较常用的是 RedisDesktopManager ,您可以轻松的下载安装。通过点击Connect to Redis Server按钮(如果您的版本和我的差不多的话,应该在右下方往右数的第二个按钮,有一个绿色的+),按照我们的redis环境对其进行配置,如果成功的话,双击生成的redis服务,就可以看到出现16个数据仓库,说明您整个过程已经成功了。一般都是如下的配置
Name : 随意写Host : 你的Redis服务器idPort: 6379Auth: 无需填写
  1. 尝试一下redis的使用 redis的使用您可以参考官网的文档尝试或者参考一些关于redis的一些博客,官方文档列出了许多相关的命令,可以一一尝试下,非常有意思。(先了解redis的特性之后在开始妥当一些。)

2 整合redis

  1. 引入redis的场景启动器:
pom.xml
org.springframework.boot
spring-boot-starter-data-redis
  1. 配置redis 可以通过sprig.redis相关参数配置redis。

application.yml

spring:  redis:    host: 10.21.1.47    port: 6379

port默认6379,如果是默认端口的话我们也可以不予指定。

  1. 查看redis自动配置类源码
/* * Copyright 2012-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.springframework.boot.autoconfigure.data.redis;import java.net.UnknownHostException;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisOperations;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;/** * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Redis support. * * @author Dave Syer * @author Andy Wilkinson * @author Christian Dupuis * @author Christoph Strobl * @author Phillip Webb * @author Eddú Meléndez * @author Stephane Nicoll * @author Marco Aust * @author Mark Paluch */@Configuration@ConditionalOnClass(RedisOperations.class)@EnableConfigurationProperties(RedisProperties.class)@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })public class RedisAutoConfiguration {	@Bean	@ConditionalOnMissingBean(name = "redisTemplate")	public RedisTemplate
redisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate
template = new RedisTemplate<>(); template.setConnectionFactory(redisConnectionFactory); return template; } @Bean @ConditionalOnMissingBean public StringRedisTemplate stringRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { StringRedisTemplate template = new StringRedisTemplate(); template.setConnectionFactory(redisConnectionFactory); return template; }}

可以看出,他为我们提供了两个组件类,一个是RedisTemplate(k-v都是对象),一个是StringRedisTemplate(k-v都是字符串)。由于我们经常使用字符串操作,所以redis配置类中为提供了stringRedisTemplate这个组件。

我们可以直接在应用中直接注入就可以使用了。

3 测试redis操作

redis支持的五大数据类型:String(字符串)、List(列表)、Set(集合)、Hash(散列)、ZSet(有序集合),我们都可以使用springboot提供的组件类进行操作。

  1. StringRedisTemplate

通过redisTemplate.opsXXX.redis提供的Command来操作相应的数据。例如redisTemplate.opsForHash.

test/AwebApplicationTests
package com.zhaoyi.aweb;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.StringRedisTemplate;import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class)@SpringBootTestpublic class AwebApplicationTests {    @Autowired    StringRedisTemplate stringRedisTemplate;    @Autowired    RedisTemplate redisTemplate;    @Test    public void test01() {        stringRedisTemplate.opsForValue().append("name", "a");        stringRedisTemplate.opsForValue().append("name","kuya");        System.out.println(stringRedisTemplate.opsForValue().get("name"));    }    @Test    public void contextLoads() {    }}

运行test01测试方法后,我们的redis存储库中存储了一个String类型的name数据,其值为akuya,其他的操作大家都可以一一逐个测试,当然不同的数据类型设置和获取由些许差异。

接下来我们使用RedisTemplate类型的template来测试对象的保存。

  1. RedisTemplate
test/AwebApplicationTests
@Autowired    RedisTemplate redisTemplate;    @Test    public void test02() {        Integer id = 1;        String key = "user_" + id;        User user = userService.getUser(id);        redisTemplate.opsForValue().set(key, user);        System.out.println(redisTemplate.opsForValue().get(key));    }

我们查询id=2的用户信息,并以user_{id}为key的方式存储一个对象user的信息,运行测试用例test02我们会发现报错:

...java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.zhaoyi.aweb.bean.User]...

提示我们需要提供的应该是一个可序列化的有效载荷(patload)类型,因此,我们需要将User标志为可序列化的对象类型。

bean/User.class
public class User implements Serializable {    private static final long serialVersionUID = 4125096758372084309L;

我们再运行之后,查看redis客户端的存储信息发现

key=\xAC\xED\x00\x05t\x00\x06user_1value = \xAC\xED\x00\x05sr\x00\x19com.zhaoyi.aweb.bean.User\xC7\xD7\xAC\x00\x0F\xDB\x0A\x97\x02\x00\x04L\x00\x0CdepartmentIdt\x00\x13Ljava/lang/Integer;L\x00\x02idq\x00~\x00\x01L\x00\x09loginNamet\x00\x12Ljava/lang/String;L\x00\x08userNameq\x00~\x00\x02xpsr\x00\x11java.lang.Integer\x12\xE2\xA0\xA4\xF7\x81\x878\x02\x00\x01I\x00\x05valuexr\x00\x10java.lang.Number\x86\xAC\x95\x1D\x0B\x94\xE0\x8B\x02\x00\x00xp\x00\x00\x00\x01q\x00~\x00\x06t\x00\x05akuyat\x00\x09\xE9\x98\xBF\xE5\xBA\x93\xE5\xA8\x85

也就是说,保存对象时,都是以jdk序列化机制,不管是key还是value都是序列化的字符串了。

通常,我们还是习惯自己转化为json方式来存储:

  • 将对象转化为json字符串存储 这个很简单,我们一般使用这一种
  • 修改默认序列化器为json序列化器。

我们先查看默认情况下用的是什么序列化器:

org.springframework.data.redis.core.RedisTemplate
if (defaultSerializer == null) {    defaultSerializer = new JdkSerializationRedisSerializer(            classLoader != null ? classLoader : this.getClass().getClassLoader());}

也就是JdkSerializationRedisSerializer,接下来,我们修改为自己的序列化器。

config/MyConfig.class
package com.zhaoyi.aweb.config;import com.zhaoyi.aweb.bean.User;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import java.net.UnknownHostException;@Configurationpublic class MyConfig {    @Bean    public RedisTemplate
redisTemplateUser(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate
template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); // 设置默认的序列化器 Jackson2JsonRedisSerializer
userJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer
(User.class); template.setDefaultSerializer(userJackson2JsonRedisSerializer); return template; }}

然后,我们使用该template来进行redis的存储操作

test/AwebApplicationTests
@Autowired    RedisTemplate
redisTemplate; @Test public void test02() { Integer id = 1; String key = "user_" + id; User user = userService.getUser(id); redisTemplate.opsForValue().set(key, user); //System.out.println(redisTemplate.opsForValue().get(key)); }

查看我们的redis客户端,就可以看到不管是key还是value都是易读的的形式了:

key = "user_1"value = {  "id": 1,  "loginName": "akuya",  "userName": "阿库娅",  "departmentId": 1}

4 测试缓存

我们引入redis的starter之后,我们的容器中的缓存管理器变成了RedisCacheManager,他的作用是创建了RedisCache来作为缓存组件,RedisCachle通过我们配置的redis来进行缓存数据。

前面我们使用查询user的时候,会发现redis生成了一个名叫user命名空间,缓存了我们查询的用户信息。

默认创建的RedisCacheManager使用的是RedisTemplate<Object,Object>,他默认使用的序列化器还是我们默认的JDK序列化机制。要改变这种行为,我们同样需要创建自己的自定义CacheManager,注意2.0和1.x版本还是有很大的区别,请小心版本带来的问题。

但在寻找其区别的时候,我发现一个问题,那就是我们应用中不可能没有一个类就写一个template,因此,我们需要写一个通用的redis底层存储配置,也就是说遵循:String类型的数据作为key,以json字符串作为结果进行存储,因此,编写了如下的配置器,如果嫌麻烦的同学可以直接复制过去使用,兼容任何的类与底层缓存:

config/JoyRedisConfig.class
package com.zhaoyi.aweb.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.*;import java.net.UnknownHostException;@Configurationpublic class JoyRedisConfig {    /**     * 配置RedisTemplate
* @param redisConnectionFactory * @return * @throws UnknownHostException */ @Bean public RedisTemplate
redisTemplateUser(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate
template = new RedisTemplate(); template.setConnectionFactory(redisConnectionFactory); // 设置序列化器 template.setDefaultSerializer(valueSerializer()); return template; } @Bean public RedisCacheManager redisCacheManagerUser(RedisConnectionFactory redisConnectionFactory){ // 这里可以配置超时时间等 RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration // Default { using the following: // key expiration === eternal // cache null values === yes // prefix cache keys===yes // default prefix===the actual cache name // key serializer === org.springframework.data.redis.serializer.StringRedisSerializer // value serializer === org.springframework.data.redis.serializer.JdkSerializationRedisSerializer // conversion service === DefaultFormattingConversionService with #registerDefaultConverters(ConverterRegistry) default .defaultCacheConfig() // Define the {@link SerializationPair} used for de-/serializing cache keys. .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer())) // Define the {@link SerializationPair} used for de-/serializing cache values. .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer())) // Disable caching .disableCachingNullValues(); return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(redisCacheConfiguration) .transactionAware() .build(); } // key序列化器 private RedisSerializer
keySerializer() { return new StringRedisSerializer(); } // Value序列化器 private RedisSerializer
valueSerializer() { return new GenericJackson2JsonRedisSerializer(); }}

我们可以看到通过配置@Cacheable(value = "user", key = "#id")生成的缓存key的样子为user::1,也就是说cacheName指定的值,生成了user::这样的前缀,在redis中以名称空间的形式存在;另外,如果我们以@Cacheable(value = {"user","saber"}, key = "#id"),这样存储的话,结果会在user和saber两个名称空间中,存储两份结果,即user::1saber::1

注意这是2.x版本,简化配置。基本满足需要,如果您有详细的配置,例如超时时间、针对具体的容器进行配置,可以在redisCacheConfiguration配置。

还记得@CacheManager注解吗,他所指定的就是我们现在定义的这些CacheManager了。

如果你配置了多个缓存管理器,别忘了为默认的缓存管理器添加一个@Primary注解。

转载于:https://my.oschina.net/u/3091870/blog/2993912

你可能感兴趣的文章
经验:常见木马和未授权控制软件的关闭 1
查看>>
[AlwaysOn Availability Groups] 健康模型 Part 2 ——扩展
查看>>
WCF客户端异常处理
查看>>
redhat5.4 www服务器配置实例(2)
查看>>
Silverlight4不同控件间拖拽实现-附源码下载
查看>>
Esxi 5.0虚拟机网络不通问题解决
查看>>
Net设计模式实例之迭代器模式(Iterator Pattern)(2)
查看>>
Cocos2d-x游戏实例-《跑跑跑》制作教程(第七篇)——添加能吃的物品以及胜利条件...
查看>>
iptables/netfilter网络防火墙实现及实战分析
查看>>
php设计模式--策略模式
查看>>
网络音视频技术的深入研究
查看>>
深入浅出Hyper-V网络虚拟化(三)
查看>>
如何在不需要安装光盘的前提下通过Win RE(Windows恢复环境)重装Windows 7
查看>>
【驱动】Flash设备驱动基础·NOR·NAND
查看>>
自己总结的jQuery点滴以及各种jQuery古怪问题
查看>>
Unity应用架构设计(6)——设计动态数据集合ObservableList
查看>>
老罗将死,或者Android也将就换代,但是互联网的,共享,互助精神将永存
查看>>
Elasticsearch之IKAnalyzer的过滤停止词
查看>>
爆牙齿的世界杯日记(玩火巴西焚世界杯)
查看>>
迷惑的C#中的Object.Equals静态方法
查看>>