第六篇:SpringBoot集成Redis

redis介绍

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。
Redis 本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。

docker安装redis
  1. 拉取镜像
docker pull redis
  1. 运行容器
docker run -d --name redis --restart always -p 6379:6379 -v /usr/local/redis/config:/etc/redis -v /usr/local/redis/data:/data redis redis-server /etc/redis/redis.conf --appendonly yes
  • docker run:这里指启动容器
  • -d:后台模式启动redis
  • –name:指定容器名
  • –restart always:当服务器重启时,redis的容器也自动启动
  • -p 6379:6379:将容器的6379端口映射到宿主机的6379端口
  • -v /usr/local/redis/conf:/etc/redis:用于挂载目录,docker镜像redis默认无配置文件,在宿主主机/usr/local/redis/conf下创建redis.conf配置文件,会将宿主机的配置文件复制到docker中
  • -v /root/redis/redis01/data:/data:容器/data映射到宿主机 /usr/local/redis/data下
  • –appendonly yes:开启redis的AOF持久化,默认为false,不持久化
  1. 查看正在运行的容器
docker ps
  1. 进入redis容器里操作
docker exec -it redis redis-cli

在这里插入图片描述
5. redis默认有15个库(集群没有),通过select 1 可以切换数据库0~15

select 1

在这里插入图片描述

快速集成
  1. pom.xml文件添加依赖
		<!-- 引入redis依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
  1. application.yml添加redis配置
spring:
  redis:
    database: 0 # Redis 数据库索引(默认为0)
    host: 115.29.149.49 # Redis 服务器地址
    port: 6379 # Redis 服务器连接端口
    password: # Redis 服务器连接密码(默认为空)
    jedis:
      pool:
        max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
        max-wait: -1 # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-idle: 8 # 连接池中的最大空闲连接
        min-idle: 0 # 连接池中的最小空闲连接
    timeout: 10000 # 连接超时时间(毫秒)
自动配置

在项目中引入了 Spring Data Redis ,并且配置了 Redis 的基本信息,此时,自动化配置就会生效。
此刻我们就可以在项目中注入redisTemplate进行使用,可以查看RedisTemplate的自动配置源码,如下:

@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(
                    RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
            RedisTemplate<Object, Object> 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;
    }
}

通过源码可以看出Springboot会自动在容器中生成一个RedisTemplate 和StringRedisTemplate ,其中 StringRedisTemplate 是 RedisTemplate 的子类,RedisTemplate 的泛型是<Object,Object>意味着key和value都可以是同一个对象,但写代码不方便需要写很多类型转换,我们需要一个泛型为<String,Object>形式的RedisTemplate。而且,这个RedisTemplate 没有设置数据存在redis时的key和value的序列化方式。

SpringBoot具有天然的开箱即用的特点,那么集成redis也是一样,通过redisTemplate进行操作:

 redisTemplate.opsForValue();//操作字符串

 redisTemplate.opsForHash();//操作hash

 redisTemplate.opsForList();//操作list

 redisTemplate.opsForSet();//操作set

 redisTemplate.opsForZSet();//操作有序set

注意:
如果没有设置key和value的序列化方式,那么存入数据会乱码一样。
举个小例子:

@RestController
@RequestMapping(value = "/user")
@Api(tags = "UserController", description = "用户管理")
public class UserController {
	@Autowired
    private RedisTemplate redisTemplate;
    
	@RequestMapping(value = "/getRedis")
    public void getRedisValue(){
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        operations.set("devin", "药岩");
        operations.set("jack", "药尘");
    }
}

通过命令查询存入的所有key:

keys *

查询如下图所示:
在这里插入图片描述
可以看出Jack和devin前面的字符乱码是因为RedisTemplate 序列化的结果,而RedisTemplate 中key的默认序列化方案是JDK的序列化策略(JdkSerializationRedisSerializer) ,可这在StringRedisTemplate 中,key 默认的序列化方案是 StringRedisSerializer ,因此,如果使用 StringRedisTemplate ,默认情况下 key 前面不会有这种乱码前缀。

自动配置不好用那就重写一下RedisTemplate

创建一个RedisConfig的配置类

/**
 * redis 配置类
 * @ClassName RedisConfig
 * @Author 药岩
 * @Date 2020/2/2
 * Version 1.0
 */
@Configuration
public class RedisConfig {

