Browse Source

!42 合并

Merge pull request !42 from blue/v_2.0.0
master
blue 2 years ago
committed by Gitee
parent
commit
9868a710c8
No known key found for this signature in database GPG Key ID: 173E9B9CA92EEF8F
  1. 1
      im-client/src/main/java/com/bx/imclient/IMAutoConfiguration.java
  2. 4
      im-client/src/main/java/com/bx/imclient/listener/MessageListener.java
  3. 24
      im-client/src/main/java/com/bx/imclient/listener/MessageListenerMulticaster.java
  4. 44
      im-client/src/main/java/com/bx/imclient/sender/IMSender.java
  5. 16
      im-client/src/main/java/com/bx/imclient/task/AbstractMessageResultTask.java
  6. 41
      im-client/src/main/java/com/bx/imclient/task/GroupMessageResultResultTask.java
  7. 43
      im-client/src/main/java/com/bx/imclient/task/PrivateMessageResultResultTask.java
  8. 4
      im-commom/src/main/java/com/bx/imcommon/model/IMRecvInfo.java
  9. 13
      im-platform/src/main/java/com/bx/implatform/listener/GroupMessageListener.java
  10. 24
      im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java
  11. 32
      im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java
  12. 1
      im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java
  13. 2
      im-platform/src/main/resources/application.yml
  14. 4
      im-server/src/main/java/com/bx/imserver/netty/processor/GroupMessageProcessor.java
  15. 3
      im-server/src/main/java/com/bx/imserver/netty/processor/PrivateMessageProcessor.java
  16. 4
      im-server/src/main/java/com/bx/imserver/task/AbstractPullMessageTask.java
  17. 8
      im-server/src/main/java/com/bx/imserver/task/PullGroupMessageTask.java
  18. 15
      im-server/src/main/java/com/bx/imserver/task/PullPrivateMessageTask.java
  19. 2
      im-ui/src/api/date.js
  20. 1
      im-ui/src/components/chat/ChatBox.vue
  21. 2
      im-uniapp/common/date.js
  22. 2
      im-uniapp/components/chat-item/chat-item.vue

1
im-client/src/main/java/com/bx/imclient/IMAutoConfiguration.java

@ -9,4 +9,5 @@ import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.bx.imclient")
public class IMAutoConfiguration {
}

4
im-client/src/main/java/com/bx/imclient/listener/MessageListener.java

@ -3,8 +3,10 @@ package com.bx.imclient.listener;
import com.bx.imcommon.model.IMSendResult;
import java.util.List;
public interface MessageListener<T> {
void process(IMSendResult<T> result);
void process(List<IMSendResult<T>> result);
}

24
im-client/src/main/java/com/bx/imclient/listener/MessageListenerMulticaster.java

