|
|
@@ -1,29 +1,18 @@
|
|
|
package com.nb.common.websocket.handler;
|
|
|
|
|
|
import cn.hutool.core.collection.CollectionUtil;
|
|
|
-import cn.hutool.core.util.StrUtil;
|
|
|
-import cn.hutool.extra.spring.SpringUtil;
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
import com.nb.auth.bean.LoginUser;
|
|
|
import com.nb.common.websocket.*;
|
|
|
-import com.nb.common.websocket.event.PubMsgEvent;
|
|
|
-import com.nb.common.websocket.filter.PubMsgFilter;
|
|
|
+import com.nb.common.websocket.msg.handler.IMsgRequestHandler;
|
|
|
+import com.nb.common.websocket.msg.MessagingRequest;
|
|
|
+import com.nb.common.websocket.msg.handler.MsgRequestHandlerManager;
|
|
|
import com.nb.core.Constants;
|
|
|
-import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
-import com.nb.core.result.R;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.tomcat.util.descriptor.web.WebXml;
|
|
|
-import org.redisson.api.RPatternTopic;
|
|
|
-import org.redisson.api.RTopic;
|
|
|
-import org.redisson.api.RedissonClient;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.tio.core.ChannelContext;
|
|
|
-import org.tio.core.Tio;
|
|
|
-import org.tio.websocket.common.WsPacket;
|
|
|
-import org.tio.websocket.common.WsResponse;
|
|
|
|
|
|
import java.util.*;
|
|
|
-import java.util.concurrent.ConcurrentHashMap;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -35,23 +24,9 @@ import java.util.stream.Collectors;
|
|
|
*/
|
|
|
@Slf4j
|
|
|
public abstract class Subscribe implements WsHandler {
|
|
|
- @Autowired
|
|
|
- private ObjectMapper objectMapper;
|
|
|
|
|
|
@Autowired
|
|
|
- private RedissonClient redissonClient;
|
|
|
-
|
|
|
- @Autowired(required = false)
|
|
|
- private List<PubMsgFilter> msgFilters;
|
|
|
- /**
|
|
|
- * 订阅主题缓存
|
|
|
- */
|
|
|
- private static Map<String, RPatternTopic> subTopicMap =new ConcurrentHashMap<>();
|
|
|
-
|
|
|
- /**
|
|
|
- * 发布主题缓存
|
|
|
- */
|
|
|
- private static Map<String, RTopic> pubTopicMap =new ConcurrentHashMap<>();
|
|
|
+ private MsgRequestHandlerManager requestHandlerManager;
|
|
|
|
|
|
public TopicWrapper getTopic(String productName,String param,String tenantId){
|
|
|
return WebSocketConstant.getTopic(this.getId(),productName, param, tenantId);
|
|
|
@@ -81,118 +56,12 @@ public abstract class Subscribe implements WsHandler {
|
|
|
else {
|
|
|
subScribeTopic = Collections.singletonList(getTopic(message.getProductName(), null, message.getTenantId()));
|
|
|
}
|
|
|
-
|
|
|
- MessagingRequest.Type type = message.getType();
|
|
|
- if(MessagingRequest.Type.sub.equals(type)){
|
|
|
- //订阅主题
|
|
|
- subScribeTopic.forEach(topicWrapper->this.subscribe(channelContext,topicWrapper));
|
|
|
- }else if(MessagingRequest.Type.unsub.equals(type)){
|
|
|
- //取消订阅主题
|
|
|
- subScribeTopic.forEach(topicWrapper->this.unsubscribe(channelContext,topicWrapper.getTopic()));
|
|
|
- }else {
|
|
|
- subScribeTopic.forEach(topicWrapper->this.publish(channelContext,message,topicWrapper.getTopic(),topicWrapper.getParam()));
|
|
|
+ IMsgRequestHandler handle = requestHandlerManager.getHandle(message.getType());
|
|
|
+ if(handle!=null){
|
|
|
+ subScribeTopic.forEach(topicWrapper->handle.handler(message,channelContext,topicWrapper));
|
|
|
}
|
|
|
if(log.isDebugEnabled()){
|
|
|
log.debug("ws数据处理成功{}", JSONUtil.toJsonStr(message));
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * 描述: 推送主题
|
|
|
- * @author lifang
|
|
|
- * @date 2022/8/16 14:04
|
|
|
- * @param channelContext 发布推送消息的通道
|
|
|
- * @param message
|
|
|
- * @param topic
|
|
|
- * @param param
|
|
|
- * @return void
|
|
|
- */
|
|
|
- private void publish(ChannelContext channelContext, MessagingRequest message, String topic, String param) {
|
|
|
- if(CollectionUtil.isNotEmpty(msgFilters)){
|
|
|
- boolean result = msgFilters.stream()
|
|
|
- .allMatch(filter -> filter.doFilter(channelContext, message));
|
|
|
- if(result){
|
|
|
- SpringUtil.publishEvent(new PubMsgEvent(this,message));
|
|
|
- pubTopicMap.computeIfAbsent(topic, k->redissonClient.getTopic(k))
|
|
|
- .publishAsync( TopicMessage.of(message.getPayload(),param,message.getMsgId()))
|
|
|
- .whenComplete((r,e)->{
|
|
|
- Tio.send(channelContext, WsResponse.fromText(JSONUtil.toJsonStr(PubResponse.success(message.getMsgId())), WsPacket.CHARSET_NAME));
|
|
|
- });
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * ws 订阅主题
|
|
|
- * @param channelContext
|
|
|
- * @param topicWrapper
|
|
|
- */
|
|
|
- public void subscribe(ChannelContext channelContext, TopicWrapper topicWrapper){
|
|
|
- getChannelTopic(channelContext).add(topicWrapper.getTopic());
|
|
|
- //同一主题只订阅一次
|
|
|
- RPatternTopic rTopic = subTopicMap.computeIfAbsent(topicWrapper.getTopic(), topic->redissonClient.getPatternTopic(topicWrapper.getTopic()));
|
|
|
- addTopicListener(rTopic,channelContext, topicWrapper.getTopic());
|
|
|
- };
|
|
|
-
|
|
|
- /**
|
|
|
- * ws取消订阅主题
|
|
|
- * @param channelContext
|
|
|
- * @param topic
|
|
|
- */
|
|
|
- public void unsubscribe(ChannelContext channelContext, String topic){
|
|
|
- if(StrUtil.isEmpty(topic)){
|
|
|
- return;
|
|
|
- }
|
|
|
- Set<String> allTopics=new HashSet<>();
|
|
|
-
|
|
|
- if(topic.startsWith("all")){
|
|
|
- allTopics.addAll(getChannelTopic(channelContext));
|
|
|
- }
|
|
|
-
|
|
|
- //取消订阅
|
|
|
- for (String subTopic : allTopics) {
|
|
|
- subTopicMap.computeIfPresent(subTopic,(k, rTopic)->{
|
|
|
- rTopic.removeListener( getTopicListener(channelContext,k));
|
|
|
- return rTopic;
|
|
|
- });
|
|
|
- Map<String, DefaultMessageListener> topicListeners = getTopicListeners(channelContext);
|
|
|
- topicListeners.remove(subTopic);
|
|
|
- }
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
-
|
|
|
- public Map<String,DefaultMessageListener> getTopicListeners(ChannelContext channelContext){
|
|
|
- Object result = Optional.ofNullable(channelContext.get("topic")).orElse(new HashMap<String,DefaultMessageListener>());
|
|
|
- channelContext.set("topic",result);
|
|
|
- return (Map<String,DefaultMessageListener>) result;
|
|
|
- }
|
|
|
-
|
|
|
- public DefaultMessageListener getTopicListener(ChannelContext channelContext,String topic){
|
|
|
- Map<String,DefaultMessageListener> result = (Map<String, DefaultMessageListener>) Optional.ofNullable(channelContext.get("topic")).orElse(new HashMap<>());
|
|
|
- return result.get(topic);
|
|
|
- }
|
|
|
-
|
|
|
- public DefaultMessageListener addTopicListener(RPatternTopic rTopic,ChannelContext channelContext,String topic){
|
|
|
- Map<String, DefaultMessageListener> topicByChannel = getTopicListeners(channelContext);
|
|
|
- DefaultMessageListener messageListener = topicByChannel.computeIfAbsent(topic, k -> {
|
|
|
- DefaultMessageListener defaultMessageListener = new DefaultMessageListener(getId(), objectMapper, channelContext,rTopic);
|
|
|
- rTopic.addListenerAsync(TopicMessage.class, defaultMessageListener);
|
|
|
- return defaultMessageListener;
|
|
|
- });
|
|
|
- return messageListener;
|
|
|
- }
|
|
|
-
|
|
|
- private Set<String> getChannelTopic(ChannelContext channelContext){
|
|
|
- Set<String> topics=null;
|
|
|
- Object topicSet = channelContext.getAttribute("subtopic");
|
|
|
- if(topicSet==null){
|
|
|
- topics=new HashSet<>();
|
|
|
- }else {
|
|
|
- topics= (Set<String>) topicSet;
|
|
|
- }
|
|
|
- channelContext.setAttribute("subtopic",topics);
|
|
|
- return topics;
|
|
|
- }
|
|
|
}
|