redis可以用于消息订阅,下面一段代码实现了spring中使用redis作为消息订阅模型:
消息处理器:
Java
/**
* 接口RedisMessageHandler:
*/
public interface RedisMessageHandler {
/**
* 处理redis消息
* @param message redis消息
* @return 处理结果
*/
String handlerRedisMessage(TMRedisMessage message);
}
实现消息处理:
java
@Service
@Slf4j
public class ClusterMessageHandler implements RedisMessageHandler {
@Override
public String handlerRedisMessage(TMRedisMessage tmRedisMessage) {
log.info("收到消息通知,消息内容:{}", tmRedisMessage);
// 设置JWT信息
JwtUtil.setJwtInfo(String.valueOf(tmRedisMessage.getAppId()), tmRedisMessage.getUin());
// 构造集群组件创建/卸载请求
var clusterRequest = new ClusterRequest();
clusterRequest.setClusterId(tmRedisMessage.getClusterId());
ClusterFactory.get(ClusterTypeEnum.COMMON.getName()).create(clusterRequest);
JwtUtil.removeJwtInfo();
return "success";
}
}
消息消费者:
java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tencent.tbds.tm.platform.server.message.RedisMessageHandler;
import com.tencent.tbds.tm.platform.server.message.pojo.TMRedisMessage;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* 类RedisConsumer:
*/
@Component
@Slf4j
public class RedisConsumer implements MessageListener {
@Resource
private RedisTemplate<String, Object> redisTemplate;
private final Map<String, RedisMessageHandler> redisMessageHandlerMap;
public RedisConsumer(ConfigurableApplicationContext context) {
this.redisMessageHandlerMap = context.getBeansOfType(RedisMessageHandler.class);
}
@Override
public void onMessage(Message message, byte[] bytes) {
try {
var channel = new String(message.getChannel());
var body = new String(message.getBody());
log.info("Received Redis message: {} from channel: {}", body, channel);
var tmRedisMessage = new ObjectMapper().readValue(body, TMRedisMessage.class);
var isSet = redisTemplate.opsForValue().setIfAbsent(tmRedisMessage.getClusterType() + tmRedisMessage.getEventsType(), "1", 5, TimeUnit.SECONDS);
if (isSet != null && isSet) {
for (var redisMessageHandler : redisMessageHandlerMap.values()) {
messageErrorHandler(redisMessageHandler, tmRedisMessage);
}
}
} catch (Exception e) {
log.error("Received Redis Message From Tm Error! ", e);
}
}
/**
* 消息处理错误处理
* @param redisMessageHandler 请求处理类
* @param tmRedisMessage 消息体
*/
private void messageErrorHandler(RedisMessageHandler redisMessageHandler, TMRedisMessage tmRedisMessage) {
var errMessage = "";
try {
var handlerClass = redisMessageHandler.getClass();
var annotation = handlerClass.getAnnotation(MessageHandler.class);
var clusterType = annotation.ClusterType();
var eventsType = annotation.EventsType();
if (clusterType.length == 0 && eventsType.length == 0) {
log.info("{} Handler all Redis Message", handlerClass.getName());
errMessage = redisMessageHandler.handlerRedisMessage(tmRedisMessage);
} else {
var clusterTypeList = Arrays.stream(clusterType)
.boxed()
.toList();
var eventsTypes = Arrays.asList(eventsType);
if (clusterTypeList.contains(tmRedisMessage.getClusterType()) &&
eventsTypes.contains(tmRedisMessage.getEventsType())) {
log.info("Invoke RedisMessageHandler to handler Message: {}", handlerClass.getName());
errMessage = redisMessageHandler.handlerRedisMessage(tmRedisMessage);
}
}
} catch (Exception e) {
errMessage = e.getMessage();
}
log.info("Redis message handler result is {}", errMessage);
}
}