mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-14 06:03:42 +08:00
feat:消息标记重构
This commit is contained in:
@@ -1,19 +1,3 @@
|
|||||||
/*
|
|
||||||
Navicat Premium Data Transfer
|
|
||||||
|
|
||||||
Source Server : mallchat
|
|
||||||
Source Server Type : MySQL
|
|
||||||
Source Server Version : 50741
|
|
||||||
Source Host : 101.33.251.36:3306
|
|
||||||
Source Schema : mallchat
|
|
||||||
|
|
||||||
Target Server Type : MySQL
|
|
||||||
Target Server Version : 50741
|
|
||||||
File Encoding : 65001
|
|
||||||
|
|
||||||
Date: 10/05/2023 14:25:59
|
|
||||||
*/
|
|
||||||
|
|
||||||
SET NAMES utf8mb4;
|
SET NAMES utf8mb4;
|
||||||
SET FOREIGN_KEY_CHECKS = 0;
|
SET FOREIGN_KEY_CHECKS = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@
|
|||||||
<version>2.0.9</version>
|
<version>2.0.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.hibernate</groupId>
|
<groupId>org.hibernate.validator</groupId>
|
||||||
<artifactId>hibernate-validator</artifactId>
|
<artifactId>hibernate-validator</artifactId>
|
||||||
<version>6.0.1.Final</version>
|
<version>6.0.1.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -116,5 +116,14 @@
|
|||||||
<version>3.17.1</version>
|
<version>3.17.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>2.4.3</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
@@ -16,12 +16,22 @@ import lombok.NoArgsConstructor;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
public class ChatMessageMarkDTO {
|
public class ChatMessageMarkDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty("操作者")
|
||||||
|
private Long uid;
|
||||||
|
|
||||||
@ApiModelProperty("消息id")
|
@ApiModelProperty("消息id")
|
||||||
private Long msgId;
|
private Long msgId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum
|
||||||
|
*/
|
||||||
@ApiModelProperty("标记类型 1点赞 2举报")
|
@ApiModelProperty("标记类型 1点赞 2举报")
|
||||||
private Integer markType;
|
private Integer markType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum
|
||||||
|
*/
|
||||||
@ApiModelProperty("动作类型 1确认 2取消")
|
@ApiModelProperty("动作类型 1确认 2取消")
|
||||||
private Integer actType;
|
private Integer actType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.abin.mallchat.common.chat.domain.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 消息标记动作类型
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-19
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum MessageMarkActTypeEnum {
|
||||||
|
MARK(1, "确认标记"),
|
||||||
|
UN_MARK(2, "取消标记"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer type;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
private static Map<Integer, MessageMarkActTypeEnum> cache;
|
||||||
|
|
||||||
|
static {
|
||||||
|
cache = Arrays.stream(MessageMarkActTypeEnum.values()).collect(Collectors.toMap(MessageMarkActTypeEnum::getType, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MessageMarkActTypeEnum of(Integer type) {
|
||||||
|
return cache.get(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.abin.mallchat.common.common.domain.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 是否正常的通用枚举
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-19
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum NormalOrNoEnum {
|
||||||
|
NORMAL(0, "正常"),
|
||||||
|
NOT_NORMAL(1, "不正常"),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer status;
|
||||||
|
private final String desc;
|
||||||
|
|
||||||
|
private static Map<Integer, NormalOrNoEnum> cache;
|
||||||
|
|
||||||
|
static {
|
||||||
|
cache = Arrays.stream(NormalOrNoEnum.values()).collect(Collectors.toMap(NormalOrNoEnum::getStatus, Function.identity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NormalOrNoEnum of(Integer type) {
|
||||||
|
return cache.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer toStatus(Boolean bool) {
|
||||||
|
return bool ? NORMAL.getStatus() : NOT_NORMAL.getStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,8 +17,8 @@ public enum CommonErrorEnum implements ErrorEnum {
|
|||||||
FREQUENCY_LIMIT(-3, "请求太频繁了,请稍后再试哦~~"),
|
FREQUENCY_LIMIT(-3, "请求太频繁了,请稍后再试哦~~"),
|
||||||
LOCK_LIMIT(-4, "请求太频繁了,请稍后再试哦~~"),
|
LOCK_LIMIT(-4, "请求太频繁了,请稍后再试哦~~"),
|
||||||
;
|
;
|
||||||
private Integer code;
|
private final Integer code;
|
||||||
private String msg;
|
private final String msg;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer getErrorCode() {
|
public Integer getErrorCode() {
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ package com.abin.mallchat.common.common.factory;
|
|||||||
|
|
||||||
import com.abin.mallchat.common.common.handler.GlobalUncaughtExceptionHandler;
|
import com.abin.mallchat.common.common.handler.GlobalUncaughtExceptionHandler;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
|
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|
||||||
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
@@ -13,14 +10,12 @@ import java.util.concurrent.ThreadFactory;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class MyThreadFactory implements ThreadFactory {
|
public class MyThreadFactory implements ThreadFactory {
|
||||||
|
|
||||||
private ThreadFactory factory;
|
private final ThreadFactory factory;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Thread newThread(Runnable r) {
|
public Thread newThread(Runnable r) {
|
||||||
Thread thread =factory.newThread(r);
|
Thread thread =factory.newThread(r);
|
||||||
thread.setUncaughtExceptionHandler(new GlobalUncaughtExceptionHandler());
|
thread.setUncaughtExceptionHandler(new GlobalUncaughtExceptionHandler());
|
||||||
thread.setDaemon(false);
|
|
||||||
thread.setPriority(5);
|
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.abin.mallchat.common.common.handler;
|
package com.abin.mallchat.common.common.handler;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -10,7 +8,7 @@ public class GlobalUncaughtExceptionHandler implements Thread.UncaughtException
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uncaughtException(Thread t, Throwable e) {
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
log.error("{} task execute is error",t.getName());
|
log.error("Exception in thread {} ", t.getName(), e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class ChatController {
|
|||||||
return userCache.getBlackMap().getOrDefault(BlackTypeEnum.UID.getType(), new HashSet<>());
|
return userCache.getBlackMap().getOrDefault(BlackTypeEnum.UID.getType(), new HashSet<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("public/member/statistic/")
|
@GetMapping("public/member/statistic")
|
||||||
@ApiOperation("群成员人数统计")
|
@ApiOperation("群成员人数统计")
|
||||||
public ApiResult<ChatMemberStatisticResp> getMemberStatistic() {
|
public ApiResult<ChatMemberStatisticResp> getMemberStatistic() {
|
||||||
return ApiResult.success(chatService.getMemberStatistic());
|
return ApiResult.success(chatService.getMemberStatistic());
|
||||||
|
|||||||
@@ -20,5 +20,6 @@ public class ChatMemberStatisticResp {
|
|||||||
@ApiModelProperty("在线人数")
|
@ApiModelProperty("在线人数")
|
||||||
private Long onlineNum;//在线人数
|
private Long onlineNum;//在线人数
|
||||||
@ApiModelProperty("总人数")
|
@ApiModelProperty("总人数")
|
||||||
|
@Deprecated
|
||||||
private Long totalNum;//总人数
|
private Long totalNum;//总人数
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,14 @@ import cn.hutool.core.lang.Pair;
|
|||||||
import com.abin.mallchat.common.chat.dao.MessageDao;
|
import com.abin.mallchat.common.chat.dao.MessageDao;
|
||||||
import com.abin.mallchat.common.chat.dao.MessageMarkDao;
|
import com.abin.mallchat.common.chat.dao.MessageMarkDao;
|
||||||
import com.abin.mallchat.common.chat.dao.RoomDao;
|
import com.abin.mallchat.common.chat.dao.RoomDao;
|
||||||
import com.abin.mallchat.common.chat.domain.dto.ChatMessageMarkDTO;
|
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Message;
|
import com.abin.mallchat.common.chat.domain.entity.Message;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
||||||
import com.abin.mallchat.common.chat.domain.entity.Room;
|
import com.abin.mallchat.common.chat.domain.entity.Room;
|
||||||
|
import com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum;
|
||||||
import com.abin.mallchat.common.common.annotation.RedissonLock;
|
import com.abin.mallchat.common.common.annotation.RedissonLock;
|
||||||
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
||||||
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||||
import com.abin.mallchat.common.common.event.MessageMarkEvent;
|
|
||||||
import com.abin.mallchat.common.common.event.MessageSendEvent;
|
import com.abin.mallchat.common.common.event.MessageSendEvent;
|
||||||
import com.abin.mallchat.common.common.exception.BusinessException;
|
import com.abin.mallchat.common.common.exception.BusinessException;
|
||||||
import com.abin.mallchat.common.common.utils.AssertUtil;
|
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||||
@@ -36,8 +35,9 @@ import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter;
|
|||||||
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
|
import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter;
|
||||||
import com.abin.mallchat.custom.chat.service.adapter.RoomAdapter;
|
import com.abin.mallchat.custom.chat.service.adapter.RoomAdapter;
|
||||||
import com.abin.mallchat.custom.chat.service.helper.ChatMemberHelper;
|
import com.abin.mallchat.custom.chat.service.helper.ChatMemberHelper;
|
||||||
|
import com.abin.mallchat.custom.chat.service.strategy.mark.AbstractMsgMarkStrategy;
|
||||||
|
import com.abin.mallchat.custom.chat.service.strategy.mark.MsgMarkFactory;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.BeanUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationEventPublisher;
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -165,38 +165,25 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
public ChatMemberStatisticResp getMemberStatistic() {
|
public ChatMemberStatisticResp getMemberStatistic() {
|
||||||
System.out.println(Thread.currentThread().getName());
|
System.out.println(Thread.currentThread().getName());
|
||||||
Long onlineNum = userCache.getOnlineNum();
|
Long onlineNum = userCache.getOnlineNum();
|
||||||
Long offlineNum = userCache.getOfflineNum();
|
// Long offlineNum = userCache.getOfflineNum();不展示总人数
|
||||||
ChatMemberStatisticResp resp = new ChatMemberStatisticResp();
|
ChatMemberStatisticResp resp = new ChatMemberStatisticResp();
|
||||||
resp.setOnlineNum(onlineNum);
|
resp.setOnlineNum(onlineNum);
|
||||||
resp.setTotalNum(onlineNum + offlineNum);
|
// resp.setTotalNum(onlineNum + offlineNum);
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@RedissonLock(key = "#uid")
|
@RedissonLock(key = "#uid")
|
||||||
public void setMsgMark(Long uid, ChatMessageMarkReq request) {
|
public void setMsgMark(Long uid, ChatMessageMarkReq request) {
|
||||||
//用户对该消息的标记
|
AbstractMsgMarkStrategy strategy = MsgMarkFactory.getStrategyNoNull(request.getMarkType());
|
||||||
MessageMark messageMark = messageMarkDao.get(uid, request.getMsgId(), request.getMarkType());
|
switch (MessageMarkActTypeEnum.of(request.getActType())) {
|
||||||
if (Objects.nonNull(messageMark)) {//有标记过消息修改一下就好
|
case MARK:
|
||||||
MessageMark update = MessageMark.builder()
|
strategy.mark(uid, request.getMsgId());
|
||||||
.id(messageMark.getId())
|
break;
|
||||||
.status(transformAct(request.getActType()))
|
case UN_MARK:
|
||||||
.build();
|
strategy.unMark(uid, request.getMsgId());
|
||||||
messageMarkDao.updateById(update);
|
break;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
//没标记过消息,插入一条新消息
|
|
||||||
MessageMark insert = MessageMark.builder()
|
|
||||||
.uid(uid)
|
|
||||||
.msgId(request.getMsgId())
|
|
||||||
.type(request.getMarkType())
|
|
||||||
.status(transformAct(request.getActType()))
|
|
||||||
.build();
|
|
||||||
messageMarkDao.save(insert);
|
|
||||||
//发布消息标记事件
|
|
||||||
ChatMessageMarkDTO dto = new ChatMessageMarkDTO();
|
|
||||||
BeanUtils.copyProperties(request, dto);
|
|
||||||
applicationEventPublisher.publishEvent(new MessageMarkEvent(this, dto));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Integer transformAct(Integer actType) {
|
private Integer transformAct(Integer actType) {
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package com.abin.mallchat.custom.chat.service.strategy.mark;
|
||||||
|
|
||||||
|
import com.abin.mallchat.common.chat.dao.MessageMarkDao;
|
||||||
|
import com.abin.mallchat.common.chat.domain.dto.ChatMessageMarkDTO;
|
||||||
|
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
|
||||||
|
import com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum;
|
||||||
|
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||||
|
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
||||||
|
import com.abin.mallchat.common.common.event.MessageMarkEvent;
|
||||||
|
import com.abin.mallchat.common.common.exception.BusinessException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 消息标记抽象类
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-05-30
|
||||||
|
*/
|
||||||
|
public abstract class AbstractMsgMarkStrategy {
|
||||||
|
@Autowired
|
||||||
|
private MessageMarkDao messageMarkDao;
|
||||||
|
@Autowired
|
||||||
|
private ApplicationEventPublisher applicationEventPublisher;
|
||||||
|
|
||||||
|
protected abstract MessageMarkTypeEnum getTypeEnum();
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void mark(Long uid, Long msgId) {
|
||||||
|
exec(uid, msgId, MessageMarkActTypeEnum.MARK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void unMark(Long uid, Long msgId) {
|
||||||
|
exec(uid, msgId, MessageMarkActTypeEnum.UN_MARK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
private void init() {
|
||||||
|
MsgMarkFactory.register(getTypeEnum().getType(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void exec(Long uid, Long msgId, MessageMarkActTypeEnum actTypeEnum) {
|
||||||
|
Integer markType = getTypeEnum().getType();
|
||||||
|
Integer actType = actTypeEnum.getType();
|
||||||
|
MessageMark oldMark = messageMarkDao.get(uid, msgId, markType);
|
||||||
|
if (Objects.isNull(oldMark) && actTypeEnum == MessageMarkActTypeEnum.UN_MARK) {
|
||||||
|
//取消的类型,数据库一定有记录,没有就直接跳过操作
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//插入一条新消息,或者修改一条消息
|
||||||
|
MessageMark insertOrUpdate = MessageMark.builder()
|
||||||
|
.id(Optional.ofNullable(oldMark).map(MessageMark::getId).orElse(null))
|
||||||
|
.uid(uid)
|
||||||
|
.msgId(msgId)
|
||||||
|
.type(markType)
|
||||||
|
.status(transformAct(actType))
|
||||||
|
.build();
|
||||||
|
boolean modify = messageMarkDao.saveOrUpdate(insertOrUpdate);
|
||||||
|
if (modify) {
|
||||||
|
//修改成功才发布消息标记事件
|
||||||
|
ChatMessageMarkDTO dto = new ChatMessageMarkDTO(uid, msgId, markType, actType);
|
||||||
|
applicationEventPublisher.publishEvent(new MessageMarkEvent(this, dto));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer transformAct(Integer actType) {
|
||||||
|
if (actType == 1) {
|
||||||
|
return YesOrNoEnum.NO.getStatus();
|
||||||
|
} else if (actType == 2) {
|
||||||
|
return YesOrNoEnum.YES.getStatus();
|
||||||
|
}
|
||||||
|
throw new BusinessException("动作类型 1确认 2取消");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.abin.mallchat.custom.chat.service.strategy.mark;
|
||||||
|
|
||||||
|
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 点踩标记策略类
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-05-30
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DisLikeStrategy extends AbstractMsgMarkStrategy {
|
||||||
|
@Autowired
|
||||||
|
@Lazy
|
||||||
|
private LikeStrategy likeStrategy;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MessageMarkTypeEnum getTypeEnum() {
|
||||||
|
return MessageMarkTypeEnum.DISLIKE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mark(Long uid, Long msgId) {
|
||||||
|
super.mark(uid, msgId);
|
||||||
|
//同时取消点赞的动作
|
||||||
|
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.LIKE.getType()).unMark(uid, msgId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.abin.mallchat.custom.chat.service.strategy.mark;
|
||||||
|
|
||||||
|
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 点赞标记策略类
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-05-30
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class LikeStrategy extends AbstractMsgMarkStrategy {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MessageMarkTypeEnum getTypeEnum() {
|
||||||
|
return MessageMarkTypeEnum.LIKE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mark(Long uid, Long msgId) {
|
||||||
|
super.mark(uid, msgId);
|
||||||
|
//同时取消点踩的动作
|
||||||
|
MsgMarkFactory.getStrategyNoNull(MessageMarkTypeEnum.DISLIKE.getType()).unMark(uid, msgId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.abin.mallchat.custom.chat.service.strategy.mark;
|
||||||
|
|
||||||
|
import com.abin.mallchat.common.common.exception.CommonErrorEnum;
|
||||||
|
import com.abin.mallchat.common.common.utils.AssertUtil;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 消息标记策略工厂
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-05-30
|
||||||
|
*/
|
||||||
|
public class MsgMarkFactory {
|
||||||
|
private static final Map<Integer, AbstractMsgMarkStrategy> STRATEGY_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
public static void register(Integer markType, AbstractMsgMarkStrategy strategy) {
|
||||||
|
STRATEGY_MAP.put(markType, strategy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbstractMsgMarkStrategy getStrategyNoNull(Integer markType) {
|
||||||
|
AbstractMsgMarkStrategy strategy = STRATEGY_MAP.get(markType);
|
||||||
|
AssertUtil.isNotEmpty(strategy, CommonErrorEnum.PARAM_VALID);
|
||||||
|
return strategy;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,11 +10,13 @@ import com.abin.mallchat.common.common.domain.enums.IdempotentEnum;
|
|||||||
import com.abin.mallchat.common.common.event.MessageMarkEvent;
|
import com.abin.mallchat.common.common.event.MessageMarkEvent;
|
||||||
import com.abin.mallchat.common.user.domain.enums.ItemEnum;
|
import com.abin.mallchat.common.user.domain.enums.ItemEnum;
|
||||||
import com.abin.mallchat.common.user.service.IUserBackpackService;
|
import com.abin.mallchat.common.user.service.IUserBackpackService;
|
||||||
|
import com.abin.mallchat.custom.user.service.WebSocketService;
|
||||||
|
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -32,9 +34,11 @@ public class MessageMarkListener {
|
|||||||
private MessageDao messageDao;
|
private MessageDao messageDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IUserBackpackService iUserBackpackService;
|
private IUserBackpackService iUserBackpackService;
|
||||||
|
@Autowired
|
||||||
|
private WebSocketService webSocketService;
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
@EventListener(classes = MessageMarkEvent.class)
|
@TransactionalEventListener(classes = MessageMarkEvent.class, fallbackExecution = true)
|
||||||
public void changeMsgType(MessageMarkEvent event) {
|
public void changeMsgType(MessageMarkEvent event) {
|
||||||
ChatMessageMarkDTO dto = event.getDto();
|
ChatMessageMarkDTO dto = event.getDto();
|
||||||
Message msg = messageDao.getById(dto.getMsgId());
|
Message msg = messageDao.getById(dto.getMsgId());
|
||||||
@@ -53,4 +57,12 @@ public class MessageMarkListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Async
|
||||||
|
@TransactionalEventListener(classes = MessageMarkEvent.class, fallbackExecution = true)
|
||||||
|
public void notifyAll(MessageMarkEvent event) {//后续可做合并查询,目前异步影响不大
|
||||||
|
ChatMessageMarkDTO dto = event.getDto();
|
||||||
|
Integer markCount = messageMarkDao.getMarkCount(dto.getMsgId(), dto.getMarkType());
|
||||||
|
webSocketService.sendToAllOnline(WSAdapter.buildMsgMarkSend(dto, markCount), dto.getUid());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import com.abin.mallchat.custom.user.service.WebSocketService;
|
|||||||
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
import com.abin.mallchat.custom.user.service.adapter.WSAdapter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.event.EventListener;
|
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.event.TransactionalEventListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 消息发送监听器
|
* 消息发送监听器
|
||||||
@@ -29,7 +29,7 @@ public class MessageSendListener {
|
|||||||
private MessageDao messageDao;
|
private MessageDao messageDao;
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
@EventListener(classes = MessageSendEvent.class)
|
@TransactionalEventListener(classes = MessageSendEvent.class, fallbackExecution = true)
|
||||||
public void notifyAllOnline(MessageSendEvent event) {
|
public void notifyAllOnline(MessageSendEvent event) {
|
||||||
Message message = messageDao.getById(event.getMsgId());
|
Message message = messageDao.getById(event.getMsgId());
|
||||||
ChatMessageResp msgResp = chatService.getMsgResp(message, null);
|
ChatMessageResp msgResp = chatService.getMsgResp(message, null);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class UserOnlineListener {
|
|||||||
User user = event.getUser();
|
User user = event.getUser();
|
||||||
userCache.online(user.getId(), user.getLastOptTime());
|
userCache.online(user.getId(), user.getLastOptTime());
|
||||||
//推送给所有在线用户,该用户登录成功
|
//推送给所有在线用户,该用户登录成功
|
||||||
webSocketService.sendToAllOnline(wsAdapter.buildOnlineNotifyResp(event.getUser()), null);
|
webSocketService.sendToAllOnline(wsAdapter.buildOnlineNotifyResp(event.getUser()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Async
|
@Async
|
||||||
|
|||||||
@@ -33,16 +33,16 @@ public class UserRegisterListener {
|
|||||||
iUserBackpackService.acquireItem(user.getId(), ItemEnum.MODIFY_NAME_CARD.getId(), IdempotentEnum.UID, user.getId().toString());
|
iUserBackpackService.acquireItem(user.getId(), ItemEnum.MODIFY_NAME_CARD.getId(), IdempotentEnum.UID, user.getId().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Async
|
// @Async
|
||||||
@EventListener(classes = UserRegisterEvent.class)
|
// @EventListener(classes = UserRegisterEvent.class)
|
||||||
public void sendBadge(UserRegisterEvent event) {
|
// public void sendBadge(UserRegisterEvent event) {
|
||||||
User user = event.getUser();
|
// User user = event.getUser();
|
||||||
int count = userDao.count();//todo 性能瓶颈,等注册用户多了直接删掉
|
// int count = userDao.count();// 性能瓶颈,等注册用户多了直接删掉
|
||||||
if (count <= 10) {
|
// if (count <= 10) {
|
||||||
iUserBackpackService.acquireItem(user.getId(), ItemEnum.REG_TOP10_BADGE.getId(), IdempotentEnum.UID, user.getId().toString());
|
// iUserBackpackService.acquireItem(user.getId(), ItemEnum.REG_TOP10_BADGE.getId(), IdempotentEnum.UID, user.getId().toString());
|
||||||
} else if (count <= 100) {
|
// } else if (count <= 100) {
|
||||||
iUserBackpackService.acquireItem(user.getId(), ItemEnum.REG_TOP100_BADGE.getId(), IdempotentEnum.UID, user.getId().toString());
|
// iUserBackpackService.acquireItem(user.getId(), ItemEnum.REG_TOP100_BADGE.getId(), IdempotentEnum.UID, user.getId().toString());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public enum WSRespTypeEnum {
|
|||||||
ONLINE_OFFLINE_NOTIFY(5, "上下线通知", WSOnlineOfflineNotify.class),
|
ONLINE_OFFLINE_NOTIFY(5, "上下线通知", WSOnlineOfflineNotify.class),
|
||||||
INVALIDATE_TOKEN(6, "使前端的token失效,意味着前端需要重新登录", null),
|
INVALIDATE_TOKEN(6, "使前端的token失效,意味着前端需要重新登录", null),
|
||||||
BLACK(7, "拉黑用户", WSBlack.class),
|
BLACK(7, "拉黑用户", WSBlack.class),
|
||||||
|
MARK(8, "消息标记", WSMsgMark.class),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.abin.mallchat.custom.user.domain.vo.response.ws;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description:
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-19
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class WSMsgMark {
|
||||||
|
private List<WSMsgMarkItem> markList;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class WSMsgMarkItem {
|
||||||
|
@ApiModelProperty("操作者")
|
||||||
|
private Long uid;
|
||||||
|
@ApiModelProperty("消息id")
|
||||||
|
private Long msgId;
|
||||||
|
/**
|
||||||
|
* @see com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("标记类型 1点赞 2举报")
|
||||||
|
private Integer markType;
|
||||||
|
@ApiModelProperty("被标记的数量")
|
||||||
|
private Integer markCount;
|
||||||
|
/**
|
||||||
|
* @see com.abin.mallchat.common.chat.domain.enums.MessageMarkActTypeEnum
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("动作类型 1确认 2取消")
|
||||||
|
private Integer actType;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ import java.util.List;
|
|||||||
public class WSOnlineOfflineNotify {
|
public class WSOnlineOfflineNotify {
|
||||||
private List<ChatMemberResp> changeList = new ArrayList<>();//新的上下线用户
|
private List<ChatMemberResp> changeList = new ArrayList<>();//新的上下线用户
|
||||||
private Long onlineNum;//在线人数
|
private Long onlineNum;//在线人数
|
||||||
|
@Deprecated
|
||||||
private Long totalNum;//总人数
|
private Long totalNum;//总人数
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,14 @@ public interface WebSocketService {
|
|||||||
* @param wsBaseResp 发送的消息体
|
* @param wsBaseResp 发送的消息体
|
||||||
* @param skipUid 需要跳过的人
|
* @param skipUid 需要跳过的人
|
||||||
*/
|
*/
|
||||||
void sendToAllOnline(WSBaseResp wsBaseResp, Long skipUid);
|
void sendToAllOnline(WSBaseResp<?> wsBaseResp, Long skipUid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推动消息给所有在线的人
|
||||||
|
*
|
||||||
|
* @param wsBaseResp 发送的消息体
|
||||||
|
*/
|
||||||
|
void sendToAllOnline(WSBaseResp<?> wsBaseResp);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.abin.mallchat.custom.user.service.adapter;
|
package com.abin.mallchat.custom.user.service.adapter;
|
||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import com.abin.mallchat.common.chat.domain.dto.ChatMessageMarkDTO;
|
||||||
import com.abin.mallchat.common.user.domain.entity.User;
|
import com.abin.mallchat.common.user.domain.entity.User;
|
||||||
import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum;
|
import com.abin.mallchat.common.user.domain.enums.ChatActiveStatusEnum;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp;
|
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp;
|
||||||
@@ -8,11 +9,9 @@ import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberStatisticResp;
|
|||||||
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
|
import com.abin.mallchat.custom.chat.domain.vo.response.ChatMessageResp;
|
||||||
import com.abin.mallchat.custom.chat.service.ChatService;
|
import com.abin.mallchat.custom.chat.service.ChatService;
|
||||||
import com.abin.mallchat.custom.user.domain.enums.WSRespTypeEnum;
|
import com.abin.mallchat.custom.user.domain.enums.WSRespTypeEnum;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSBaseResp;
|
import com.abin.mallchat.custom.user.domain.vo.response.ws.*;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSLoginSuccess;
|
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSLoginUrl;
|
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSOnlineOfflineNotify;
|
|
||||||
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
|
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -110,4 +109,16 @@ public class WSAdapter {
|
|||||||
wsBaseResp.setData(msgResp);
|
wsBaseResp.setData(msgResp);
|
||||||
return wsBaseResp;
|
return wsBaseResp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static WSBaseResp<WSMsgMark> buildMsgMarkSend(ChatMessageMarkDTO dto, Integer markCount) {
|
||||||
|
WSMsgMark.WSMsgMarkItem item = new WSMsgMark.WSMsgMarkItem();
|
||||||
|
BeanUtils.copyProperties(dto, item);
|
||||||
|
item.setMarkCount(markCount);
|
||||||
|
WSBaseResp<WSMsgMark> wsBaseResp = new WSBaseResp<>();
|
||||||
|
wsBaseResp.setType(WSRespTypeEnum.MARK.getType());
|
||||||
|
WSMsgMark mark = new WSMsgMark();
|
||||||
|
mark.setMarkList(Collections.singletonList(item));
|
||||||
|
wsBaseResp.setData(mark);
|
||||||
|
return wsBaseResp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ public class WebSocketServiceImpl implements WebSocketService {
|
|||||||
|
|
||||||
//entrySet的值不是快照数据,但是它支持遍历,所以无所谓了,不用快照也行。
|
//entrySet的值不是快照数据,但是它支持遍历,所以无所谓了,不用快照也行。
|
||||||
@Override
|
@Override
|
||||||
public void sendToAllOnline(WSBaseResp wsBaseResp, Long skipUid) {
|
public void sendToAllOnline(WSBaseResp<?> wsBaseResp, Long skipUid) {
|
||||||
ONLINE_WS_MAP.forEach((channel, ext) -> {
|
ONLINE_WS_MAP.forEach((channel, ext) -> {
|
||||||
if (ObjectUtil.equal(ext.getUid(), skipUid)) {
|
if (ObjectUtil.equal(ext.getUid(), skipUid)) {
|
||||||
return;
|
return;
|
||||||
@@ -236,7 +236,12 @@ public class WebSocketServiceImpl implements WebSocketService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMsg(Channel channel, WSBaseResp wsBaseResp) {
|
@Override
|
||||||
|
public void sendToAllOnline(WSBaseResp<?> wsBaseResp) {
|
||||||
|
sendToAllOnline(wsBaseResp, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMsg(Channel channel, WSBaseResp<?> wsBaseResp) {
|
||||||
channel.writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(wsBaseResp)));
|
channel.writeAndFlush(new TextWebSocketFrame(JSONUtil.toJsonStr(wsBaseResp)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
pom.xml
1
pom.xml
@@ -26,7 +26,6 @@
|
|||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<skipTests>true</skipTests>
|
<skipTests>true</skipTests>
|
||||||
<docker.host>http://192.168.3.101:2375</docker.host>
|
<docker.host>http://192.168.3.101:2375</docker.host>
|
||||||
<docker.maven.plugin.version>0.40.2</docker.maven.plugin.version>
|
|
||||||
<hutool.version>5.8.18</hutool.version>
|
<hutool.version>5.8.18</hutool.version>
|
||||||
<springfox-swagger.version>3.0.0</springfox-swagger.version>
|
<springfox-swagger.version>3.0.0</springfox-swagger.version>
|
||||||
<swagger-models.version>1.6.0</swagger-models.version>
|
<swagger-models.version>1.6.0</swagger-models.version>
|
||||||
|
|||||||
Reference in New Issue
Block a user