1.链接跳转功能
2.归属地功能
fix:
1.修复回复跳转功能
2.优化翻页工具类
3,修复下线重置ip的bug
This commit is contained in:
zhongzb
2023-05-28 15:29:50 +08:00
parent de27f7791f
commit 53201465f2
23 changed files with 400 additions and 31 deletions

1
.gitignore vendored
View File

@@ -67,6 +67,7 @@ CodeGenerator.java
TestController.java
application-my-prod.properties
application-remote-prod.properties
application-my-test.properties
mybatis-generator-config.xml
ChannelBizRankClient.java
ChannelBizBrandWallClient.java

View File

@@ -54,6 +54,7 @@ CREATE TABLE `message` (
`status` int(11) NOT NULL COMMENT '消息状态 0正常 1删除',
`gap_count` int(11) NULL DEFAULT NULL COMMENT '与回复的消息间隔多少条',
`type` int(11) NULL DEFAULT 1 COMMENT '消息类型 1正常文本 2.爆赞 点赞超过103.危险发言举报超5',
`extra` json DEFAULT NULL COMMENT '扩展信息',
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
@@ -163,10 +164,10 @@ DROP TABLE IF EXISTS `black`;
CREATE TABLE `black` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
`type` int(11) NOT NULL COMMENT '拉黑目标类型 1.ip 2uid',
`target` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '拉黑目标',
`target` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '拉黑目标',
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `idx_type_target`(`type`, `target`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '黑名单' ROW_FORMAT = Dynamic;
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '黑名单' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -24,6 +24,11 @@
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
</dependency>
<!-- MyBatis-->
<dependency>
<groupId>org.mybatis</groupId>

View File

@@ -55,6 +55,7 @@ public class MessageDao extends ServiceImpl<MessageMapper, Message> {
public void updateGapCount(Long id, Integer gapCount) {
lambdaUpdate()
.eq(Message::getId, id)
.set(Message::getGapCount, gapCount);
.set(Message::getGapCount, gapCount)
.update();
}
}

View File

@@ -1,5 +1,6 @@
package com.abin.mallchat.common.chat.domain.entity;
import com.abin.mallchat.common.user.domain.entity.IpInfo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -8,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import java.util.Date;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
import lombok.experimental.Accessors;
@@ -21,7 +23,7 @@ import lombok.experimental.Accessors;
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("message")
@TableName(value = "message",autoResultMap = true)
@Builder
@AllArgsConstructor
@NoArgsConstructor
@@ -79,6 +81,11 @@ public class Message implements Serializable {
@TableField("type")
private Integer type;
/**
* 最后上下线时间
*/
@TableField(value = "extra", typeHandler = JacksonTypeHandler.class)
private MessageExtra extra;
/**
* 创建时间

View File

@@ -0,0 +1,25 @@
package com.abin.mallchat.common.chat.domain.entity;
import com.abin.mallchat.common.user.domain.entity.IpDetail;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Map;
/**
* Description: 消息扩展属性
* Author: <a href="https://github.com/zongzibinbin">abin</a>
* Date: 2023-05-28
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MessageExtra implements Serializable {
private static final long serialVersionUID = 1L;
//注册时的ip
private Map<String, String> urlTitleMap;
}

View File

@@ -32,22 +32,23 @@ public class CursorPageBaseResp<T> {
@ApiModelProperty("数据列表")
private List<T> list;
public static CursorPageBaseResp init(CursorPageBaseResp cursorPage, List list) {
CursorPageBaseResp cursorPageBaseResp = new CursorPageBaseResp();
public static <T> CursorPageBaseResp<T> init(CursorPageBaseResp cursorPage, List<T> list) {
CursorPageBaseResp<T> cursorPageBaseResp = new CursorPageBaseResp<T>();
cursorPageBaseResp.setIsLast(cursorPage.getIsLast());
cursorPageBaseResp.setList(list);
cursorPageBaseResp.setCursor(cursorPage.getCursor());
return cursorPageBaseResp;
}
@JsonIgnore
public Boolean isEmpty() {
return CollectionUtil.isEmpty(list);
}
public static CursorPageBaseResp empty() {
CursorPageBaseResp cursorPageBaseResp = new CursorPageBaseResp();
public static <T> CursorPageBaseResp<T> empty() {
CursorPageBaseResp<T> cursorPageBaseResp = new CursorPageBaseResp<T>();
cursorPageBaseResp.setIsLast(true);
cursorPageBaseResp.setList(new ArrayList());
cursorPageBaseResp.setList(new ArrayList<T>());
return cursorPageBaseResp;
}

View File

@@ -0,0 +1,125 @@
package com.abin.mallchat.common.common.utils;
import lombok.extern.slf4j.Slf4j;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.function.BinaryOperator;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* 美团的CompletableFuture封装工具类参考文章https://mp.weixin.qq.com/s/GQGidprakfticYnbVYVYGQ
*/
@Slf4j
public class FutureUtils {
/**
* 设置CF状态为失败
*/
public static <T> CompletableFuture<T> failed(Throwable ex) {
CompletableFuture<T> completableFuture = new CompletableFuture<>();
completableFuture.completeExceptionally(ex);
return completableFuture;
}
/**
* 设置CF状态为成功
*/
public static <T> CompletableFuture<T> success(T result) {
CompletableFuture<T> completableFuture = new CompletableFuture<>();
completableFuture.complete(result);
return completableFuture;
}
/**
* 将List<CompletableFuture<T>> 转为 CompletableFuture<List<T>>
*/
public static <T> CompletableFuture<List<T>> sequence(Collection<CompletableFuture<T>> completableFutures) {
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
}
/**
* 将List<CompletableFuture<List<T>>> 转为 CompletableFuture<List<T>>
* 多用于分页查询的场景
*/
public static <T> CompletableFuture<List<T>> sequenceList(Collection<CompletableFuture<List<T>>> completableFutures) {
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream()
.flatMap( listFuture -> listFuture.join().stream())
.collect(Collectors.toList())
);
}
/*
* 将List<CompletableFuture<Map<K, V>>> 转为 CompletableFuture<Map<K, V>>
* @Param mergeFunction 自定义key冲突时的merge策略
*/
public static <K, V> CompletableFuture<Map<K, V>> sequenceMap(
Collection<CompletableFuture<Map<K, V>>> completableFutures, BinaryOperator<V> mergeFunction) {
return CompletableFuture
.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream().map(CompletableFuture::join)
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, mergeFunction)));
}
/**
* 将List<CompletableFuture<T>> 转为 CompletableFuture<List<T>>并过滤调null值
*/
public static <T> CompletableFuture<List<T>> sequenceNonNull(Collection<CompletableFuture<T>> completableFutures) {
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream()
.map(CompletableFuture::join)
.filter(Objects::nonNull)
.collect(Collectors.toList())
);
}
/**
* 将List<CompletableFuture<List<T>>> 转为 CompletableFuture<List<T>>并过滤调null值
* 多用于分页查询的场景
*/
public static <T> CompletableFuture<List<T>> sequenceListNonNull(Collection<CompletableFuture<List<T>>> completableFutures) {
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream()
.flatMap( listFuture -> listFuture.join().stream().filter(Objects::nonNull))
.collect(Collectors.toList())
);
}
/**
* 将List<CompletableFuture<Map<K, V>>> 转为 CompletableFuture<Map<K, V>>
* @Param filterFunction 自定义过滤策略
*/
public static <T> CompletableFuture<List<T>> sequence(Collection<CompletableFuture<T>> completableFutures,
Predicate<? super T> filterFunction) {
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream()
.map(CompletableFuture::join)
.filter(filterFunction)
.collect(Collectors.toList())
);
}
/**
* 将List<CompletableFuture<List<T>>> 转为 CompletableFuture<List<T>>
* @Param filterFunction 自定义过滤策略
*/
public static <T> CompletableFuture<List<T>> sequenceList(Collection<CompletableFuture<List<T>>> completableFutures,
Predicate<? super T> filterFunction) {
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream()
.flatMap( listFuture -> listFuture.join().stream().filter(filterFunction))
.collect(Collectors.toList())
);
}
/**
* 将CompletableFuture<Map<K,V>>的list转为 CompletableFuture<Map<K,V>>。 多个map合并为一个map。 如果key冲突采用新的value覆盖。
*/
public static <K, V> CompletableFuture<Map<K, V>> sequenceMap(
Collection<CompletableFuture<Map<K, V>>> completableFutures) {
return CompletableFuture
.allOf(completableFutures.toArray(new CompletableFuture<?>[0]))
.thenApply(v -> completableFutures.stream().map(CompletableFuture::join)
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> b)));
}}

