From 13dc04d4af5b8b8e780c7e7006050711c39f1836 Mon Sep 17 00:00:00 2001 From: zhongzb <972627721@qq.com> Date: Sat, 10 Jun 2023 23:34:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=201.=E5=89=8D=E5=90=8E=E7=AB=AF=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E6=94=B9=E7=89=88=202.=E8=89=BE=E7=89=B9=E6=88=90?= =?UTF-8?q?=E5=91=98=E5=8A=9F=E8=83=BD=203.=E7=94=A8=E6=88=B7=E5=90=8D?= =?UTF-8?q?=E7=89=87=E5=8D=A1=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/domain/entity/MessageMark.java | 6 +- .../chat/domain/entity/msg/MessageExtra.java | 3 + .../common/common/constant/RedisKey.java | 10 +++ .../cache/AbstractRedisStringCache.java | 66 ++++++++++++++++++ .../common/service/cache/BatchCache.java | 16 +++++ .../discover/AbstractUrlTitleDiscover.java | 2 +- .../common/user/dao/UserBackpackDao.java | 7 ++ .../mallchat/common/user/dao/UserDao.java | 13 ++++ .../common/user/domain/dto/ItemInfoDTO.java | 27 ++++++++ .../user/domain/dto/SummeryInfoDTO.java | 35 ++++++++++ .../common/user/domain/entity/Black.java | 6 +- .../common/user/domain/entity/ItemConfig.java | 6 +- .../common/user/domain/entity/Role.java | 6 +- .../user/domain/entity/UserBackpack.java | 6 +- .../common/user/service/cache/UserCache.java | 15 ++++ .../user/service/cache/UserInfoCache.java | 40 +++++++++++ .../user/service/cache/UserSummaryCache.java | 68 +++++++++++++++++++ .../user/service/impl/IpServiceImpl.java | 15 ++-- .../chat/controller/ChatController.java | 31 ++++----- .../vo/request/ChatMessageMemberReq.java | 24 +++++++ .../domain/vo/request/ChatMessageReq.java | 7 -- .../domain/vo/request/msg/TextMsgReq.java | 5 ++ .../vo/response/ChatMemberListResp.java | 25 +++++++ .../domain/vo/response/msg/TextMsgResp.java | 3 + .../custom/chat/service/ChatService.java | 13 ++-- .../chat/service/adapter/MessageAdapter.java | 8 --- .../chat/service/impl/ChatServiceImpl.java | 30 +++++--- .../strategy/msg/AbstractMsgHandler.java | 2 +- .../strategy/msg/RecallMsgHandler.java | 2 +- .../service/strategy/msg/TextMsgHandler.java | 37 +++++++++- .../event/listener/ItemReceiveListener.java | 2 +- .../user/controller/UserController.java | 18 ++++- .../domain/vo/request/user/ItemInfoReq.java | 34 ++++++++++ .../vo/request/user/SummeryInfoReq.java | 34 ++++++++++ .../custom/user/service/UserService.java | 16 ++++- .../user/service/impl/UserServiceImpl.java | 53 +++++++++++++-- 36 files changed, 604 insertions(+), 87 deletions(-) create mode 100644 mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/AbstractRedisStringCache.java create mode 100644 mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/BatchCache.java create mode 100644 mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/ItemInfoDTO.java create mode 100644 mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/SummeryInfoDTO.java create mode 100644 mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserInfoCache.java create mode 100644 mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserSummaryCache.java create mode 100644 mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageMemberReq.java create mode 100644 mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberListResp.java create mode 100644 mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/ItemInfoReq.java create mode 100644 mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/SummeryInfoReq.java diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java index 25a551c..a6cd1e0 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/MessageMark.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -63,13 +63,13 @@ public class MessageMark implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java index 94dfcfc..32c04c1 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/chat/domain/entity/msg/MessageExtra.java @@ -7,6 +7,7 @@ import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; +import java.util.List; import java.util.Map; /** @@ -25,4 +26,6 @@ public class MessageExtra implements Serializable { private Map urlTitleMap; //消息撤回详情 private MsgRecall recall; + //艾特的uid + private List atUidList; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java index c0c5efc..faa6bd2 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/constant/RedisKey.java @@ -26,6 +26,16 @@ public class RedisKey { */ public static final String USER_TOKEN_STRING = "userToken:uid_%d"; + /** + * 用户的信息更新时间 + */ + public static final String USER_MODIFY_STRING = "userModify:uid_%d"; + + /** + * 用户的信息汇总 + */ + public static final String USER_SUMMARY_STRING = "userSummary:uid_%d"; + public static String getKey(String key, Object... objects) { return BASE_KEY + String.format(key, objects); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/AbstractRedisStringCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/AbstractRedisStringCache.java new file mode 100644 index 0000000..37f2d90 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/AbstractRedisStringCache.java @@ -0,0 +1,66 @@ +package com.abin.mallchat.common.common.service.cache; + +import cn.hutool.core.collection.CollectionUtil; +import com.abin.mallchat.common.common.utils.RedisUtils; +import org.springframework.data.util.Pair; + +import java.lang.reflect.ParameterizedType; +import java.util.*; +import java.util.stream.Collectors; + +/** + * Description: redis string类型的批量缓存框架 + * Author: abin + * Date: 2023-06-10 + */ +public abstract class AbstractRedisStringCache implements BatchCache { + + private Class outClass; + + public AbstractRedisStringCache() { + ParameterizedType genericSuperclass = (ParameterizedType) this.getClass().getGenericSuperclass(); + this.outClass = (Class) genericSuperclass.getActualTypeArguments()[1]; + } + + protected abstract String getKey(IN req); + + protected abstract Long getExpireSeconds(); + + protected abstract Map load(List req); + + @Override + public OUT get(IN req) { + return getBatch(Collections.singletonList(req)).get(req); + } + + @Override + public Map getBatch(List req) { + List keys = req.stream().map(this::getKey).collect(Collectors.toList()); + List valueList = RedisUtils.mget(keys, outClass); + List loadReqs = new ArrayList<>(); + for (int i = 0; i < valueList.size(); i++) { + if (Objects.isNull(valueList.get(i))) { + loadReqs.add(req.get(i)); + } + } + Map load = new HashMap<>(); + //不足的重新加载进redis + if (CollectionUtil.isNotEmpty(loadReqs)) { + load = load(loadReqs); + Map loadMap = load.entrySet().stream() + .map(a -> Pair.of(getKey(a.getKey()), a.getValue())) + .collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)); + RedisUtils.mset(loadMap, getExpireSeconds()); + } + + //组装最后的结果 + Map resultMap = new HashMap<>(); + for (int i = 0; i < req.size(); i++) { + IN in = req.get(i); + OUT out = Optional.ofNullable(valueList.get(i)) + .orElse(load.get(in)); + resultMap.put(in, out); + } + return resultMap; + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/BatchCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/BatchCache.java new file mode 100644 index 0000000..1d97529 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/service/cache/BatchCache.java @@ -0,0 +1,16 @@ +package com.abin.mallchat.common.common.service.cache; + +import java.util.List; +import java.util.Map; + +public interface BatchCache { + /** + * 获取单个 + */ + OUT get(IN req); + + /** + * 获取批量 + */ + Map getBatch(List req); +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java index cb13478..79cbefe 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/utils/discover/AbstractUrlTitleDiscover.java @@ -66,7 +66,7 @@ public abstract class AbstractUrlTitleDiscover implements UrlTitleDiscover { protected Document getUrlDocument(String matchUrl) { try { Connection connect = Jsoup.connect(matchUrl); - connect.timeout(1000); + connect.timeout(2000); return connect.get(); } catch (Exception e) { log.error("find title error:url:{}", matchUrl, e); diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java index 0bcd4ab..a0a33fa 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserBackpackDao.java @@ -51,6 +51,13 @@ public class UserBackpackDao extends ServiceImpl getByItemIds(List uids, List itemIds) { + return lambdaQuery().in(UserBackpack::getUid, uids) + .in(UserBackpack::getItemId, itemIds) + .eq(UserBackpack::getStatus, YesOrNoEnum.NO.getStatus()) + .list(); + } + public UserBackpack getByIdp(String idempotent) { return lambdaQuery().eq(UserBackpack::getIdempotent, idempotent).one(); } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java index 8184271..659220c 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/dao/UserDao.java @@ -1,5 +1,6 @@ package com.abin.mallchat.common.user.dao; +import com.abin.mallchat.common.common.domain.enums.NormalOrNoEnum; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.mapper.UserMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -7,6 +8,8 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.List; + /** *

* 用户表 服务实现类 @@ -40,4 +43,14 @@ public class UserDao extends ServiceImpl { public User getByName(String name) { return lambdaQuery().eq(User::getName, name).one(); } + + public List getMemberList() { + return lambdaQuery() + .eq(User::getStatus, NormalOrNoEnum.NORMAL.getStatus()) + .orderByDesc(User::getUpdateTime)//最近活跃的1000个人,可以用lastOptTime字段,但是该字段没索引,updateTime可平替 + .last("limit 1000")//毕竟是大群聊,人数需要做个限制 + .select(User::getId, User::getName, User::getAvatar) + .list(); + + } } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/ItemInfoDTO.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/ItemInfoDTO.java new file mode 100644 index 0000000..3fda5c5 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/ItemInfoDTO.java @@ -0,0 +1,27 @@ +package com.abin.mallchat.common.user.domain.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + + +/** + * Description: 修改用户名 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ItemInfoDTO { + @ApiModelProperty(value = "徽章id") + private Long itemId; + @ApiModelProperty("徽章图像") + private String img; + @ApiModelProperty("徽章说明") + private String describe; + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/SummeryInfoDTO.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/SummeryInfoDTO.java new file mode 100644 index 0000000..70751d8 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/dto/SummeryInfoDTO.java @@ -0,0 +1,35 @@ +package com.abin.mallchat.common.user.domain.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + + +/** + * Description: 修改用户名 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SummeryInfoDTO { + @ApiModelProperty(value = "用户id") + private Long uid; + @ApiModelProperty(value = "用户昵称") + private String name; + @ApiModelProperty(value = "用户头像") + private String avatar; + @ApiModelProperty(value = "归属地") + private String locPlace; + @ApiModelProperty("佩戴的徽章id") + private Long wearingItemId; + @ApiModelProperty(value = "用户拥有的徽章id列表") + List itemIds; + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java index ff8b82a..15178d4 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Black.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -49,13 +49,13 @@ public class Black implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java index a46646b..3232c0a 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/ItemConfig.java @@ -7,7 +7,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -52,13 +52,13 @@ public class ItemConfig implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java index 4fac5a1..b139c41 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/Role.java @@ -8,7 +8,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -41,13 +41,13 @@ public class Role implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java index da96761..8952541 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/UserBackpack.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.io.Serializable; -import java.time.LocalDateTime; +import java.util.Date; /** *

@@ -61,13 +61,13 @@ public class UserBackpack implements Serializable { * 创建时间 */ @TableField("create_time") - private LocalDateTime createTime; + private Date createTime; /** * 修改时间 */ @TableField("update_time") - private LocalDateTime updateTime; + private Date updateTime; } diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java index 4302ac3..44b7321 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java @@ -95,6 +95,16 @@ public class UserCache { return cursorUtils.getCursorPageByRedis(pageBaseReq, RedisKey.getKey(RedisKey.OFFLINE_UID_ZET), Long::parseLong); } + public List getUserModifyTime(List uidList) { + List keys = uidList.stream().map(uid -> RedisKey.getKey(RedisKey.USER_MODIFY_STRING, uid)).collect(Collectors.toList()); + return RedisUtils.mget(keys, Long.class); + } + + public void refreshUserModifyTime(Long uid) { + String key = RedisKey.getKey(RedisKey.USER_MODIFY_STRING, uid); + RedisUtils.set(key, new Date().getTime()); + } + /** * 获取用户信息,盘路缓存模式 */ @@ -120,6 +130,11 @@ public class UserCache { return map; } + public void userInfoChange(Long uid) { + delUserInfo(uid); + refreshUserModifyTime(uid); + } + public void delUserInfo(Long uid) { String key = RedisKey.getKey(RedisKey.USER_INFO_STRING, uid); RedisUtils.del(key); diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserInfoCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserInfoCache.java new file mode 100644 index 0000000..df93121 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserInfoCache.java @@ -0,0 +1,40 @@ +package com.abin.mallchat.common.user.service.cache; + +import com.abin.mallchat.common.common.constant.RedisKey; +import com.abin.mallchat.common.common.service.cache.AbstractRedisStringCache; +import com.abin.mallchat.common.user.dao.UserDao; +import com.abin.mallchat.common.user.domain.entity.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Description: 用户基本信息的缓存 + * Author: abin + * Date: 2023-06-10 + */ +@Component +public class UserInfoCache extends AbstractRedisStringCache { + @Autowired + private UserDao userDao; + + @Override + protected String getKey(Long uid) { + return RedisKey.getKey(RedisKey.USER_INFO_STRING, uid); + } + + @Override + protected Long getExpireSeconds() { + return 5 * 60L; + } + + @Override + protected Map load(List uidList) { + List needLoadUserList = userDao.listByIds(uidList); + return needLoadUserList.stream().collect(Collectors.toMap(User::getId, Function.identity())); + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserSummaryCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserSummaryCache.java new file mode 100644 index 0000000..faa8017 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserSummaryCache.java @@ -0,0 +1,68 @@ +package com.abin.mallchat.common.user.service.cache; + +import com.abin.mallchat.common.common.constant.RedisKey; +import com.abin.mallchat.common.common.service.cache.AbstractRedisStringCache; +import com.abin.mallchat.common.user.dao.UserBackpackDao; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; +import com.abin.mallchat.common.user.domain.entity.*; +import com.abin.mallchat.common.user.domain.enums.ItemTypeEnum; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Description: 用户所有信息的缓存 + * Author: abin + * Date: 2023-06-10 + */ +@Component +public class UserSummaryCache extends AbstractRedisStringCache { + @Autowired + private UserInfoCache userInfoCache; + @Autowired + private UserBackpackDao userBackpackDao; + @Autowired + private ItemCache itemCache; + + @Override + protected String getKey(Long uid) { + return RedisKey.getKey(RedisKey.USER_SUMMARY_STRING, uid); + } + + @Override + protected Long getExpireSeconds() { + return 10 * 60L; + } + + @Override + protected Map load(List uidList) {//后续可优化徽章信息也异步加载 + //用户基本信息 + Map userMap = userInfoCache.getBatch(uidList); + //用户徽章信息 + List itemConfigs = itemCache.getByType(ItemTypeEnum.BADGE.getType()); + List itemIds = itemConfigs.stream().map(ItemConfig::getId).collect(Collectors.toList()); + List backpacks = userBackpackDao.getByItemIds(uidList, itemIds); + Map> userBadgeMap = backpacks.stream().collect(Collectors.groupingBy(UserBackpack::getUid)); + //用户最后一次更新时间 + return uidList.stream().map(uid -> { + SummeryInfoDTO summeryInfoDTO = new SummeryInfoDTO(); + User user = userMap.get(uid); + if (Objects.isNull(user)) { + return null; + } + List userBackpacks = userBadgeMap.getOrDefault(user.getId(), new ArrayList<>()); + summeryInfoDTO.setUid(user.getId()); + summeryInfoDTO.setName(user.getName()); + summeryInfoDTO.setAvatar(user.getAvatar()); + summeryInfoDTO.setLocPlace(Optional.ofNullable(user.getIpInfo()).map(IpInfo::getUpdateIpDetail).map(IpDetail::getCity).orElse(null)); + summeryInfoDTO.setWearingItemId(user.getItemId()); + summeryInfoDTO.setItemIds(userBackpacks.stream().map(UserBackpack::getItemId).collect(Collectors.toList())); + return summeryInfoDTO; + }) + .filter(Objects::nonNull) + .collect(Collectors.toMap(SummeryInfoDTO::getUid, Function.identity())); + } +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java index 7207166..e6513ab 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/impl/IpServiceImpl.java @@ -1,7 +1,6 @@ package com.abin.mallchat.common.user.service.impl; import cn.hutool.core.lang.TypeReference; - import cn.hutool.core.thread.NamedThreadFactory; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; @@ -13,7 +12,7 @@ import com.abin.mallchat.common.user.domain.entity.IpDetail; import com.abin.mallchat.common.user.domain.entity.IpInfo; import com.abin.mallchat.common.user.domain.entity.User; import com.abin.mallchat.common.user.service.IpService; -import jodd.util.concurrent.ThreadFactoryBuilder; +import com.abin.mallchat.common.user.service.cache.UserCache; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.annotation.Autowired; @@ -21,7 +20,10 @@ import org.springframework.stereotype.Service; import java.util.Date; import java.util.Objects; -import java.util.concurrent.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * Description: ip @@ -34,13 +36,13 @@ public class IpServiceImpl implements IpService, DisposableBean { private static ExecutorService executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(500), - new NamedThreadFactory("refresh-ipDetail", (ThreadGroup)null,false, + new NamedThreadFactory("refresh-ipDetail", (ThreadGroup) null, false, new GlobalUncaughtExceptionHandler())); @Autowired private UserDao userDao; - - + @Autowired + private UserCache userCache; @Override @@ -62,6 +64,7 @@ public class IpServiceImpl implements IpService, DisposableBean { update.setId(uid); update.setIpInfo(ipInfo); userDao.updateById(update); + userCache.userInfoChange(uid); } else { log.error("get ip detail fail ip:{},uid:{}", ip, uid); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java index a42dd25..65200ae 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java @@ -8,15 +8,8 @@ import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; import com.abin.mallchat.common.common.utils.RequestHolder; import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; -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.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.*; import com.abin.mallchat.custom.chat.service.ChatService; import com.abin.mallchat.custom.user.service.impl.UserServiceImpl; import io.swagger.annotations.Api; @@ -27,7 +20,7 @@ import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.util.HashSet; -import java.util.Objects; +import java.util.List; import java.util.Set; /** @@ -56,14 +49,20 @@ public class ChatController { @GetMapping("/public/member/page") @ApiOperation("群成员列表") - @FrequencyControl(time = 120, count = 10, target = FrequencyControl.Target.IP) + @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP) public ApiResult> getMemberPage(@Valid CursorPageBaseReq request) { - black(request); +// black(request); CursorPageBaseResp memberPage = chatService.getMemberPage(request); filterBlackMember(memberPage); return ApiResult.success(memberPage); } + @GetMapping("/member/list") + @ApiOperation("房间内的所有群成员列表-@专用") + public ApiResult> getMemberList(@Valid ChatMessageMemberReq chatMessageMemberReq) { + return ApiResult.success(chatService.getMemberList(chatMessageMemberReq)); + } + private void filterBlackMember(CursorPageBaseResp memberPage) { Set blackMembers = getBlackUidSet(); memberPage.getList().removeIf(a -> blackMembers.contains(a.getUid().toString())); @@ -84,9 +83,9 @@ public class ChatController { @GetMapping("/public/msg/page") @ApiOperation("消息列表") - @FrequencyControl(time = 120, count = 10, target = FrequencyControl.Target.IP) + @FrequencyControl(time = 120, count = 20, target = FrequencyControl.Target.IP) public ApiResult> getMsgPage(@Valid ChatMessagePageReq request) { - black(request); +// black(request); CursorPageBaseResp msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid()); filterBlackMsg(msgPage); return ApiResult.success(msgPage); @@ -113,10 +112,6 @@ public class ChatController { @FrequencyControl(time = 30, count = 5, target = FrequencyControl.Target.UID) @FrequencyControl(time = 60, count = 10, target = FrequencyControl.Target.UID) public ApiResult sendMsg(@Valid @RequestBody ChatMessageReq request) { - if (Objects.isNull(request.getBody())) { - TextMsgReq req = new TextMsgReq(request.getContent(), request.getReplyMsgId());//todo 消息兼容之后删了 - request.setBody(req); - } Long msgId = chatService.sendMsg(request, RequestHolder.get().getUid()); //返回完整消息格式,方便前端展示 return ApiResult.success(chatService.getMsgResp(msgId, RequestHolder.get().getUid())); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageMemberReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageMemberReq.java new file mode 100644 index 0000000..4354cb0 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageMemberReq.java @@ -0,0 +1,24 @@ +package com.abin.mallchat.custom.chat.domain.vo.request; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.NotNull; + +/** + * Description: 消息列表请求 + * Author: abin + * Date: 2023-03-29 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChatMessageMemberReq { + @NotNull + @ApiModelProperty("会话id") + private Long roomId; +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java index eb2041b..ac3063d 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/ChatMessageReq.java @@ -30,11 +30,4 @@ public class ChatMessageReq { @ApiModelProperty("消息内容,类型不同传值不同,见https://www.yuque.com/snab/mallcaht/rkb2uz5k1qqdmcmd") private Object body; - @ApiModelProperty("消息内容") - @Deprecated - private String content; - - @ApiModelProperty("回复的消息id,如果没有别传就好") - @Deprecated - private Long replyMsgId; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java index 841c75b..a58d6b8 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/request/msg/TextMsgReq.java @@ -6,6 +6,8 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.util.List; + /** * Description: 文本消息入参 * Author: abin @@ -22,4 +24,7 @@ public class TextMsgReq { @ApiModelProperty("回复的消息id,如果没有别传就好") private Long replyMsgId; + + @ApiModelProperty("艾特的uid") + private List atUidList; } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberListResp.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberListResp.java new file mode 100644 index 0000000..9ba50a4 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/ChatMemberListResp.java @@ -0,0 +1,25 @@ +package com.abin.mallchat.custom.chat.domain.vo.response; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * Description: 群成员列表的成员信息 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ChatMemberListResp { + @ApiModelProperty("uid") + private Long uid; + @ApiModelProperty("用户名称") + private String name; + @ApiModelProperty("头像") + private String avatar; +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java index 5b7d18b..34db6c5 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/domain/vo/response/msg/TextMsgResp.java @@ -6,6 +6,7 @@ import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import java.util.List; import java.util.Map; /** @@ -22,6 +23,8 @@ public class TextMsgResp { private String content; @ApiModelProperty("消息链接映射") private Map urlTitleMap; + @ApiModelProperty("艾特的uid") + private List atUidList; @ApiModelProperty("父消息,如果没有父消息,返回的是null") private TextMsgResp.ReplyMsg reply; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java index bbf4778..43e00cc 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/ChatService.java @@ -3,16 +3,11 @@ package com.abin.mallchat.custom.chat.service; import com.abin.mallchat.common.chat.domain.entity.Message; import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq; import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; -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.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.*; import javax.annotation.Nullable; +import java.util.List; /** * Description: 消息处理类 @@ -76,4 +71,6 @@ public interface ChatService { void setMsgMark(Long uid, ChatMessageMarkReq request); void recallMsg(Long uid, ChatMessageBaseReq request); + + List getMemberList(ChatMessageMemberReq chatMessageMemberReq); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java index aa4f4a4..dd49ed8 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/adapter/MessageAdapter.java @@ -7,7 +7,6 @@ import com.abin.mallchat.common.chat.domain.entity.msg.MessageExtra; import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum; import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum; import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum; -import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover; import com.abin.mallchat.common.user.domain.entity.IpDetail; import com.abin.mallchat.common.user.domain.entity.IpInfo; import com.abin.mallchat.common.user.domain.entity.ItemConfig; @@ -27,7 +26,6 @@ import java.util.stream.Collectors; */ public class MessageAdapter { public static final int CAN_CALLBACK_GAP_COUNT = 100; - private static final PrioritizedUrlTitleDiscover URL_TITLE_DISCOVER = new PrioritizedUrlTitleDiscover(); public static Message buildMsgSave(ChatMessageReq request, Long uid) { @@ -35,16 +33,10 @@ public class MessageAdapter { .fromUid(uid) .roomId(request.getRoomId()) .status(MessageStatusEnum.NORMAL.getStatus()) - .extra(buildExtra(request)) .build(); } - private static MessageExtra buildExtra(ChatMessageReq request) { - Map contentTitleMap = URL_TITLE_DISCOVER.getContentTitleMap(request.getContent()); - return MessageExtra.builder().urlTitleMap(contentTitleMap).build(); - } - public static List buildMsgResp(List messages, Map replyMap, Map userMap, List msgMark, Long receiveUid, Map itemMap) { Map> markMap = msgMark.stream().collect(Collectors.groupingBy(MessageMark::getMsgId)); return messages.stream().map(a -> { diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java index 355fca8..adbb1d3 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/impl/ChatServiceImpl.java @@ -26,14 +26,8 @@ import com.abin.mallchat.common.user.domain.enums.RoleEnum; import com.abin.mallchat.common.user.service.IRoleService; import com.abin.mallchat.common.user.service.cache.ItemCache; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageBaseReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq; -import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; -import com.abin.mallchat.custom.chat.domain.vo.response.ChatMemberResp; -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.ChatRoomResp; +import com.abin.mallchat.custom.chat.domain.vo.request.*; +import com.abin.mallchat.custom.chat.domain.vo.response.*; import com.abin.mallchat.custom.chat.service.ChatService; import com.abin.mallchat.custom.chat.service.adapter.MemberAdapter; import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter; @@ -45,7 +39,9 @@ import com.abin.mallchat.custom.chat.service.strategy.msg.AbstractMsgHandler; import com.abin.mallchat.custom.chat.service.strategy.msg.MsgHandlerFactory; import com.abin.mallchat.custom.chat.service.strategy.msg.RecallMsgHandler; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -92,7 +88,7 @@ public class ChatServiceImpl implements ChatService { @Transactional public Long sendMsg(ChatMessageReq request, Long uid) { AbstractMsgHandler msgHandler = MsgHandlerFactory.getStrategyNoNull(request.getMsgType());//todo 这里先不扩展,后续再改 - msgHandler.checkMsg(request); + msgHandler.checkMsg(request, uid); //同步获取消息的跳转链接标题 Message insert = MessageAdapter.buildMsgSave(request, uid); messageDao.save(insert); @@ -196,6 +192,22 @@ public class ChatServiceImpl implements ChatService { recallMsgHandler.recall(uid, message); } + @Override + @Cacheable(cacheNames = "member", key = "'memberList.'+#req.roomId") + public List getMemberList(ChatMessageMemberReq req) { + if (Objects.equals(1L, req.getRoomId())) {//大群聊可看见所有人 + return userDao.getMemberList() + .stream() + .map(a -> { + ChatMemberListResp resp = new ChatMemberListResp(); + BeanUtils.copyProperties(a, resp); + resp.setUid(a.getId()); + return resp; + }).collect(Collectors.toList()); + } + return null; + } + private void checkRecall(Long uid, Message message) { AssertUtil.isNotEmpty(message, "消息有误"); AssertUtil.notEqual(message.getType(), MessageTypeEnum.RECALL, "消息无法撤回"); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java index 5c88033..1715937 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/AbstractMsgHandler.java @@ -20,7 +20,7 @@ public abstract class AbstractMsgHandler { abstract MessageTypeEnum getMsgTypeEnum(); - public abstract void checkMsg(ChatMessageReq req); + public abstract void checkMsg(ChatMessageReq req, Long uid); public abstract void saveMsg(Message msg, ChatMessageReq req); diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java index 3bba9e7..a5fd9e4 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/RecallMsgHandler.java @@ -40,7 +40,7 @@ public class RecallMsgHandler extends AbstractMsgHandler { } @Override - public void checkMsg(ChatMessageReq request) { + public void checkMsg(ChatMessageReq request, Long uid) { throw new UnsupportedOperationException(); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java index 08a8e84..33762ca 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/service/strategy/msg/TextMsgHandler.java @@ -9,15 +9,22 @@ import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum; import com.abin.mallchat.common.chat.service.cache.MsgCache; import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum; import com.abin.mallchat.common.common.utils.AssertUtil; +import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover; import com.abin.mallchat.common.user.domain.entity.User; +import com.abin.mallchat.common.user.domain.enums.RoleEnum; +import com.abin.mallchat.common.user.service.IRoleService; import com.abin.mallchat.common.user.service.cache.UserCache; +import com.abin.mallchat.common.user.service.cache.UserInfoCache; import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq; import com.abin.mallchat.custom.chat.domain.vo.request.msg.TextMsgReq; import com.abin.mallchat.custom.chat.domain.vo.response.msg.TextMsgResp; import com.abin.mallchat.custom.chat.service.adapter.MessageAdapter; +import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -34,6 +41,12 @@ public class TextMsgHandler extends AbstractMsgHandler { private MsgCache msgCache; @Autowired private UserCache userCache; + @Autowired + private UserInfoCache userInfoCache; + @Autowired + private IRoleService iRoleService; + @Autowired + private static final PrioritizedUrlTitleDiscover URL_TITLE_DISCOVER = new PrioritizedUrlTitleDiscover(); @Override MessageTypeEnum getMsgTypeEnum() { @@ -41,7 +54,7 @@ public class TextMsgHandler extends AbstractMsgHandler { } @Override - public void checkMsg(ChatMessageReq request) { + public void checkMsg(ChatMessageReq request, Long uid) { TextMsgReq body = BeanUtil.toBean(request.getBody(), TextMsgReq.class); AssertUtil.isNotEmpty(body.getContent(), "内容不能为空"); AssertUtil.isTrue(body.getContent().length() < 500, "消息内容过长,服务器扛不住啊,兄dei"); @@ -51,14 +64,26 @@ public class TextMsgHandler extends AbstractMsgHandler { AssertUtil.isNotEmpty(replyMsg, "回复消息不存在"); AssertUtil.equal(replyMsg.getRoomId(), request.getRoomId(), "只能回复相同会话内的消息"); } + if (CollectionUtils.isNotEmpty(body.getAtUidList())) { + AssertUtil.isTrue(body.getAtUidList().size() > 10, "一次别艾特这么多人"); + List atUidList = body.getAtUidList(); + Map batch = userInfoCache.getBatch(atUidList); + AssertUtil.equal(atUidList.size(), batch.values().size(), "@用户不存在"); + boolean atAll = body.getAtUidList().contains(0L); + if (atAll) { + AssertUtil.isTrue(iRoleService.hasPower(uid, RoleEnum.CHAT_MANAGER), "没有权限"); + } + } } @Override public void saveMsg(Message msg, ChatMessageReq request) {//插入文本内容 TextMsgReq body = BeanUtil.toBean(request.getBody(), TextMsgReq.class); + MessageExtra extra = Optional.ofNullable(msg.getExtra()).orElse(new MessageExtra()); Message update = new Message(); update.setId(msg.getId()); update.setContent(body.getContent()); + update.setExtra(extra); //如果有回复消息 if (Objects.nonNull(body.getReplyMsgId())) { Integer gapCount = messageDao.getGapCount(request.getRoomId(), body.getReplyMsgId(), msg.getId()); @@ -66,6 +91,15 @@ public class TextMsgHandler extends AbstractMsgHandler { update.setReplyMsgId(body.getReplyMsgId()); } + //判断消息url跳转 + Map urlTitleMap = URL_TITLE_DISCOVER.getContentTitleMap(body.getContent()); + extra.setUrlTitleMap(urlTitleMap); + //艾特功能 + if (CollectionUtils.isNotEmpty(body.getAtUidList())) { + extra.setAtUidList(body.getAtUidList()); + + } + messageDao.updateById(update); } @@ -74,6 +108,7 @@ public class TextMsgHandler extends AbstractMsgHandler { TextMsgResp resp = new TextMsgResp(); resp.setContent(msg.getContent()); resp.setUrlTitleMap(Optional.ofNullable(msg.getExtra()).map(MessageExtra::getUrlTitleMap).orElse(null)); + resp.setAtUidList(Optional.ofNullable(msg.getExtra()).map(MessageExtra::getAtUidList).orElse(null)); //回复消息 Optional reply = Optional.ofNullable(msg.getReplyMsgId()) .map(msgCache::getMsg) diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java index 143b8fb..11aa871 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/event/listener/ItemReceiveListener.java @@ -45,7 +45,7 @@ public class ItemReceiveListener { User user = userDao.getById(userBackpack.getUid()); if (Objects.isNull(user.getItemId())) { userDao.wearingBadge(userBackpack.getUid(), userBackpack.getItemId()); - userCache.delUserInfo(userBackpack.getUid()); + userCache.userInfoChange(userBackpack.getUid()); } } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java index bd1c1a7..3380edc 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/controller/UserController.java @@ -4,11 +4,11 @@ package com.abin.mallchat.custom.user.controller; import com.abin.mallchat.common.common.domain.vo.response.ApiResult; import com.abin.mallchat.common.common.utils.AssertUtil; import com.abin.mallchat.common.common.utils.RequestHolder; +import com.abin.mallchat.common.user.domain.dto.ItemInfoDTO; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; import com.abin.mallchat.common.user.domain.enums.RoleEnum; import com.abin.mallchat.common.user.service.IRoleService; -import com.abin.mallchat.custom.user.domain.vo.request.user.BlackReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.ModifyNameReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.WearingBadgeReq; +import com.abin.mallchat.custom.user.domain.vo.request.user.*; import com.abin.mallchat.custom.user.domain.vo.response.user.BadgeResp; import com.abin.mallchat.custom.user.domain.vo.response.user.UserInfoResp; import com.abin.mallchat.custom.user.service.UserService; @@ -43,6 +43,18 @@ public class UserController { return ApiResult.success(userService.getUserInfo(RequestHolder.get().getUid())); } + @PostMapping("/public/summary/userInfo/batch") + @ApiOperation("用户聚合信息-返回的代表需要刷新的") + public ApiResult> getSummeryUserInfo(@Valid @RequestBody SummeryInfoReq req) { + return ApiResult.success(userService.getSummeryUserInfo(req)); + } + + @PostMapping("/public/badges/batch") + @ApiOperation("徽章聚合信息-返回的代表需要刷新的") + public ApiResult> getItemInfo(@Valid @RequestBody ItemInfoReq req) { + return ApiResult.success(userService.getItemInfo(req)); + } + @PutMapping("/name") @ApiOperation("修改用户名") public ApiResult modifyName(@Valid @RequestBody ModifyNameReq req) { diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/ItemInfoReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/ItemInfoReq.java new file mode 100644 index 0000000..8d60c86 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/ItemInfoReq.java @@ -0,0 +1,34 @@ +package com.abin.mallchat.custom.user.domain.vo.request.user; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Size; +import java.util.List; + + +/** + * Description: 批量查询徽章详情 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ItemInfoReq { + @ApiModelProperty(value = "徽章信息入参") + @Size(max = 50) + private List reqList; + + @Data + public static class infoReq { + @ApiModelProperty(value = "徽章id") + private Long itemId; + @ApiModelProperty(value = "最近一次更新徽章信息时间") + private Long lastModifyTime; + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/SummeryInfoReq.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/SummeryInfoReq.java new file mode 100644 index 0000000..79b9ad2 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/request/user/SummeryInfoReq.java @@ -0,0 +1,34 @@ +package com.abin.mallchat.custom.user.domain.vo.request.user; + +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.constraints.Size; +import java.util.List; + + +/** + * Description: 批量查询用户汇总详情 + * Author: abin + * Date: 2023-03-23 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SummeryInfoReq { + @ApiModelProperty(value = "用户信息入参") + @Size(max = 50) + private List reqList; + + @Data + public static class infoReq { + @ApiModelProperty(value = "uid") + private Long uid; + @ApiModelProperty(value = "最近一次更新用户信息时间") + private Long lastModifyTime; + } +} diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java index a8a8e0e..2cb2259 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/UserService.java @@ -1,8 +1,8 @@ package com.abin.mallchat.custom.user.service; -import com.abin.mallchat.custom.user.domain.vo.request.user.BlackReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.ModifyNameReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.WearingBadgeReq; +import com.abin.mallchat.common.user.domain.dto.ItemInfoDTO; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; +import com.abin.mallchat.custom.user.domain.vo.request.user.*; import com.abin.mallchat.custom.user.domain.vo.response.user.BadgeResp; import com.abin.mallchat.custom.user.domain.vo.response.user.UserInfoResp; @@ -57,4 +57,14 @@ public interface UserService { void register(String openId); void black(BlackReq req); + + /** + * 获取用户汇总信息 + * + * @param req + * @return + */ + List getSummeryUserInfo(SummeryInfoReq req); + + List getItemInfo(ItemInfoReq req); } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java index 53811fa..f8c0106 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/service/impl/UserServiceImpl.java @@ -8,6 +8,8 @@ import com.abin.mallchat.common.user.dao.BlackDao; import com.abin.mallchat.common.user.dao.ItemConfigDao; import com.abin.mallchat.common.user.dao.UserBackpackDao; import com.abin.mallchat.common.user.dao.UserDao; +import com.abin.mallchat.common.user.domain.dto.ItemInfoDTO; +import com.abin.mallchat.common.user.domain.dto.SummeryInfoDTO; import com.abin.mallchat.common.user.domain.entity.Black; import com.abin.mallchat.common.user.domain.entity.ItemConfig; import com.abin.mallchat.common.user.domain.entity.User; @@ -17,9 +19,8 @@ import com.abin.mallchat.common.user.domain.enums.ItemEnum; import com.abin.mallchat.common.user.domain.enums.ItemTypeEnum; import com.abin.mallchat.common.user.service.cache.ItemCache; import com.abin.mallchat.common.user.service.cache.UserCache; -import com.abin.mallchat.custom.user.domain.vo.request.user.BlackReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.ModifyNameReq; -import com.abin.mallchat.custom.user.domain.vo.request.user.WearingBadgeReq; +import com.abin.mallchat.common.user.service.cache.UserSummaryCache; +import com.abin.mallchat.custom.user.domain.vo.request.user.*; import com.abin.mallchat.custom.user.domain.vo.response.user.BadgeResp; import com.abin.mallchat.custom.user.domain.vo.response.user.UserInfoResp; import com.abin.mallchat.custom.user.service.UserService; @@ -30,7 +31,10 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -56,6 +60,8 @@ public class UserServiceImpl implements UserService { private ItemCache itemCache; @Autowired private BlackDao blackDao; + @Autowired + private UserSummaryCache userSummaryCache; @Override public UserInfoResp getUserInfo(Long uid) { @@ -79,7 +85,7 @@ public class UserServiceImpl implements UserService { //改名 userDao.modifyName(uid, req.getName()); //删除缓存 - userCache.delUserInfo(uid); + userCache.userInfoChange(uid); } } @@ -105,7 +111,7 @@ public class UserServiceImpl implements UserService { //佩戴徽章 userDao.wearingBadge(uid, req.getBadgeId()); //删除用户缓存 - userCache.delUserInfo(uid); + userCache.userInfoChange(uid); } @Override @@ -128,6 +134,43 @@ public class UserServiceImpl implements UserService { applicationEventPublisher.publishEvent(new UserBlackEvent(this, byId)); } + @Override + public List getSummeryUserInfo(SummeryInfoReq req) { + //需要前端同步的uid + List uidList = getNeedSyncUidList(req.getReqList()); + //加载用户信息 + Map batch = userSummaryCache.getBatch(uidList); + return new ArrayList<>(batch.values()); + } + + @Override + public List getItemInfo(ItemInfoReq req) {//简单做,更新时间可判断被修改 + return req.getReqList().stream().map(a -> { + ItemConfig itemConfig = itemCache.getById(a.getItemId()); + if (Objects.nonNull(a.getLastModifyTime()) && a.getLastModifyTime() >= itemConfig.getUpdateTime().getTime()) { + return null; + } + ItemInfoDTO dto = new ItemInfoDTO(); + dto.setItemId(itemConfig.getId()); + dto.setImg(itemConfig.getImg()); + dto.setDescribe(itemConfig.getDescribe()); + return dto; + }).collect(Collectors.toList()); + } + + private List getNeedSyncUidList(List reqList) { + List result = new ArrayList<>(); + List userModifyTime = userCache.getUserModifyTime(reqList.stream().map(SummeryInfoReq.infoReq::getUid).collect(Collectors.toList())); + for (int i = 0; i < reqList.size(); i++) { + SummeryInfoReq.infoReq infoReq = reqList.get(i); + Long modifyTime = userModifyTime.get(i); + if (Objects.isNull(infoReq.getLastModifyTime()) || (Objects.nonNull(modifyTime) && modifyTime > infoReq.getLastModifyTime())) { + result.add(infoReq.getUid()); + } + } + return result; + } + public void blackIp(String ip) { if (StrUtil.isBlank(ip)) { return;