21 changed files with 359 additions and 42 deletions
@ -0,0 +1,43 @@ |
|||
package com.bx.imclient.task; |
|||
|
|||
import cn.hutool.core.util.StrUtil; |
|||
import com.alibaba.fastjson.JSONObject; |
|||
import com.bx.imclient.listener.MessageListenerMulticaster; |
|||
import com.bx.imcommon.contant.IMRedisKey; |
|||
import com.bx.imcommon.enums.IMListenerType; |
|||
import com.bx.imcommon.model.IMSendResult; |
|||
import com.bx.imcommon.mq.RedisMQConsumer; |
|||
import com.bx.imcommon.mq.RedisMQListener; |
|||
import com.bx.imcommon.mq.RedisMQTemplate; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.LinkedList; |
|||
import java.util.List; |
|||
import java.util.Objects; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
@RequiredArgsConstructor |
|||
@RedisMQListener(queue = IMRedisKey.IM_RESULT_SYSTEM_QUEUE, batchSize = 100, period = 100) |
|||
public class SystemMessageResultResultTask extends RedisMQConsumer<IMSendResult> { |
|||
|
|||
@Value("${spring.application.name}") |
|||
private String appName; |
|||
|
|||
private final MessageListenerMulticaster listenerMulticaster; |
|||
|
|||
@Override |
|||
public void onMessage(List<IMSendResult> results) { |
|||
listenerMulticaster.multicast(IMListenerType.SYSTEM_MESSAGE, results); |
|||
} |
|||
|
|||
@Override |
|||
public String generateKey() { |
|||
return StrUtil.join(":", IMRedisKey.IM_RESULT_SYSTEM_QUEUE, appName); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
package com.bx.imcommon.model; |
|||
|
|||
import com.bx.imcommon.enums.IMTerminalType; |
|||
import lombok.Data; |
|||
|
|||
import java.util.LinkedList; |
|||
import java.util.List; |
|||
|
|||
@Data |
|||
public class IMSystemMessage<T> { |
|||
|
|||
|
|||
/** |
|||
* 接收者id列表,为空表示向所有在线用户广播 |
|||
*/ |
|||
private List<Long> recvIds = new LinkedList<>(); |
|||
|
|||
/** |
|||
* 接收者终端类型,默认全部 |
|||
*/ |
|||
private List<Integer> recvTerminals = IMTerminalType.codes(); |
|||
|
|||
/** |
|||
* 是否需要回推发送结果,默认true |
|||
*/ |
|||
private Boolean sendResult = true; |
|||
|
|||
/** |
|||
* 消息内容 |
|||
*/ |
|||
private T data; |
|||
|
|||
|
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
package com.bx.implatform.listener; |
|||
|
|||
import cn.hutool.core.collection.CollUtil; |
|||
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; |
|||
import com.bx.imclient.annotation.IMListener; |
|||
import com.bx.imclient.listener.MessageListener; |
|||
import com.bx.imcommon.enums.IMListenerType; |
|||
import com.bx.imcommon.enums.IMSendCode; |
|||
import com.bx.imcommon.model.IMSendResult; |
|||
import com.bx.implatform.entity.PrivateMessage; |
|||
import com.bx.implatform.enums.MessageStatus; |
|||
import com.bx.implatform.service.IPrivateMessageService; |
|||
import com.bx.implatform.vo.PrivateMessageVO; |
|||
import com.bx.implatform.vo.SystemMessageVO; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.context.annotation.Lazy; |
|||
|
|||
import java.util.HashSet; |
|||
import java.util.List; |
|||
import java.util.Set; |
|||
|
|||
@Slf4j |
|||
@IMListener(type = IMListenerType.SYSTEM_MESSAGE) |
|||
public class SystemMessageListener implements MessageListener<SystemMessageVO> { |
|||
|
|||
@Override |
|||
public void process(List<IMSendResult<SystemMessageVO>> results) { |
|||
for(IMSendResult<SystemMessageVO> result : results){ |
|||
SystemMessageVO messageInfo = result.getData(); |
|||
if (result.getCode().equals(IMSendCode.SUCCESS.code())) { |
|||
log.info("消息送达,消息id:{},接收者:{},终端:{}", messageInfo.getId(), result.getReceiver().getId(), result.getReceiver().getTerminal()); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
package com.bx.implatform.vo; |
|||
|
|||
import com.bx.imcommon.serializer.DateToLongSerializer; |
|||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; |
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
import java.util.Date; |
|||
|
|||
@Data |
|||
@ApiModel("系统消息VO") |
|||
public class SystemMessageVO { |
|||
|
|||
@ApiModelProperty(value = " 消息id") |
|||
private Long id; |
|||
|
|||
@ApiModelProperty(value = " 发送内容") |
|||
private String content; |
|||
|
|||
@ApiModelProperty(value = "消息内容类型 MessageType") |
|||
private Integer type; |
|||
|
|||
@ApiModelProperty(value = " 发送时间") |
|||
@JsonSerialize(using = DateToLongSerializer.class) |
|||
private Date sendTime; |
|||
} |
|||
@ -0,0 +1,65 @@ |
|||
package com.bx.imserver.netty.processor; |
|||
|
|||
import cn.hutool.core.util.StrUtil; |
|||
import com.bx.imcommon.contant.IMRedisKey; |
|||
import com.bx.imcommon.enums.IMCmdType; |
|||
import com.bx.imcommon.enums.IMSendCode; |
|||
import com.bx.imcommon.model.IMRecvInfo; |
|||
import com.bx.imcommon.model.IMSendInfo; |
|||
import com.bx.imcommon.model.IMSendResult; |
|||
import com.bx.imcommon.model.IMUserInfo; |
|||
import com.bx.imserver.netty.UserChannelCtxMap; |
|||
import io.netty.channel.ChannelHandlerContext; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.data.redis.core.RedisTemplate; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.util.Objects; |
|||
|
|||
@Slf4j |
|||
@Component |
|||
@RequiredArgsConstructor |
|||
public class SystemMessageProcessor extends AbstractMessageProcessor<IMRecvInfo> { |
|||
|
|||
private final RedisTemplate<String, Object> redisTemplate; |
|||
|
|||
@Override |
|||
public void process(IMRecvInfo recvInfo) { |
|||
IMUserInfo receiver = recvInfo.getReceivers().get(0); |
|||
log.info("接收到系统消息,接收者:{},内容:{}", receiver.getId(), recvInfo.getData()); |
|||
try { |
|||
ChannelHandlerContext channelCtx = UserChannelCtxMap.getChannelCtx(receiver.getId(), receiver.getTerminal()); |
|||
if (!Objects.isNull(channelCtx)) { |
|||
// 推送消息到用户
|
|||
IMSendInfo<Object> sendInfo = new IMSendInfo<>(); |
|||
sendInfo.setCmd(IMCmdType.SYSTEM_MESSAGE.code()); |
|||
sendInfo.setData(recvInfo.getData()); |
|||
channelCtx.channel().writeAndFlush(sendInfo); |
|||
// 消息发送成功确认
|
|||
sendResult(recvInfo, IMSendCode.SUCCESS); |
|||
} else { |
|||
// 消息推送失败确认
|
|||
sendResult(recvInfo, IMSendCode.NOT_FIND_CHANNEL); |
|||
log.error("未找到channel,接收者:{},内容:{}",receiver.getId(), recvInfo.getData()); |
|||
} |
|||
} catch (Exception e) { |
|||
// 消息推送失败确认
|
|||
sendResult(recvInfo, IMSendCode.UNKONW_ERROR); |
|||
log.error("发送异常,,接收者:{},内容:{}", receiver.getId(), recvInfo.getData(), e); |
|||
} |
|||
|
|||
} |
|||
|
|||
private void sendResult(IMRecvInfo recvInfo, IMSendCode sendCode) { |
|||
if (recvInfo.getSendResult()) { |
|||
IMSendResult<Object> result = new IMSendResult<>(); |
|||
result.setReceiver(recvInfo.getReceivers().get(0)); |
|||
result.setCode(sendCode.code()); |
|||
result.setData(recvInfo.getData()); |
|||
// 推送到结果队列
|
|||
String key = StrUtil.join(":",IMRedisKey.IM_RESULT_SYSTEM_QUEUE,recvInfo.getServiceName()); |
|||
redisTemplate.opsForList().rightPush(key, result); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
package com.bx.imserver.task; |
|||
|
|||
import com.bx.imcommon.contant.IMRedisKey; |
|||
import com.bx.imcommon.enums.IMCmdType; |
|||
import com.bx.imcommon.model.IMRecvInfo; |
|||
import com.bx.imcommon.mq.RedisMQConsumer; |
|||
import com.bx.imcommon.mq.RedisMQListener; |
|||
import com.bx.imserver.netty.IMServerGroup; |
|||
import com.bx.imserver.netty.processor.AbstractMessageProcessor; |
|||
import com.bx.imserver.netty.processor.ProcessorFactory; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
/** |
|||
* @author: 谢绍许 |
|||
* @date: 2024-07-16 |
|||
* @version: 1.0 |
|||
*/ |
|||
@Slf4j |
|||
@Component |
|||
@RedisMQListener(queue = IMRedisKey.IM_MESSAGE_SYSTEM_QUEUE,batchSize = 10) |
|||
public class PullSystemMessageTask extends RedisMQConsumer<IMRecvInfo> { |
|||
|
|||
@Override |
|||
public void onMessage(IMRecvInfo recvInfo) { |
|||
AbstractMessageProcessor processor = ProcessorFactory.createProcessor(IMCmdType.SYSTEM_MESSAGE); |
|||
processor.process(recvInfo); |
|||
} |
|||
|
|||
public String generateKey(){ |
|||
// 队列名:im:message:system:{服务id}
|
|||
return String.join(":", IMRedisKey.IM_MESSAGE_SYSTEM_QUEUE, IMServerGroup.serverId + ""); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue