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