@ -1,6 +1,7 @@
package com.bx.imclient.listener;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.bx.imclient.annotation.IMListener;
import com.bx.imcommon.enums.IMListenerType;
@ -19,19 +20,24 @@ public class MessageListenerMulticaster {
@Autowired(required = false)
private List<MessageListener> messageListeners = Collections.emptyList();
public void multicast(IMListenerType listenerType, IMSendResult result){
public void multicast(IMListenerType listenerType, List<IMSendResult> results){
if(CollUtil.isEmpty(results)){
return;
}
for(MessageListener listener:messageListeners){
IMListener annotation = listener.getClass().getAnnotation(IMListener.class);
if(annotation!=null && (annotation.type().equals(IMListenerType.ALL) || annotation.type().equals(listenerType))){
// 将data转回对象类型
if(result.getData() instanceof JSONObject){
Type superClass = listener.getClass().getGenericInterfaces()[0];
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
JSONObject data = (JSONObject)result.getData();
result.setData(data.toJavaObject(type));
}
results.forEach(result->{
// 将data转回对象类型
if(result.getData() instanceof JSONObject){
Type superClass = listener.getClass().getGenericInterfaces()[0];
Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
JSONObject data = (JSONObject)result.getData();
result.setData(data.toJavaObject(type));
}
});
// 回调到调用方处理
listener.process(result);
listener.process(results);
}
}
}

44
im-client/src/main/java/com/bx/imclient/sender/IMSender.java

@ -9,6 +9,7 @@ import com.bx.imcommon.enums.IMSendCode;
import com.bx.imcommon.enums.IMTerminalType;
import com.bx.imcommon.model.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@ -22,9 +23,13 @@ public class IMSender {
@Resource(name="IMRedisTemplate")
private RedisTemplate<String, Object> redisTemplate;
@Value("${spring.application.name}")
private String appName;
private final MessageListenerMulticaster listenerMulticaster;
public<T> void sendPrivateMessage(IMPrivateMessage<T> message) {
List<IMSendResult> results = new LinkedList<>();
for (Integer terminal : message.getRecvTerminals()) {
// 获取对方连接的channelId
String key = String.join(":", IMRedisKey.IM_USER_SERVER_ID, message.getRecvId().toString(), terminal.toString());
@ -35,18 +40,18 @@ public class IMSender {
IMRecvInfo recvInfo = new IMRecvInfo();
recvInfo.setCmd(IMCmdType.PRIVATE_MESSAGE.code());
recvInfo.setSendResult(message.getSendResult());
recvInfo.setServiceName(appName);
recvInfo.setSender(message.getSender());
recvInfo.setReceivers(Collections.singletonList(new IMUserInfo(message.getRecvId(), terminal)));
recvInfo.setData(message.getData());
redisTemplate.opsForList().rightPush(sendKey, recvInfo);
} else if (message.getSendResult()) {
// 回复消息状态
} else {
IMSendResult result = new IMSendResult();
result.setSender(message.getSender());
result.setReceiver(new IMUserInfo(message.getRecvId(), terminal));
result.setCode(IMSendCode.NOT_ONLINE.code());
result.setData(message.getData());
listenerMulticaster.multicast(IMListenerType.PRIVATE_MESSAGE, result);
results.add(result);
}
}
// 推送给自己的其他终端
@ -72,10 +77,14 @@ public class IMSender {
}
}
}
// 对离线用户回复消息状态
if(message.getSendResult() && !results.isEmpty()){
listenerMulticaster.multicast(IMListenerType.PRIVATE_MESSAGE, results);
}
}
public<T> void sendGroupMessage(IMGroupMessage<T> message) {
// 根据群聊每个成员所连的IM-server,进行分组
Map<String, IMUserInfo> sendMap = new HashMap<>();
for (Integer terminal : message.getRecvTerminals()) {
@ -106,23 +115,14 @@ public class IMSender {
recvInfo.setCmd(IMCmdType.GROUP_MESSAGE.code());
recvInfo.setReceivers(new LinkedList<>(entry.getValue()));
recvInfo.setSender(message.getSender());
recvInfo.setServiceName(appName);
recvInfo.setSendResult(message.getSendResult());
recvInfo.setData(message.getData());
// 推送至队列
String key = String.join(":", IMRedisKey.IM_MESSAGE_GROUP_QUEUE, entry.getKey().toString());
redisTemplate.opsForList().rightPush(key, recvInfo);
}
// 对离线用户回复消息状态
if (message.getSendResult()) {
for (IMUserInfo offLineUser : offLineUsers) {
IMSendResult result = new IMSendResult();
result.setSender(message.getSender());
result.setReceiver(offLineUser);
result.setCode(IMSendCode.NOT_ONLINE.code());
result.setData(message.getData());
listenerMulticaster.multicast(IMListenerType.GROUP_MESSAGE, result);
}
}
// 推送给自己的其他终端
if (message.getSendToSelf()) {
for (Integer terminal : IMTerminalType.codes()) {
@ -146,6 +146,20 @@ public class IMSender {
}
}
}
// 对离线用户回复消息状态
if(message.getSendResult() && !offLineUsers.isEmpty()){
List<IMSendResult> results = new LinkedList<>();
for (IMUserInfo offLineUser : offLineUsers) {
IMSendResult result = new IMSendResult();
result.setSender(message.getSender());
result.setReceiver(offLineUser);
result.setCode(IMSendCode.NOT_ONLINE.code());
result.setData(message.getData());
results.add(result);
}
listenerMulticaster.multicast(IMListenerType.GROUP_MESSAGE, results);
}
}
public Map<Long,List<IMTerminalType>> getOnlineTerminal(List<Long> userIds){

16
im-client/src/main/java/com/bx/imclient/task/AbstractMessageResultTask.java

@ -20,13 +20,13 @@ public abstract class AbstractMessageResultTask implements CommandLineRunner {
@SneakyThrows
@Override
public void run() {
try{
try {
pullMessage();
}catch (Exception e){
log.error("任务调度异常",e);
Thread.sleep(200);
} catch (Exception e) {
log.error("任务调度异常", e);
}
if(!EXECUTOR_SERVICE.isShutdown()){
if (!EXECUTOR_SERVICE.isShutdown()) {
Thread.sleep(100);
EXECUTOR_SERVICE.execute(this);
}
}
@ -35,10 +35,10 @@ public abstract class AbstractMessageResultTask implements CommandLineRunner {
@PreDestroy
public void destroy(){
log.info("{}线程任务关闭",this.getClass().getSimpleName());
public void destroy() {
log.info("{}线程任务关闭", this.getClass().getSimpleName());
EXECUTOR_SERVICE.shutdown();
}
public abstract void pullMessage();
public abstract void pullMessage() throws InterruptedException;
}

41
im-client/src/main/java/com/bx/imclient/task/GroupMessageResultResultTask.java

@ -1,34 +1,59 @@
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 lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
@Component
@AllArgsConstructor
@RequiredArgsConstructor
public class GroupMessageResultResultTask extends AbstractMessageResultTask {
@Resource(name = "IMRedisTemplate")
private RedisTemplate<String,Object> redisTemplate;
@Value("${spring.application.name}")
private String appName;
@Value("${im.result.batch:100}")
private int batchSize;
private final MessageListenerMulticaster listenerMulticaster;
@Override
public void pullMessage() {
String key = IMRedisKey.IM_RESULT_GROUP_QUEUE;
JSONObject jsonObject = (JSONObject)redisTemplate.opsForList().leftPop(key,10, TimeUnit.SECONDS);
if(jsonObject != null) {
IMSendResult result = jsonObject.toJavaObject(IMSendResult.class);
listenerMulticaster.multicast(IMListenerType.GROUP_MESSAGE,result);
List<IMSendResult> results;
do {
results = loadBatch();
if(!results.isEmpty()){
listenerMulticaster.multicast(IMListenerType.GROUP_MESSAGE, results);
}
} while (results.size() >= batchSize);
}
List<IMSendResult> loadBatch() {
String key = StrUtil.join(":", IMRedisKey.IM_RESULT_GROUP_QUEUE, appName);
//这个接口redis6.2以上才支持
//List<Object> list = redisTemplate.opsForList().leftPop(key, batchSize);
List<IMSendResult> results = new LinkedList<>();
JSONObject jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
while (!Objects.isNull(jsonObject) && results.size() < batchSize) {
results.add(jsonObject.toJavaObject(IMSendResult.class));
jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
}
return results;
}
}

43
im-client/src/main/java/com/bx/imclient/task/PrivateMessageResultResultTask.java

@ -1,37 +1,60 @@
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 lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
@Slf4j
@Component
@AllArgsConstructor
@RequiredArgsConstructor
public class PrivateMessageResultResultTask extends AbstractMessageResultTask {
@Resource(name = "IMRedisTemplate")
private RedisTemplate<String,Object> redisTemplate;
private RedisTemplate<String, Object> redisTemplate;
@Value("${spring.application.name}")
private String appName;
@Value("${im.result.batch:100}")
private int batchSize;
private final MessageListenerMulticaster listenerMulticaster;
@Override
public void pullMessage() {
String key = IMRedisKey.IM_RESULT_PRIVATE_QUEUE;
JSONObject jsonObject = (JSONObject)redisTemplate.opsForList().leftPop(key,10, TimeUnit.SECONDS);
if(jsonObject != null) {
IMSendResult result = jsonObject.toJavaObject(IMSendResult.class);
listenerMulticaster.multicast(IMListenerType.PRIVATE_MESSAGE, result);
List<IMSendResult> results;
do {
results = loadBatch();
if(!results.isEmpty()){
listenerMulticaster.multicast(IMListenerType.PRIVATE_MESSAGE, results);
}
} while (results.size() >= batchSize);
}
List<IMSendResult> loadBatch() {
String key = StrUtil.join(":", IMRedisKey.IM_RESULT_PRIVATE_QUEUE, appName);
//这个接口redis6.2以上才支持
//List<Object> list = redisTemplate.opsForList().leftPop(key, batchSize);
List<IMSendResult> results = new LinkedList<>();
JSONObject jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
while (!Objects.isNull(jsonObject) && results.size() < batchSize) {
results.add(jsonObject.toJavaObject(IMSendResult.class));
jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
}
return results;
}
}

4
im-commom/src/main/java/com/bx/imcommon/model/IMRecvInfo.java

@ -27,6 +27,10 @@ public class IMRecvInfo {
*/
private Boolean sendResult;
/**
* 当前服务名回调发送结果使用
*/
private String serviceName;
/**
* 推送消息体
*/

13
im-platform/src/main/java/com/bx/implatform/listener/GroupMessageListener.java

@ -7,10 +7,13 @@ import com.bx.imcommon.enums.IMSendCode;
import com.bx.imcommon.model.IMSendResult;
import com.bx.implatform.contant.RedisKey;
import com.bx.implatform.vo.GroupMessageVO;
import com.bx.implatform.vo.PrivateMessageVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.List;
@Slf4j
@IMListener(type = IMListenerType.GROUP_MESSAGE)
@AllArgsConstructor
@ -19,9 +22,13 @@ public class GroupMessageListener implements MessageListener<GroupMessageVO> {
private final RedisTemplate<String, Object> redisTemplate;
@Override
public void process(IMSendResult<GroupMessageVO> result) {
GroupMessageVO messageInfo = result.getData();
// 空空如也
public void process(List<IMSendResult<GroupMessageVO>> results) {
for(IMSendResult<GroupMessageVO> result:results){
GroupMessageVO messageInfo = result.getData();
if (result.getCode().equals(IMSendCode.SUCCESS.code())) {
log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal());
}
}
}
}

24
im-platform/src/main/java/com/bx/implatform/listener/PrivateMessageListener.java

@ -1,5 +1,6 @@
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;
@ -14,6 +15,10 @@ 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.PRIVATE_MESSAGE)
public class PrivateMessageListener implements MessageListener<PrivateMessageVO> {
@ -23,16 +28,23 @@ public class PrivateMessageListener implements MessageListener<PrivateMessageVO>
private IPrivateMessageService privateMessageService;
@Override
public void process(IMSendResult<PrivateMessageVO> result) {
PrivateMessageVO messageInfo = result.getData();
// 更新消息状态,这里只处理成功消息,失败的消息继续保持未读状态
if (result.getCode().equals(IMSendCode.SUCCESS.code())) {
public void process(List<IMSendResult<PrivateMessageVO>> results) {
Set<Long> messageIds = new HashSet<>();
for(IMSendResult<PrivateMessageVO> result : results){
PrivateMessageVO messageInfo = result.getData();
// 更新消息状态,这里只处理成功消息,失败的消息继续保持未读状态
if (result.getCode().equals(IMSendCode.SUCCESS.code())) {
messageIds.add(messageInfo.getId());
log.info("消息送达,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal());
}
}
// 批量修改状态
if(CollUtil.isNotEmpty(messageIds)){
UpdateWrapper<PrivateMessage> updateWrapper = new UpdateWrapper<>();
updateWrapper.lambda().eq(PrivateMessage::getId, messageInfo.getId())
updateWrapper.lambda().in(PrivateMessage::getId, messageIds)
.eq(PrivateMessage::getStatus, MessageStatus.UNSEND.code())
.set(PrivateMessage::getStatus, MessageStatus.SENDED.code());
privateMessageService.update(updateWrapper);
log.info("消息已读,消息id:{},发送者:{},接收者:{},终端:{}", messageInfo.getId(), result.getSender().getId(), result.getReceiver().getId(), result.getReceiver().getTerminal());
}
}

32
im-platform/src/main/java/com/bx/implatform/service/impl/GroupMessageServiceImpl.java

@ -1,6 +1,8 @@
package com.bx.implatform.service.impl;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@ -86,6 +88,7 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
IMGroupMessage<GroupMessageVO> sendMessage = new IMGroupMessage<>();
sendMessage.setSender(new IMUserInfo(session.getUserId(), session.getTerminal()));
sendMessage.setRecvIds(userIds);
sendMessage.setSendResult(false);
sendMessage.setData(msgInfo);
imClient.sendGroupMessage(sendMessage);
log.info("发送群聊消息,发送id:{},群聊id:{},内容:{}", session.getUserId(), dto.getGroupId(), dto.getContent());
@ -145,10 +148,11 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
public List<GroupMessageVO> loadMessage(Long minId) {
UserSession session = SessionContext.getSession();
List<GroupMember> members = groupMemberService.findByUserId(session.getUserId());
List<Long> ids = members.stream().map(GroupMember::getGroupId).collect(Collectors.toList());
if (CollectionUtil.isEmpty(ids)) {
if (CollectionUtil.isEmpty(members)) {
return new ArrayList<>();
}
Map<Long, GroupMember> groupMemberMap = CollStreamUtil.toIdentityMap(members, GroupMember::getGroupId);
Set<Long> ids = groupMemberMap.keySet();
// 只能拉取最近1个月的
Date minDate = DateUtils.addMonths(new Date(), -1);
LambdaQueryWrapper<GroupMessage> wrapper = Wrappers.lambdaQuery();
@ -157,15 +161,21 @@ public class GroupMessageServiceImpl extends ServiceImpl<GroupMessageMapper, Gro
List<GroupMessage> messages = this.list(wrapper);
// 转成vo
List<GroupMessageVO> vos = messages.stream().map(m -> {
GroupMessageVO vo = BeanUtils.copyProperties(m, GroupMessageVO.class);
// 被@用户列表
if (StringUtils.isNotBlank(m.getAtUserIds())) {
List<String> atIds = Splitter.on(",").trimResults().splitToList(m.getAtUserIds());
vo.setAtUserIds(atIds.stream().map(Long::parseLong).collect(Collectors.toList()));
}
return vo;
}).collect(Collectors.toList());
List<GroupMessageVO> vos = messages.stream()
.filter(m -> {
//排除加群之前的消息
GroupMember member = groupMemberMap.get(m.getGroupId());
return Objects.nonNull(member) && DateUtil.compare(member.getCreatedTime(), m.getSendTime()) <= 0;
})
.map(m -> {
GroupMessageVO vo = BeanUtils.copyProperties(m, GroupMessageVO.class);
// 被@用户列表
if (StringUtils.isNotBlank(m.getAtUserIds()) && Objects.nonNull(vo)) {
List<String> atIds = Splitter.on(",").trimResults().splitToList(m.getAtUserIds());
vo.setAtUserIds(atIds.stream().map(Long::parseLong).collect(Collectors.toList()));
}
return vo;
}).collect(Collectors.toList());
// 消息状态,数据库没有存群聊的消息状态,需要从redis取
List<String> keys = ids.stream().map(id -> String.join(":", RedisKey.IM_GROUP_READED_POSITION, id.toString(), session.getUserId().toString()))
.collect(Collectors.toList());

1
im-platform/src/main/java/com/bx/implatform/service/impl/PrivateMessageServiceImpl.java

@ -65,6 +65,7 @@ public class PrivateMessageServiceImpl extends ServiceImpl<PrivateMessageMapper,
sendMessage.setRecvId(msgInfo.getRecvId());
sendMessage.setSendToSelf(true);
sendMessage.setData(msgInfo);
sendMessage.setSendResult(true);
imClient.sendPrivateMessage(sendMessage);
log.info("发送私聊消息,发送id:{},接收id:{},内容:{}", session.getUserId(), dto.getRecvId(), dto.getContent());
return msg.getId();

2
im-platform/src/main/resources/application.yml

@ -3,6 +3,8 @@ server:
port: 8888
#配置项目的数据源
spring:
application:
name: im-platform
mvc:
pathmatch:
matching-strategy: ant_path_matcher

4
im-server/src/main/java/com/bx/imserver/netty/processor/GroupMessageProcessor.java

@ -1,5 +1,6 @@
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;
@ -24,7 +25,6 @@ public class GroupMessageProcessor extends AbstractMessageProcessor<IMRecvInfo>
private final RedisTemplate<String, Object> redisTemplate;
@Async
@Override
public void process(IMRecvInfo recvInfo) {
IMUserInfo sender = recvInfo.getSender();
@ -64,7 +64,7 @@ public class GroupMessageProcessor extends AbstractMessageProcessor<IMRecvInfo>
result.setCode(sendCode.code());
result.setData(recvInfo.getData());
// 推送到结果队列
String key = IMRedisKey.IM_RESULT_GROUP_QUEUE;
String key = StrUtil.join(":",IMRedisKey.IM_RESULT_GROUP_QUEUE,recvInfo.getServiceName());
redisTemplate.opsForList().rightPush(key, result);
}
}

3
im-server/src/main/java/com/bx/imserver/netty/processor/PrivateMessageProcessor.java

@ -1,5 +1,6 @@
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;
@ -57,7 +58,7 @@ public class PrivateMessageProcessor extends AbstractMessageProcessor<IMRecvInfo
result.setCode(sendCode.code());
result.setData(recvInfo.getData());
// 推送到结果队列
String key = IMRedisKey.IM_RESULT_PRIVATE_QUEUE;
String key = StrUtil.join(":",IMRedisKey.IM_RESULT_PRIVATE_QUEUE,recvInfo.getServiceName());
redisTemplate.opsForList().rightPush(key, result);
}
}

4
im-server/src/main/java/com/bx/imserver/task/AbstractPullMessageTask.java

@ -30,9 +30,9 @@ public abstract class AbstractPullMessageTask implements CommandLineRunner {
}
} catch (Exception e) {
log.error("任务调度异常", e);
Thread.sleep(200);
}
if (!EXECUTOR_SERVICE.isShutdown()) {
Thread.sleep(100);
EXECUTOR_SERVICE.execute(this);
}
}
@ -45,5 +45,5 @@ public abstract class AbstractPullMessageTask implements CommandLineRunner {
EXECUTOR_SERVICE.shutdown();
}
public abstract void pullMessage();
public abstract void pullMessage() throws InterruptedException;
}

8
im-server/src/main/java/com/bx/imserver/task/PullGroupMessageTask.java

@ -12,7 +12,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import java.util.Objects;
@Slf4j
@Component
@ -25,11 +25,13 @@ public class PullGroupMessageTask extends AbstractPullMessageTask {
public void pullMessage() {
// 从redis拉取未读消息
String key = String.join(":", IMRedisKey.IM_MESSAGE_GROUP_QUEUE, IMServerGroup.serverId + "");
JSONObject jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key, 10, TimeUnit.SECONDS);
if (jsonObject != null) {
JSONObject jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
while (!Objects.isNull(jsonObject)) {
IMRecvInfo recvInfo = jsonObject.toJavaObject(IMRecvInfo.class);
AbstractMessageProcessor processor = ProcessorFactory.createProcessor(IMCmdType.GROUP_MESSAGE);
processor.process(recvInfo);
// 下一条消息
jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
}
}

15
im-server/src/main/java/com/bx/imserver/task/PullPrivateMessageTask.java

@ -12,25 +12,26 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
import java.util.Objects;
@Slf4j
@Component
@RequiredArgsConstructor
public class PullPrivateMessageTask extends AbstractPullMessageTask {
public class PullPrivateMessageTask extends AbstractPullMessageTask {
private final RedisTemplate<String,Object> redisTemplate;
private final RedisTemplate<String, Object> redisTemplate;
@Override
public void pullMessage() {
// 从redis拉取未读消息
String key = String.join(":", IMRedisKey.IM_MESSAGE_PRIVATE_QUEUE,IMServerGroup.serverId+"");
JSONObject jsonObject = (JSONObject)redisTemplate.opsForList().leftPop(key,10, TimeUnit.SECONDS);
if(jsonObject!=null){
String key = String.join(":", IMRedisKey.IM_MESSAGE_PRIVATE_QUEUE, IMServerGroup.serverId + "");
JSONObject jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
while (!Objects.isNull(jsonObject)) {
IMRecvInfo recvInfo = jsonObject.toJavaObject(IMRecvInfo.class);
AbstractMessageProcessor processor = ProcessorFactory.createProcessor(IMCmdType.PRIVATE_MESSAGE);
processor.process(recvInfo);
// 下一条消息
jsonObject = (JSONObject) redisTemplate.opsForList().leftPop(key);
}
}
}

2
im-ui/src/api/date.js

@ -21,7 +21,7 @@ let toTimeText = (timeStamp, simple) => {
//不属于今年
timeText = formatDateTime(dateTime);
if(simple){
timeText = timeText.substring(2,5);
timeText = timeText.substr(2,8);
}
}
return timeText;

1
im-ui/src/components/chat/ChatBox.vue

@ -256,7 +256,6 @@
let textNode = document.createTextNode(txt);
range.insertNode(textNode)
range.collapse();
}
let items = (event.clipboardData || window.clipboardData).items
if (items.length) {

2
im-uniapp/common/date.js

@ -21,7 +21,7 @@ let toTimeText = (timeStamp, simple) => {
//不属于今年
timeText = formatDateTime(dateTime);
if(simple){
timeText = timeText.substring(2,5);
timeText = timeText.substr(2,8);
}
}
return timeText;

2
im-uniapp/components/chat-item/chat-item.vue

@ -7,7 +7,7 @@
<view class="chat-right">
<view class="chat-name">
<view class="chat-name-text">{{chat.showName}}</view>
<view class="chat-time">{{$date.toTimeText(chat.lastSendTime)}}</view>
<view class="chat-time">{{$date.toTimeText(chat.lastSendTime,true)}}</view>
</view>
<view class="chat-content">
<view class="chat-at-text">{{atText}}</view>

Loading…
Cancel
Save