    private final RedisTemplate redisTemplate;

    @Autowired
    public RedisConfig(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Bean
    @SuppressWarnings("unchecked")
    public RedisTemplate<String, Object> redisTemplate(){
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        RedisSerializer<Object> jacksonSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        // key采用String的序列化方式
        redisTemplate.setKeySerializer(redisSerializer);
        // value的序列化采用jackson
        redisTemplate.setValueSerializer(jacksonSerializer);
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(redisSerializer);
        // hash的value也采用jackson
        redisTemplate.setHashValueSerializer(jacksonSerializer);
        return redisTemplate;
    }
}

@SuppressWarnings(“unchecked”) 注解:
告诉编译器忽略指定的警告,屏蔽未检查的转换时的警告

先清空当前的数据库
在这里插入图片描述
浏览器再访问:http://localhost:8080/user/getRedis
再次查看存入的数据:
在这里插入图片描述

工具为redis客户端

redis客户端下载,解压即可使用
链接:https://pan.baidu.com/s/1ZASHtYKmtECBdmeceItQ3w
提取码:ahp6

编写redis工具类,对常用方法进行封装

在实际的使用过程中,不会给每一个使用的类都注入 redisTemplate 来直接使用,一般都会对业务进行简单的包装,最后提供出来对外使用。

/**
 * redis工具类
 * @ClassName RedisUtil
 * @Author 药岩
 * @Date 2020/2/2
 * Version 1.0
 */

@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 判断key是否存在
     * @Author 药岩
 	 * @Date 2020/2/2
     * @param  * @param key 
     * @return boolean
     */
    public boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除缓存
     * @Author 药岩
 	 * @Date 2020/2/2
     * @param  * @param key 
     * @return void
     */
    public void del(String... key){
        if (key != null && key.length > 0){
            if (key.length == 1){
                redisTemplate.delete(key[0]);
            }else {
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }

    /**
     * 设置缓存失效时间
     * @Author 药岩
 	 * @Date 2020/2/2
     * @param  * @param key
     * @param time 
     * @return boolean
     */
    public boolean expire(String key, Long time){
        try {
            if (time > 0){
                redisTemplate.expire(key, time, TimeUnit.MINUTES);
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * String类型 数据存入缓存
     * @Author 药岩
 	 * @Date 2020/2/2
     * @param  * @param key
     * @param value 
     * @return boolean
     */
    public boolean set(String key, Object value){
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * String类型 根据key获取缓存
     * @Author 药岩
 	 * @Date 2020/2/2
     * @param  * @param key 
     * @return java.lang.Object
     */
    public Object get(String key){
        return key != null ? redisTemplate.opsForValue().get(key) : null;
    }
}

创建一个User对象

/**
 * 用户信息
 * @ClassName CoinUser
 * @Author 药岩
 * @Date 2020/2/2
 * Version 1.0
 */
public class CoinUser {

    private Long id;
    private String loginName;
    private String password;
    private String email;
    private String mobile;

    public CoinUser() {
    }

    public CoinUser(String loginName, String password, String email, String mobile) {
        this.loginName = loginName;
        this.password = password;
        this.email = email;
        this.mobile = mobile;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getLoginName() {
        return loginName;
    }

    public void setLoginName(String loginName) {
        this.loginName = loginName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
}

编写测试类

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRedisTemplate {

    @Autowired
    private RedisUtil redisUtil;

    @Test
    public void testRedis(){
        CoinUser coinUser = new CoinUser("药岩", "123456", "[email protected]", "1870797****");
        redisUtil.set("user", coinUser);
    }
}

往redis里面存入一个User对象,启动运行后,通过redis客户端查看
在这里插入图片描述

超时失效
将刚刚存入redis中的用户信息,并设置1000毫秒后失效,启动一个线程暂停2000毫秒,再查看redis中的用户信息是否存在。

	@Test
    public void testRedisExpire() throws InterruptedException {
        redisUtil.expire("user", 1000L);
        Thread.sleep(2000);
        boolean exist = redisUtil.hasKey("user");
        if (exist){
            System.out.println("用户信息存在");
        }else {
            System.out.println("用户信息失效");
        }
    }

控制台打印:

用户信息失效

本篇主要介绍String数据类型,喜欢的点赞+转发就是最大的支持!

发布了29 篇原创文章 · 获赞 43 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/CSDN_Qiang17/article/details/104638777