View File

@@ -0,0 +1,77 @@
package com.abin.mallchat.common.common.utils.discover;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import com.abin.mallchat.common.common.utils.FutureUtils;
import com.google.errorprone.annotations.Var;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.data.util.Pair;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern;
import java.util.stream.Collector;
import java.util.stream.Collectors;
/**
* Description: urlTitle查询抽象类
* Author: <a href="https://github.com/zongzibinbin">abin</a>
* Date: 2023-05-27
*/
@Slf4j
public abstract class AbstractUrlTitleDiscover implements UrlTitleDiscover {
//链接识别的正则
private static final Pattern PATTERN = Pattern.compile("((http|https)://)?(www.)?([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?");
@Nullable
@Override
public Map<String, String> getContentTitleMap(String content) {
if (StrUtil.isBlank(content)) {
return new HashMap<>();
}
List<String> matchList = ReUtil.findAll(PATTERN, content, 0);
//并行请求
List<CompletableFuture<Pair<String, String>>> futures = matchList.stream().map(match -> CompletableFuture.supplyAsync(() -> {
String title = getUrlTitle(match);
return Objects.nonNull(title) ? Pair.of(match, title) : null;
})).collect(Collectors.toList());
CompletableFuture<List<Pair<String, String>>> future = FutureUtils.sequenceNonNull(futures);
//结果组装
return future.join().stream().collect(Collectors.toMap(Pair::getFirst, Pair::getSecond, (a, b) -> a));
}
@Nullable
@Override
public String getUrlTitle(String url) {
Document document = getUrlDocument(assemble(url));
if (Objects.isNull(document)) {
return null;
}
return getDocTitle(document);
}
private String assemble(String url) {
if (!StrUtil.startWith(url, "http")) {
return "http://" + url;
}
return url;
}
protected Document getUrlDocument(String matchUrl) {
try {
Connection connect = Jsoup.connect(matchUrl);
connect.timeout(1000);
return connect.get();
} catch (Exception e) {
log.error("find title error:url:{}", matchUrl, e);
}
return null;
}
}

