mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-13 21:53:41 +08:00
feat:
1.链接跳转功能 2.归属地功能 fix: 1.修复回复跳转功能 2.优化翻页工具类 3,修复下线重置ip的bug
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -67,6 +67,7 @@ CodeGenerator.java
|
|||||||
TestController.java
|
TestController.java
|
||||||
application-my-prod.properties
|
application-my-prod.properties
|
||||||
application-remote-prod.properties
|
application-remote-prod.properties
|
||||||
|
application-my-test.properties
|
||||||
mybatis-generator-config.xml
|
mybatis-generator-config.xml
|
||||||
ChannelBizRankClient.java
|
ChannelBizRankClient.java
|
||||||
ChannelBizBrandWallClient.java
|
ChannelBizBrandWallClient.java
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ CREATE TABLE `message` (
|
|||||||
`status` int(11) NOT NULL COMMENT '消息状态 0正常 1删除',
|
`status` int(11) NOT NULL COMMENT '消息状态 0正常 1删除',
|
||||||
`gap_count` int(11) NULL DEFAULT NULL COMMENT '与回复的消息间隔多少条',
|
`gap_count` int(11) NULL DEFAULT NULL COMMENT '与回复的消息间隔多少条',
|
||||||
`type` int(11) NULL DEFAULT 1 COMMENT '消息类型 1正常文本 2.爆赞 (点赞超过10)3.危险发言(举报超5)',
|
`type` int(11) NULL DEFAULT 1 COMMENT '消息类型 1正常文本 2.爆赞 (点赞超过10)3.危险发言(举报超5)',
|
||||||
|
`extra` json DEFAULT NULL COMMENT '扩展信息',
|
||||||
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) 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 '修改时间',
|
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
@@ -163,10 +164,10 @@ DROP TABLE IF EXISTS `black`;
|
|||||||
CREATE TABLE `black` (
|
CREATE TABLE `black` (
|
||||||
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
|
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
`type` int(11) NOT NULL COMMENT '拉黑目标类型 1.ip 2uid',
|
`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 '创建时间',
|
`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 '修改时间',
|
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
UNIQUE INDEX `idx_type_target`(`type`, `target`) 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;
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|||||||
@@ -24,6 +24,11 @@
|
|||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jsoup</groupId>
|
||||||
|
<artifactId>jsoup</artifactId>
|
||||||
|
</dependency>
|
||||||
<!-- MyBatis-->
|
<!-- MyBatis-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mybatis</groupId>
|
<groupId>org.mybatis</groupId>
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public class MessageDao extends ServiceImpl<MessageMapper, Message> {
|
|||||||
public void updateGapCount(Long id, Integer gapCount) {
|
public void updateGapCount(Long id, Integer gapCount) {
|
||||||
lambdaUpdate()
|
lambdaUpdate()
|
||||||
.eq(Message::getId, id)
|
.eq(Message::getId, id)
|
||||||
.set(Message::getGapCount, gapCount);
|
.set(Message::getGapCount, gapCount)
|
||||||
|
.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.abin.mallchat.common.chat.domain.entity;
|
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.TableName;
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
@@ -8,6 +9,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ import lombok.experimental.Accessors;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
@TableName("message")
|
@TableName(value = "message",autoResultMap = true)
|
||||||
@Builder
|
@Builder
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@@ -79,6 +81,11 @@ public class Message implements Serializable {
|
|||||||
@TableField("type")
|
@TableField("type")
|
||||||
private Integer type;
|
private Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后上下线时间
|
||||||
|
*/
|
||||||
|
@TableField(value = "extra", typeHandler = JacksonTypeHandler.class)
|
||||||
|
private MessageExtra extra;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -32,22 +32,23 @@ public class CursorPageBaseResp<T> {
|
|||||||
@ApiModelProperty("数据列表")
|
@ApiModelProperty("数据列表")
|
||||||
private List<T> list;
|
private List<T> list;
|
||||||
|
|
||||||
public static CursorPageBaseResp init(CursorPageBaseResp cursorPage, List list) {
|
public static <T> CursorPageBaseResp<T> init(CursorPageBaseResp cursorPage, List<T> list) {
|
||||||
CursorPageBaseResp cursorPageBaseResp = new CursorPageBaseResp();
|
CursorPageBaseResp<T> cursorPageBaseResp = new CursorPageBaseResp<T>();
|
||||||
cursorPageBaseResp.setIsLast(cursorPage.getIsLast());
|
cursorPageBaseResp.setIsLast(cursorPage.getIsLast());
|
||||||
cursorPageBaseResp.setList(list);
|
cursorPageBaseResp.setList(list);
|
||||||
cursorPageBaseResp.setCursor(cursorPage.getCursor());
|
cursorPageBaseResp.setCursor(cursorPage.getCursor());
|
||||||
return cursorPageBaseResp;
|
return cursorPageBaseResp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public Boolean isEmpty() {
|
public Boolean isEmpty() {
|
||||||
return CollectionUtil.isEmpty(list);
|
return CollectionUtil.isEmpty(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CursorPageBaseResp empty() {
|
public static <T> CursorPageBaseResp<T> empty() {
|
||||||
CursorPageBaseResp cursorPageBaseResp = new CursorPageBaseResp();
|
CursorPageBaseResp<T> cursorPageBaseResp = new CursorPageBaseResp<T>();
|
||||||
cursorPageBaseResp.setIsLast(true);
|
cursorPageBaseResp.setIsLast(true);
|
||||||
cursorPageBaseResp.setList(new ArrayList());
|
cursorPageBaseResp.setList(new ArrayList<T>());
|
||||||
return cursorPageBaseResp;
|
return cursorPageBaseResp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)));
|
||||||
|
}}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)-正品低价、品质保障、配送及时、轻松购物!}
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
|||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
@@ -99,11 +100,10 @@ public class User implements Serializable {
|
|||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
private Date updateTime;
|
private Date updateTime;
|
||||||
|
|
||||||
public IpInfo getIpInfo() {
|
public void refreshIp(String ip) {
|
||||||
if (ipInfo == null) {
|
if (ipInfo == null) {
|
||||||
ipInfo = new IpInfo();
|
ipInfo = new IpInfo();
|
||||||
}
|
}
|
||||||
return ipInfo;
|
ipInfo.refreshIp(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ public class IpServiceImpl implements IpService, DisposableBean {
|
|||||||
executor.execute(() -> {
|
executor.execute(() -> {
|
||||||
User user = userDao.getById(uid);
|
User user = userDao.getById(uid);
|
||||||
IpInfo ipInfo = user.getIpInfo();
|
IpInfo ipInfo = user.getIpInfo();
|
||||||
|
if (Objects.isNull(ipInfo)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
String ip = ipInfo.needRefreshIp();
|
String ip = ipInfo.needRefreshIp();
|
||||||
if (StrUtil.isBlank(ip)) {
|
if (StrUtil.isBlank(ip)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -66,7 +68,7 @@ public class ChatController {
|
|||||||
return userCache.getBlackMap().get(BlackTypeEnum.UID.getType());
|
return userCache.getBlackMap().get(BlackTypeEnum.UID.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@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());
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
package com.abin.mallchat.custom.chat.domain.vo.response;
|
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 io.swagger.annotations.ApiModelProperty;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description: 消息
|
* Description: 消息
|
||||||
@@ -38,6 +32,8 @@ public class ChatMessageResp {
|
|||||||
private Long uid;
|
private Long uid;
|
||||||
@ApiModelProperty("头像")
|
@ApiModelProperty("头像")
|
||||||
private String avatar;
|
private String avatar;
|
||||||
|
@ApiModelProperty("归属地")
|
||||||
|
private String locPlace;
|
||||||
@ApiModelProperty("徽章标识,如果没有展示null")
|
@ApiModelProperty("徽章标识,如果没有展示null")
|
||||||
private Badge badge;
|
private Badge badge;
|
||||||
}
|
}
|
||||||
@@ -50,6 +46,8 @@ public class ChatMessageResp {
|
|||||||
private Date sendTime;
|
private Date sendTime;
|
||||||
@ApiModelProperty("消息内容")
|
@ApiModelProperty("消息内容")
|
||||||
private String content;
|
private String content;
|
||||||
|
@ApiModelProperty("消息链接映射")
|
||||||
|
private Map<String,String> urlTitleMap;
|
||||||
@ApiModelProperty("消息类型 1正常文本 2.爆赞 (点赞超过10)3.危险发言(举报超5)")
|
@ApiModelProperty("消息类型 1正常文本 2.爆赞 (点赞超过10)3.危险发言(举报超5)")
|
||||||
private Integer type;
|
private Integer type;
|
||||||
@ApiModelProperty("消息标记")
|
@ApiModelProperty("消息标记")
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ package com.abin.mallchat.custom.chat.service.adapter;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
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.MessageExtra;
|
||||||
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.enums.MessageMarkTypeEnum;
|
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.MessageStatusEnum;
|
||||||
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
import com.abin.mallchat.common.chat.domain.enums.MessageTypeEnum;
|
||||||
import com.abin.mallchat.common.common.domain.enums.YesOrNoEnum;
|
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.ItemConfig;
|
||||||
import com.abin.mallchat.common.user.domain.entity.User;
|
import com.abin.mallchat.common.user.domain.entity.User;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
|
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
|
||||||
@@ -23,24 +27,32 @@ import java.util.stream.Collectors;
|
|||||||
* Date: 2023-03-26
|
* Date: 2023-03-26
|
||||||
*/
|
*/
|
||||||
public class MessageAdapter {
|
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) {
|
public static Message buildMsgSave(ChatMessageReq request, Long uid) {
|
||||||
|
|
||||||
return Message.builder()
|
return Message.builder()
|
||||||
.replyMsgId(request.getReplyMsgId())
|
.replyMsgId(request.getReplyMsgId())
|
||||||
.content(request.getContent())
|
.content(request.getContent())
|
||||||
.fromUid(uid)
|
.fromUid(uid)
|
||||||
.roomId(request.getRoomId())
|
.roomId(request.getRoomId())
|
||||||
.status(MessageStatusEnum.NORMAL.getStatus())
|
.status(MessageStatusEnum.NORMAL.getStatus())
|
||||||
|
.extra(buildExtra(request))
|
||||||
.build();
|
.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) {
|
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));
|
Map<Long, List<MessageMark>> markMap = msgMark.stream().collect(Collectors.groupingBy(MessageMark::getMsgId));
|
||||||
return messages.stream().map(a -> {
|
return messages.stream().map(a -> {
|
||||||
ChatMessageResp resp = new ChatMessageResp();
|
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));
|
resp.setMessage(buildMessage(a, replyMap, userMap, markMap.getOrDefault(a.getId(), new ArrayList<>()), receiveUid));
|
||||||
return resp;
|
return resp;
|
||||||
})
|
})
|
||||||
@@ -52,6 +64,7 @@ public class MessageAdapter {
|
|||||||
ChatMessageResp.Message messageVO = new ChatMessageResp.Message();
|
ChatMessageResp.Message messageVO = new ChatMessageResp.Message();
|
||||||
BeanUtil.copyProperties(message, messageVO);
|
BeanUtil.copyProperties(message, messageVO);
|
||||||
messageVO.setSendTime(message.getCreateTime());
|
messageVO.setSendTime(message.getCreateTime());
|
||||||
|
messageVO.setUrlTitleMap(Optional.ofNullable(message.getExtra()).map(MessageExtra::getUrlTitleMap).orElse(null));
|
||||||
Message replyMessage = replyMap.get(message.getReplyMsgId());
|
Message replyMessage = replyMap.get(message.getReplyMsgId());
|
||||||
//回复消息
|
//回复消息
|
||||||
if (Objects.nonNull(replyMessage)) {
|
if (Objects.nonNull(replyMessage)) {
|
||||||
@@ -85,9 +98,10 @@ public class MessageAdapter {
|
|||||||
ChatMessageResp.UserInfo userInfo = new ChatMessageResp.UserInfo();
|
ChatMessageResp.UserInfo userInfo = new ChatMessageResp.UserInfo();
|
||||||
userInfo.setUsername(fromUser.getName());
|
userInfo.setUsername(fromUser.getName());
|
||||||
userInfo.setAvatar(fromUser.getAvatar());
|
userInfo.setAvatar(fromUser.getAvatar());
|
||||||
|
userInfo.setLocPlace(Optional.ofNullable(fromUser.getIpInfo()).map(IpInfo::getUpdateIpDetail).map(IpDetail::getCity).orElse(null));
|
||||||
userInfo.setUid(fromUser.getId());
|
userInfo.setUid(fromUser.getId());
|
||||||
if(Objects.nonNull(fromUser.getItemId())){
|
if (Objects.nonNull(fromUser.getItemId())) {
|
||||||
ChatMessageResp.Badge badge =new ChatMessageResp.Badge();
|
ChatMessageResp.Badge badge = new ChatMessageResp.Badge();
|
||||||
ItemConfig itemConfig = itemMap.get(fromUser.getItemId());
|
ItemConfig itemConfig = itemMap.get(fromUser.getItemId());
|
||||||
badge.setImg(itemConfig.getImg());
|
badge.setImg(itemConfig.getImg());
|
||||||
badge.setDescribe(itemConfig.getDescribe());
|
badge.setDescribe(itemConfig.getDescribe());
|
||||||
|
|||||||
@@ -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.domain.vo.response.CursorPageBaseResp;
|
||||||
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;
|
||||||
|
import com.abin.mallchat.common.common.utils.discover.PrioritizedUrlTitleDiscover;
|
||||||
import com.abin.mallchat.common.user.dao.UserDao;
|
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.ItemConfig;
|
||||||
import com.abin.mallchat.common.user.domain.entity.User;
|
import com.abin.mallchat.common.user.domain.entity.User;
|
||||||
@@ -76,8 +77,6 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送消息
|
* 发送消息
|
||||||
*
|
|
||||||
* @param request
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -90,6 +89,7 @@ public class ChatServiceImpl implements ChatService {
|
|||||||
AssertUtil.equal(replyMsg.getRoomId(), request.getRoomId(), "只能回复相同会话内的消息");
|
AssertUtil.equal(replyMsg.getRoomId(), request.getRoomId(), "只能回复相同会话内的消息");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
//同步获取消息的跳转链接标题
|
||||||
Message insert = MessageAdapter.buildMsgSave(request, uid);
|
Message insert = MessageAdapter.buildMsgSave(request, uid);
|
||||||
messageDao.save(insert);
|
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());
|
Set<Long> uidSet = Stream.concat(replyMap.values().stream().map(Message::getFromUid), messages.stream().map(Message::getFromUid)).collect(Collectors.toSet());
|
||||||
userMap = userCache.getUserInfoBatch(uidSet);
|
userMap = userCache.getUserInfoBatch(uidSet);
|
||||||
//批量查询item信息
|
//批量查询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()));
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class LoginServiceImpl implements LoginService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String key = RedisKey.getKey(RedisKey.USER_TOKEN_STRING, uid);
|
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一致
|
return token.equals(realToken);//有可能token失效了,需要校验是不是和最新token一致
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ public class WebSocketServiceImpl implements WebSocketService {
|
|||||||
boolean online = userCache.isOnline(user.getId());
|
boolean online = userCache.isOnline(user.getId());
|
||||||
if (!online) {
|
if (!online) {
|
||||||
user.setLastOptTime(new Date());
|
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));
|
applicationEventPublisher.publishEvent(new UserOnlineEvent(this, user));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class NettyWebSocketServer {
|
|||||||
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||||
ChannelPipeline pipeline = socketChannel.pipeline();
|
ChannelPipeline pipeline = socketChannel.pipeline();
|
||||||
//30秒客户端没有向服务器发送心跳则关闭连接
|
//30秒客户端没有向服务器发送心跳则关闭连接
|
||||||
pipeline.addLast(new IdleStateHandler(30, 0, 0));
|
// pipeline.addLast(new IdleStateHandler(30, 0, 0));
|
||||||
// 因为使用http协议,所以需要使用http的编码器,解码器
|
// 因为使用http协议,所以需要使用http的编码器,解码器
|
||||||
pipeline.addLast(new HttpServerCodec());
|
pipeline.addLast(new HttpServerCodec());
|
||||||
// 以块方式写,添加 chunkedWriter 处理器
|
// 以块方式写,添加 chunkedWriter 处理器
|
||||||
|
|||||||
6
pom.xml
6
pom.xml
@@ -44,6 +44,7 @@
|
|||||||
<netty-all.version>4.1.76.Final</netty-all.version>
|
<netty-all.version>4.1.76.Final</netty-all.version>
|
||||||
<weixin-java-mp.version>4.4.0</weixin-java-mp.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>
|
<mybatis-plus-boot-starter.version>3.4.0</mybatis-plus-boot-starter.version>
|
||||||
|
<jsoup.version>1.15.3</jsoup.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
@@ -53,6 +54,11 @@
|
|||||||
<artifactId>mallchat-common</artifactId>
|
<artifactId>mallchat-common</artifactId>
|
||||||
<version>${mallchat-common.version}</version>
|
<version>${mallchat-common.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jsoup</groupId>
|
||||||
|
<artifactId>jsoup</artifactId>
|
||||||
|
<version>${jsoup.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
|||||||
Reference in New Issue
Block a user