SpringBoot集成Redis

Redis原生命令大全,作者整顿的很具体,大部分命令转化为java命令根本也是关键词

Redis 命令参考

接下来开始咱们的正题,一起学习下,SpringBoot整合Redis

引入依赖

pom文件不贴全副代码了,依赖有些多了,占据的篇幅过大,只贴新增的吧

  • pom.xml

    <!-- 引入redis依赖 --><dependency>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 引入redis连接池的依赖 --><dependency>  <groupId>org.apache.commons</groupId>  <artifactId>commons-pool2</artifactId></dependency>

Redis配置

随着配置越来越多,这里就不贴全副了,留神和datasource同级,在spring的上级,要去掉spring哈

  • 增加application.yml 配置
spring:  redis:    database: 0    host: 127.0.0.1    port: 6379    timeout: 5000    lettuce:      pool:        max-active: 32        max-wait: -1        max-idle: 16        min-idle: 8
  • 在config包下增加RedisConfig.java 配置类

    package com.maple.demo.config;import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.data.redis.RedisProperties;import org.springframework.boot.context.properties.EnableConfigurationProperties;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.RedisOperations;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.StringRedisSerializer;/** * @author 笑小枫 * @date 2022/07/19 **/@Configuration@ConditionalOnClass(RedisOperations.class)@EnableConfigurationProperties(RedisProperties.class)public class RedisConfig {  @Bean  @ConditionalOnMissingBean(name = "redisTemplate")  public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {      RedisTemplate<Object, Object> template = new RedisTemplate<>();      //应用fastjson序列化      FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);      // value值的序列化采纳fastJsonRedisSerializer      template.setValueSerializer(fastJsonRedisSerializer);      template.setHashValueSerializer(fastJsonRedisSerializer);      // key的序列化采纳StringRedisSerializer      template.setKeySerializer(new StringRedisSerializer());      template.setHashKeySerializer(new StringRedisSerializer());      template.setConnectionFactory(redisConnectionFactory);      return template;  }  @Bean  @ConditionalOnMissingBean(StringRedisTemplate.class)  public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {      StringRedisTemplate template = new StringRedisTemplate();      template.setConnectionFactory(redisConnectionFactory);      return template;  }}

工具类

配置完配置,其实咱们的Redis就曾经集成了,SpringBoot的starter是真的香,前面咱们会解说一下如何制作咱们本人的starter。

上面配置一下redis罕用的工具类,在util包下创立RedisUtil.java

package com.maple.demo.util;import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;import org.apache.commons.lang3.BooleanUtils;import org.springframework.data.redis.core.*;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.util.List;import java.util.Set;import java.util.concurrent.TimeUnit;/** * Redis罕用的一些操作 * * @author 笑小枫 * @date 2022/07/19 */@Componentpublic class RedisUtil {    @Resource    private RedisTemplate<String, Object> redisTemplate;    /**     * 写入缓存     */    public boolean set(final String key, Object value) {        boolean result = false;        try {            ValueOperations<String, Object> operations = redisTemplate.opsForValue();            operations.set(key, value);            result = true;        } catch (Exception e) {            e.printStackTrace();        }        return result;    }    /**     * 写入缓存设置时效工夫     */    public boolean set(final String key, Object value, Long expireTime) {        boolean result = false;        try {            ValueOperations<String, Object> operations = redisTemplate.opsForValue();            operations.set(key, value);            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);            result = true;        } catch (Exception e) {            e.printStackTrace();        }        return result;    }    /**     * 更新缓存     */    public boolean getAndSet(final String key, String value) {        boolean result = false;        try {            redisTemplate.opsForValue().getAndSet(key, value);            result = true;        } catch (Exception e) {            e.printStackTrace();        }        return result;    }    /**     * 批量删除对应的value     */    public void remove(final String... keys) {        for (String key : keys) {            remove(key);        }    }    /**     * 批量删除key     */    public void removePattern(final String pattern) {        Set<String> keys = redisTemplate.keys(pattern);        if (CollectionUtils.isNotEmpty(keys)) {            redisTemplate.delete(keys);        }    }    /**     * 删除对应的value     */    public void remove(final String key) {        if (exists(key)) {            redisTemplate.delete(key);        }    }    /**     * 判断缓存中是否有对应的value     */    public boolean exists(final String key) {        Boolean isExists = redisTemplate.hasKey(key);        return BooleanUtils.isTrue(isExists);    }    /**     * 读取缓存     */    public Object get(final String key) {        ValueOperations<String, Object> operations = redisTemplate.opsForValue();        return operations.get(key);    }    /**     * 哈希 增加     */    public void hmSet(String key, Object hashKey, Object value) {        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();        hash.put(key, hashKey, value);    }    /**     * 哈希获取数据     */    public Object hmGet(String key, Object hashKey) {        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();        return hash.get(key, hashKey);    }    /**     * 列表增加     */    public void lPush(String k, Object v) {        ListOperations<String, Object> list = redisTemplate.opsForList();        list.rightPush(k, v);    }    /**     * 列表获取     */    public List<Object> lRange(String k, long l, long l1) {        ListOperations<String, Object> list = redisTemplate.opsForList();        return list.range(k, l, l1);    }    /**     * 汇合增加     */    public void addSet(String key, Object value) {        SetOperations<String, Object> set = redisTemplate.opsForSet();        set.add(key, value);    }    /**     * 删除汇合下的所有值     */    public void removeSetAll(String key) {        SetOperations<String, Object> set = redisTemplate.opsForSet();        Set<Object> objectSet = set.members(key);        if (objectSet != null && !objectSet.isEmpty()) {            for (Object o : objectSet) {                set.remove(key, o);            }        }    }    /**     * 判断set汇合外面是否蕴含某个元素     */    public Boolean isMember(String key, Object member) {        SetOperations<String, Object> set = redisTemplate.opsForSet();        return set.isMember(key, member);    }    /**     * 汇合获取     */    public Set<Object> setMembers(String key) {        SetOperations<String, Object> set = redisTemplate.opsForSet();        return set.members(key);    }    /**     * 有序汇合增加     */    public void zAdd(String key, Object value, double source) {        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();        zset.add(key, value, source);    }    /**     * 有序汇合获取指定范畴的数据     */    public Set<Object> rangeByScore(String key, double source, double source1) {        ZSetOperations<String, Object> zSet = redisTemplate.opsForZSet();        return zSet.rangeByScore(key, source, source1);    }    /**     * 有序汇合升序获取     */    public Set<Object> range(String key, Long source, Long source1) {        ZSetOperations<String, Object> zSet = redisTemplate.opsForZSet();        return zSet.range(key, source, source1);    }    /**     * 有序汇合降序获取     */    public Set<Object> reverseRange(String key, Long source, Long source1) {        ZSetOperations<String, Object> zSet = redisTemplate.opsForZSet();        return zSet.reverseRange(key, source, source1);    }}

测试一下吧

编写咱们的测试类

package com.maple.demo.controller;import com.alibaba.fastjson.JSON;import com.maple.demo.util.RedisUtil;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;/** * @author 笑小枫 * @date 2022/7/20 */@Slf4j@RestController@AllArgsConstructor@RequestMapping("/example")@Api(tags = "实例演示-Redis接口文档")public class TestRedisController {    private final RedisUtil redisUtil;    @PutMapping("/insertStr")    @ApiOperation(value = "插入String类型的数据到redis")    public void insertStr(String key, String value) {        redisUtil.set(key, value);    }    @PostMapping("/getStr")    @ApiOperation(value = "依据key获取redis的数据")    public String getStr(String key) {        return String.valueOf(redisUtil.get(key));    }    @DeleteMapping("/deleteStr")    @ApiOperation(value = "依据key删除redis的数据")    public Boolean deleteStr(String key) {        redisUtil.remove(key);        return redisUtil.exists(key);    }    @PostMapping("/operateMap")    @ApiOperation(value = "模仿操作Map汇合的数据")    public Object operateMap() {        redisUtil.hmSet("maple:map", "xiaofeng", "笑小枫");        return redisUtil.hmGet("maple:map", "xiaofeng");    }    @PostMapping("/operateList")    @ApiOperation(value = "模仿操作List汇合的数据")    public String operateList() {        String listKey = "maple:list";        redisUtil.lPush(listKey, "小枫");        redisUtil.lPush(listKey, "小明");        redisUtil.lPush(listKey, "小枫");        return JSON.toJSONString(redisUtil.lRange(listKey, 0, 2));    }    @PostMapping("/operateSet")    @ApiOperation(value = "模仿操作Set汇合的数据")    public String operateSet() {        String listKey = "maple:set";        redisUtil.addSet(listKey, "小枫");        redisUtil.addSet(listKey, "小明");        redisUtil.addSet(listKey, "小枫");        log.info("汇合中是否蕴含小枫" + redisUtil.isMember(listKey, "小枫"));        log.info("汇合中是否蕴含小红" + redisUtil.isMember(listKey, "小红"));        return JSON.toJSONString(redisUtil.setMembers(listKey));    }    @PostMapping("/operateZSet")    @ApiOperation(value = "模仿操作ZSet有序汇合的数据")    public String operateZSet() {        String listKey = "maple:zSet";        redisUtil.zAdd(listKey, "小枫", 8);        redisUtil.zAdd(listKey, "小明", 1);        redisUtil.zAdd(listKey, "小红", 12);        redisUtil.zAdd(listKey, "大明", 5);        redisUtil.zAdd(listKey, "唐三", 10);        redisUtil.zAdd(listKey, "小舞", 9);        // 降序获取source最高的5条数据        return JSON.toJSONString(redisUtil.reverseRange(listKey, 0L, 4L));    }}

具体的返回后果我就不一一贴图了,本人建站,流量和网速永远都是一大诟病(哭穷)

简略贴两张吧,怕你们说我搪塞

  • 模仿操作List汇合的数据

  • 模仿操作ZSet有序汇合的数据

监听redis Key过期的事件

  • 开始redis过期Key的监听事件
如果数据要求比拟谨严,请慎用此性能

批改redis.conf配置为文件,我用的Redis3.2版本(比拟古老了),windows下是redis.windows-service.conf文件

看一下notify-keyspace-events Ex是否被正文(默认是正文),放开正文即可。

K:keyspace事件,事件以__keyspace@<db>__为前缀进行公布;        E:keyevent事件,事件以__keyevent@<db>__为前缀进行公布;        g:一般性的,非特定类型的命令,比方del,expire,rename等;       $:字符串特定命令;        l:列表特定命令;        s:汇合特定命令;        h:哈希特定命令;        z:有序汇合特定命令;        x:过期事件,当某个键过期并删除时会产生该事件;        e:驱赶事件,当某个键因maxmemore策略而被删除时,产生该事件;        A:g$lshzxe的别名,因而”AKE”意味着所有事件。
  • 批改咱们的RedisConfig.java文件,增加开启监听redis Key过期事件,残缺配置如下
package com.maple.demo.config;import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.boot.autoconfigure.data.redis.RedisProperties;import org.springframework.boot.context.properties.EnableConfigurationProperties;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.RedisOperations;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.listener.RedisMessageListenerContainer;import org.springframework.data.redis.serializer.StringRedisSerializer;/** * @author 笑小枫 * @date 2022/07/19 **/@Configuration@ConditionalOnClass(RedisOperations.class)@EnableConfigurationProperties(RedisProperties.class)public class RedisConfig {    @Bean    @ConditionalOnMissingBean(name = "redisTemplate")    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {        RedisTemplate<Object, Object> template = new RedisTemplate<>();        //应用fastjson序列化        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);        // value值的序列化采纳fastJsonRedisSerializer        template.setValueSerializer(fastJsonRedisSerializer);        template.setHashValueSerializer(fastJsonRedisSerializer);        // key的序列化采纳StringRedisSerializer        template.setKeySerializer(new StringRedisSerializer());        template.setHashKeySerializer(new StringRedisSerializer());        template.setConnectionFactory(redisConnectionFactory);        return template;    }    @Bean    @ConditionalOnMissingBean(StringRedisTemplate.class)    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {        StringRedisTemplate template = new StringRedisTemplate();        template.setConnectionFactory(redisConnectionFactory);        return template;    }    /**     * 开启监听redis Key过期事件     */    @Bean    public RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory){        RedisMessageListenerContainer container = new RedisMessageListenerContainer();        container.setConnectionFactory(connectionFactory);        return container;    }}
  • 定义监听器RedisKeyExpireListener
package com.maple.demo.listener;import lombok.extern.slf4j.Slf4j;import org.springframework.data.redis.connection.Message;import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;import org.springframework.data.redis.listener.RedisMessageListenerContainer;import org.springframework.stereotype.Component;/** * Redis监听key过期 * * @author 笑小枫 * @date 2022/07/19 **/@Slf4j@Componentpublic class RedisKeyExpireListener extends KeyExpirationEventMessageListener {    public RedisKeyExpireListener(RedisMessageListenerContainer listenerContainer) {        super(listenerContainer);    }    @Override    public void onMessage(Message message, byte[] pattern) {        String expireKey = message.toString();        // 依据过期的key解决对应的业务逻辑        log.info(expireKey + "已过期-------------------");    }}

小结

好啦,本文就到这里了,咱们简略的总结一下,次要介绍了以下内容

  • 本文外围:SpringBoot继承redis
  • SpringBoot罕用的redis操作演示
  • 监听Redis的key过期机制

对于笑小枫

本章到这里完结了,喜爱的敌人关注一下我呦,大伙的反对,就是我保持写下去的能源。
老规矩,懂了就点赞珍藏;不懂就问,日常在线,我会就会回复哈~
微信公众号:笑小枫
笑小枫集体博客:https://www.xiaoxiaofeng.com
CSDN:https://zhangfz.blog.csdn.net
本文源码:https://github.com/hack-feng/maple-demo