View File

@@ -0,0 +1,16 @@
package com.abin.mallchat.common.common.utils.discover;
import cn.hutool.core.util.StrUtil;
import org.jsoup.nodes.Document;
/**
* Description: 通用的标题解析类
* Author: <a href="https://github.com/zongzibinbin">abin</a>
* Date: 2023-05-27
*/
public class CommonUrlTitleDiscover extends AbstractUrlTitleDiscover {
@Override
public String getDocTitle(Document document) {
return document.title();
}
}

View File

@@ -0,0 +1,34 @@
package com.abin.mallchat.common.common.utils.discover;
import cn.hutool.core.util.StrUtil;
import org.jsoup.nodes.Document;
import org.springframework.core.ParameterNameDiscoverer;
import java.util.ArrayList;
import java.util.List;
/**
* Description: 具有优先级的title查询器
* Author: <a href="https://github.com/zongzibinbin">abin</a>
* Date: 2023-05-27
*/
public class PrioritizedUrlTitleDiscover extends AbstractUrlTitleDiscover {
private final List<UrlTitleDiscover> urlTitleDiscovers = new ArrayList<>(2);
public PrioritizedUrlTitleDiscover() {
urlTitleDiscovers.add(new CommonUrlTitleDiscover());
urlTitleDiscovers.add(new WxUrlTitleDiscover());
}
@Override
public String getDocTitle(Document document) {
for (UrlTitleDiscover urlTitleDiscover : urlTitleDiscovers) {
String urlTitle = urlTitleDiscover.getDocTitle(document);
if (StrUtil.isNotBlank(urlTitle)) {
return urlTitle;
}
}
return null;
}
}

