一、依赖
1.1 pom
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.21.1</version>
</dependency>
1.2 yml
spring:
redis:
host: 127.0.0.1
port: 13678
database: 0
password: 123456
redisson:
singleServerConfig:
address: "redis://${spring.redis.host}:${spring.redis.port}"
password: "${spring.redis.password}"
database: "${spring.redis.database}"
二、RedissonConfig 配置类
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RedissonConfig {
public static final String DELAY_NAME = "warning-record";
@Value("${redisson.singleServerConfig.address}")
private String address;
@Value("${redisson.singleServerConfig.password}")
private String password;
@Value("${redisson.singleServerConfig.database}")
private int database;
@Bean(destroyMethod = "shutdown")
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer().setAddress(address).setDatabase(database).setPassword(password);
return Redisson.create(config);
}
}
三、RedisDelayQueueUtil 工具类
import com.ccbx.rmbmanage.common.exception.BusinessException;
import com.ccbx.rmbmanage.config.RedissonConfig;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class RedisDelayQueueUtil {
public static final String DELAY_NAME = "warning-record";
@Resource
private RedissonConfig redissonConfig;
public <T> void addDelayQueue(T value, long delay, TimeUnit timeUnit, String queueCode) {
if (!StringUtils.hasText(queueCode)) {
queueCode = DELAY_NAME;
}
try {
RedissonClient redissonClient = redissonConfig.redissonClient();
RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(queueCode);
RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
delayedQueue.offer(value, delay, timeUnit);
log.info("(添加延时队列成功) 队列键:{},队列值:{},延迟时间:{}", queueCode, value, timeUnit.toSeconds(delay) + "秒");
} catch (Exception e) {
log.error("(添加延时队列失败) {}", e.getMessage());
throw new BusinessException("(添加延时队列失败)");
}
}
public <T> T getDelayQueue(String queueCode) throws InterruptedException {
if (!StringUtils.hasText(queueCode)) {
queueCode = DELAY_NAME;
}
RBlockingDeque<Map> blockingDeque = redissonConfig.redissonClient().getBlockingDeque(queueCode);
return (T) blockingDeque.take();
}
public <T> T removeDelayQueue(T value, String queueCode) {
if (!StringUtils.hasText(queueCode)) {
queueCode = DELAY_NAME;
}
RBlockingDeque<Object> blockingDeque = redissonConfig.redissonClient().getBlockingDeque(queueCode);
RDelayedQueue<Object> delayedQueue = redissonConfig.redissonClient().getDelayedQueue(blockingDeque);
delayedQueue.remove(value);
return value;
}
@PostConstruct
public void reScheduleDelayedTasks() {
removeDelayQueue(null, null);
}
}
四、RedisDelayQueueRunner 消费者
import com.ccbx.rmbmanage.domain.redisson.BicycleState;
import com.ccbx.rmbmanage.utils.RedisDelayQueueUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Slf4j
@Component
public class RedisDelayQueueRunner implements CommandLineRunner {
@Resource
private RedisDelayQueueUtil redisDelayQueueUtil;
@Override
public void run(String... args) throws Exception {
new Thread(() -> {
try {
while (true) {
BicycleState value = redisDelayQueueUtil.getDelayQueue(RedisDelayQueueUtil.DELAY_NAME);
consumerMessage(value);
}
}catch (InterruptedException e) {
log.error("Redis 延迟队列消费监听器异常中断,{}", e.getMessage());
}
}).start();
log.info("Redis 延迟队列消费监听器启动成功");
}
private void consumerMessage(BicycleState bicycleState) {
log.warn("收到延迟消息进行处理,消息内容:{}", bicycleState);
}
}
五、消息生产者
package com.ccbx.rmbmanage.controller.redisson;
import cn.hutool.core.lang.UUID;
import com.ccbx.rmbmanage.common.ApiResp;
import com.ccbx.rmbmanage.domain.redisson.BicycleState;
import com.ccbx.rmbmanage.utils.RedisDelayQueueUtil;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("redisson")
public class RedissonController {
@Resource
private RedisDelayQueueUtil redisDelayQueueUtil;
@PostMapping("create")
public ApiResp<List<BicycleState>> createDelayMsg() {
List<BicycleState> rltList = new ArrayList<>(5);
for (int i = 0; i < 5; i++) {
BicycleState bicycleState = new BicycleState();
bicycleState.setBicycleSerialNumber(UUID.randomUUID().toString(true));
bicycleState.setTerminalSerialNumber(UUID.randomUUID().toString(true));
bicycleState.setState(i%2 == 0);
redisDelayQueueUtil.addDelayQueue(bicycleState, 1, TimeUnit.MINUTES, null);
rltList.add(bicycleState);
}
return ApiResp.success(rltList);
}
}