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
*/
@Component
public 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
@Component
public 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