View File

@@ -0,0 +1,38 @@
package com.abin.mallchat.common.common.utils.discover;
import cn.hutool.core.date.StopWatch;
import com.google.common.base.Stopwatch;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import javax.annotation.Nullable;
import javax.annotation.Signed;
import java.util.Map;
public interface UrlTitleDiscover {
@Nullable
Map<String, String> getContentTitleMap(String content);
@Nullable
String getUrlTitle(String url);
@Nullable
String getDocTitle(Document document);
public static void main(String[] args) {//用异步多任务查询并合并 974 //串行访问的速度1349 1291 1283 1559
StopWatch stopWatch = new StopWatch();
stopWatch.start();
String longStr = "这是一个很长的字符串再来 www.github.com其中包含一个URL www.baidu.com,, 一个带有端口号的URL http://www.jd.com:80, 一个带有路径的URL http://mallchat.cn, 还有美团技术文章https://mp.weixin.qq.com/s/hwTf4bDck9_tlFpgVDeIKg ";
PrioritizedUrlTitleDiscover discover =new PrioritizedUrlTitleDiscover();
Map<String, String> contentTitleMap = discover.getContentTitleMap(longStr);
System.out.println(contentTitleMap);
//
// Jsoup.connect("http:// www.github.com");
stopWatch.stop();
long cost = stopWatch.getTotalTimeMillis();
System.out.println(cost);
}//{http://mallchat.cn=MallChat, www.baidu.com=百度一下,你就知道, https://mp.weixin.qq.com/s/hwTf4bDck9_tlFpgVDeIKg=超大规模数据库集群保稳系列之二:数据库攻防演练建设实践, http://www.jd.com:80=京东(JD.COM)-正品低价、品质保障、配送及时、轻松购物!}
}

View File

@@ -0,0 +1,15 @@
package com.abin.mallchat.common.common.utils.discover;
import org.jsoup.nodes.Document;
/**
* Description: 针对微信公众号文章的标题获取类
* Author: <a href="https://github.com/zongzibinbin">abin</a>
* Date: 2023-05-27
*/
public class WxUrlTitleDiscover extends AbstractUrlTitleDiscover {
@Override
public String getDocTitle(Document document) {
return document.getElementsByAttributeValue("property", "og:title").attr("content");
}
}

View File

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
@@ -99,11 +100,10 @@ public class User implements Serializable {
@TableField("update_time")
private Date updateTime;
public IpInfo getIpInfo() {
public void refreshIp(String ip) {
if (ipInfo == null) {
ipInfo = new IpInfo();
}
return ipInfo;
ipInfo.refreshIp(ip);
}
}

View File

@@ -45,6 +45,9 @@ public class IpServiceImpl implements IpService, DisposableBean {
executor.execute(() -> {
User user = userDao.getById(uid);
IpInfo ipInfo = user.getIpInfo();
if (Objects.isNull(ipInfo)) {
return;
}
String ip = ipInfo.needRefreshIp();
if (StrUtil.isBlank(ip)) {
return;

View File

@@ -27,6 +27,8 @@ import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <p>
@@ -66,7 +68,7 @@ public class ChatController {
return userCache.getBlackMap().get(BlackTypeEnum.UID.getType());
}
@GetMapping("/public/member/statistic")
@GetMapping("public/member/statistic/")
@ApiOperation("群成员人数统计")
public ApiResult<ChatMemberStatisticResp> getMemberStatistic() {
return ApiResult.success(chatService.getMemberStatistic());

View File

@@ -1,18 +1,12 @@
package com.abin.mallchat.custom.chat.domain.vo.response;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* Description: 消息
@@ -38,6 +32,8 @@ public class ChatMessageResp {
private Long uid;
@ApiModelProperty("头像")
private String avatar;
@ApiModelProperty("归属地")
private String locPlace;
@ApiModelProperty("徽章标识如果没有展示null")
private Badge badge;
}
@@ -50,6 +46,8 @@ public class ChatMessageResp {
private Date sendTime;
@ApiModelProperty("消息内容")
private String content;
@ApiModelProperty("消息链接映射")
private Map<String,String> urlTitleMap;
@ApiModelProperty("消息类型 1正常文本 2.爆赞 点赞超过103.危险发言举报超5")
private Integer type;
@ApiModelProperty("消息标记")

View File

@@ -2,11 +2,15 @@ package com.abin.mallchat.custom.chat.service.adapter;
import cn.hutool.core.bean.BeanUtil;
import com.abin.mallchat.common.chat.domain.entity.Message;
import com.abin.mallchat.common.chat.domain.entity.MessageExtra;
import com.abin.mallchat.common.chat.domain.entity.MessageMark;
import com.abin.mallchat.common.chat.domain.enums.MessageMarkTypeEnum;
import com.abin.mallchat.common.chat.domain.enums.MessageStatusEnum;
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
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;
import com.abin.mallchat.common.user.domain.entity.User;
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
@@ -23,24 +27,32 @@ import java.util.stream.Collectors;
* Date: 2023-03-26
*/
public class MessageAdapter {
public static final int CAN_CALLBACK_GAP_COUNT = 100;
public static final int CAN_CALLBACK_GAP_COUNT = 50;
private static final PrioritizedUrlTitleDiscover URL_TITLE_DISCOVER = new PrioritizedUrlTitleDiscover();
public static Message buildMsgSave(ChatMessageReq request, Long uid) {
return Message.builder()
.replyMsgId(request.getReplyMsgId())
.content(request.getContent())
.fromUid(uid)
.roomId(request.getRoomId())
.status(MessageStatusEnum.NORMAL.getStatus())
.extra(buildExtra(request))
.build();
}
private static MessageExtra buildExtra(ChatMessageReq request) {
Map<String, String> contentTitleMap = URL_TITLE_DISCOVER.getContentTitleMap(request.getContent());
return MessageExtra.builder().urlTitleMap(contentTitleMap).build();
}
public static List<ChatMessageResp> buildMsgResp(List<Message> messages, Map<Long, Message> replyMap, Map<Long, User> userMap, List<MessageMark> msgMark, Long receiveUid, Map<Long, ItemConfig> itemMap) {
Map<Long, List<MessageMark>> markMap = msgMark.stream().collect(Collectors.groupingBy(MessageMark::getMsgId));
return messages.stream().map(a -> {
ChatMessageResp resp = new ChatMessageResp();
resp.setFromUser(buildFromUser(userMap.get(a.getFromUid()),itemMap));
resp.setFromUser(buildFromUser(userMap.get(a.getFromUid()), itemMap));
resp.setMessage(buildMessage(a, replyMap, userMap, markMap.getOrDefault(a.getId(), new ArrayList<>()), receiveUid));
return resp;
})
@@ -52,6 +64,7 @@ public class MessageAdapter {
ChatMessageResp.Message messageVO = new ChatMessageResp.Message();
BeanUtil.copyProperties(message, messageVO);
messageVO.setSendTime(message.getCreateTime());
messageVO.setUrlTitleMap(Optional.ofNullable(message.getExtra()).map(MessageExtra::getUrlTitleMap).orElse(null));
Message replyMessage = replyMap.get(message.getReplyMsgId());
//回复消息
if (Objects.nonNull(replyMessage)) {
@@ -85,9 +98,10 @@ public class MessageAdapter {
ChatMessageResp.UserInfo userInfo = new ChatMessageResp.UserInfo();
userInfo.setUsername(fromUser.getName());
userInfo.setAvatar(fromUser.getAvatar());
userInfo.setLocPlace(Optional.ofNullable(fromUser.getIpInfo()).map(IpInfo::getUpdateIpDetail).map(IpDetail::getCity).orElse(null));
userInfo.setUid(fromUser.getId());
if(Objects.nonNull(fromUser.getItemId())){
ChatMessageResp.Badge badge =new ChatMessageResp.Badge();
if (Objects.nonNull(fromUser.getItemId())) {
ChatMessageResp.Badge badge = new ChatMessageResp.Badge();
ItemConfig itemConfig = itemMap.get(fromUser.getItemId());
badge.setImg(itemConfig.getImg());
badge.setDescribe(itemConfig.getDescribe());

View File

@@ -16,6 +16,7 @@ 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.exception.BusinessException;
import com.abin.mallchat.common.common.utils.AssertUtil;
import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover;
import com.abin.mallchat.common.user.dao.UserDao;
import com.abin.mallchat.common.user.domain.entity.ItemConfig;
import com.abin.mallchat.common.user.domain.entity.User;
@@ -76,8 +77,6 @@ public class ChatServiceImpl implements ChatService {
/**
* 发送消息
*
* @param request
*/
@Override
@Transactional
@@ -90,6 +89,7 @@ public class ChatServiceImpl implements ChatService {
AssertUtil.equal(replyMsg.getRoomId(), request.getRoomId(), "只能回复相同会话内的消息");
}
//同步获取消息的跳转链接标题
Message insert = MessageAdapter.buildMsgSave(request, uid);
messageDao.save(insert);
//如果有回复消息
@@ -224,10 +224,10 @@ public class ChatServiceImpl implements ChatService {
Set<Long> uidSet = Stream.concat(replyMap.values().stream().map(Message::getFromUid), messages.stream().map(Message::getFromUid)).collect(Collectors.toSet());
userMap = userCache.getUserInfoBatch(uidSet);
//批量查询item信息
itemMap = userMap.values().stream().map(User::getItemId).distinct().filter(Objects::nonNull).map(itemCache::getById).collect(Collectors.toMap(ItemConfig::getId,Function.identity()));
itemMap = userMap.values().stream().map(User::getItemId).distinct().filter(Objects::nonNull).map(itemCache::getById).collect(Collectors.toMap(ItemConfig::getId, Function.identity()));
//查询消息标志
List<MessageMark> msgMark = messageMarkDao.getValidMarkByMsgIdBatch(messages.stream().map(Message::getId).collect(Collectors.toList()));
return MessageAdapter.buildMsgResp(messages, replyMap, userMap, msgMark, receiveUid,itemMap);
return MessageAdapter.buildMsgResp(messages, replyMap, userMap, msgMark, receiveUid, itemMap);
}
}

View File

@@ -45,7 +45,7 @@ public class LoginServiceImpl implements LoginService {
return false;
}
String key = RedisKey.getKey(RedisKey.USER_TOKEN_STRING, uid);
String realToken = redisUtils.getStr(key);
String realToken = RedisUtils.getStr(key);
return token.equals(realToken);//有可能token失效了需要校验是不是和最新token一致
}

View File

@@ -157,7 +157,7 @@ public class WebSocketServiceImpl implements WebSocketService {
boolean online = userCache.isOnline(user.getId());
if (!online) {
user.setLastOptTime(new Date());
user.getIpInfo().refreshIp(NettyUtil.getAttr(channel, NettyUtil.IP));
user.refreshIp(NettyUtil.getAttr(channel, NettyUtil.IP));
applicationEventPublisher.publishEvent(new UserOnlineEvent(this, user));
}
}

View File

@@ -67,7 +67,7 @@ public class NettyWebSocketServer {
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//30秒客户端没有向服务器发送心跳则关闭连接
pipeline.addLast(new IdleStateHandler(30, 0, 0));
// pipeline.addLast(new IdleStateHandler(30, 0, 0));
// 因为使用http协议所以需要使用http的编码器解码器
pipeline.addLast(new HttpServerCodec());
// 以块方式写,添加 chunkedWriter 处理器

View File

@@ -44,6 +44,7 @@
<netty-all.version>4.1.76.Final</netty-all.version>
<weixin-java-mp.version>4.4.0</weixin-java-mp.version>
<mybatis-plus-boot-starter.version>3.4.0</mybatis-plus-boot-starter.version>
<jsoup.version>1.15.3</jsoup.version>
</properties>
<dependencyManagement>
@@ -53,6 +54,11 @@
<artifactId>mallchat-common</artifactId>
<version>${mallchat-common.version}</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>