From b8603f68f730c7b36bdaf9c57a3eceda3a8981fe Mon Sep 17 00:00:00 2001 From: imalasong <2879499479@qq.com> Date: Sat, 1 Jul 2023 19:11:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=87=E4=BA=BA=E5=A4=A7=E7=BE=A4?= =?UTF-8?q?=E8=81=8A=E5=8A=9F=E8=83=BD=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- im-commom/im-common-core/pom.xml | 5 - .../common/core/model/CommonMessageInfo.java | 45 +++++++ .../common/core/model/GroupMessageInfo.java | 27 +--- .../common/core/model/PrivateMessageInfo.java | 28 +--- .../muchat/common/core/utils/TPair.java | 21 +++ im-commom/im-common-log/.gitignore | 38 ++++++ im-commom/im-common-log/pom.xml | 55 ++++++++ .../muchat/common/log/LogAutoConfig.java | 18 +++ .../muchat/common/log/annotation/ApiLog.java | 31 +++++ .../muchat/common/log/aop/ApiLogAspect.java | 122 ++++++++++++++++++ .../common/log/entity/ApiLogEntity.java | 22 ++++ .../main/resources/META-INF/spring.factories | 2 + im-commom/pom.xml | 1 + im-server/pom.xml | 4 + .../server/aop/AnonymousUserAspect.java | 33 ++++- .../aop/annotation/AnonymousUserCheck.java | 2 +- .../common/vo/user/ChatSessionInfoResp.java | 10 +- .../muchat/server/common/vo/user/UserVO.java | 6 + .../server/controller/FriendController.java | 1 - .../server/controller/GroupController.java | 1 - .../controller/GroupMessageController.java | 7 +- .../controller/PrivateMessageController.java | 8 +- .../server/controller/UserController.java | 1 - .../exception/GlobalExceptionHandler.java | 40 +++--- .../server/service/IGroupMessageService.java | 3 +- .../service/impl/ChatSessionServiceImpl.java | 4 +- .../service/impl/GroupMessageServiceImpl.java | 119 ++++++++--------- .../server/service/impl/UserServiceImpl.java | 4 +- .../muchat/server/util/SessionContext.java | 6 + pom.xml | 11 +- 30 files changed, 508 insertions(+), 167 deletions(-) create mode 100644 im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/CommonMessageInfo.java create mode 100644 im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/utils/TPair.java create mode 100644 im-commom/im-common-log/.gitignore create mode 100644 im-commom/im-common-log/pom.xml create mode 100644 im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/LogAutoConfig.java create mode 100644 im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/annotation/ApiLog.java create mode 100644 im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/aop/ApiLogAspect.java create mode 100644 im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/entity/ApiLogEntity.java create mode 100644 im-commom/im-common-log/src/main/resources/META-INF/spring.factories diff --git a/im-commom/im-common-core/pom.xml b/im-commom/im-common-core/pom.xml index d3f8fc0..4a53a87 100644 --- a/im-commom/im-common-core/pom.xml +++ b/im-commom/im-common-core/pom.xml @@ -18,11 +18,6 @@ - - org.projectlombok - lombok - ${lombok.version} - cn.hutool hutool-all diff --git a/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/CommonMessageInfo.java b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/CommonMessageInfo.java new file mode 100644 index 0000000..16c9a13 --- /dev/null +++ b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/CommonMessageInfo.java @@ -0,0 +1,45 @@ +package io.pisceshub.muchat.common.core.model; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.pisceshub.muchat.common.core.serializer.DateToLongSerializer; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author xiaochangbai + * @date 2023-07-01 13:38 + */ +@Data +public abstract class CommonMessageInfo implements Serializable { + + + /* + * 发送者id + */ + private Long sendId; + + + /* + * 消息id + */ + private Long id; + + /* + * 发送内容 + */ + private String content; + + /* + * 消息内容类型 具体枚举值由应用层定义 + */ + private Integer type; + + + /** + * 发送时间 + */ + @JsonSerialize(using = DateToLongSerializer.class) + private Date sendTime; +} diff --git a/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/GroupMessageInfo.java b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/GroupMessageInfo.java index 364458c..bbfd45c 100644 --- a/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/GroupMessageInfo.java +++ b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/GroupMessageInfo.java @@ -7,36 +7,11 @@ import java.util.Date; @Data -public class GroupMessageInfo { - - /* - * 消息id - */ - private Long id; +public class GroupMessageInfo extends CommonMessageInfo{ /* * 群聊id */ private Long groupId; - /* - * 发送者id - */ - private Long sendId; - - /* - * 消息内容 - */ - private String content; - - /* - * 消息内容类型 具体枚举值由应用层定义 - */ - private Integer type; - - /** - * 发送时间 - */ - @JsonSerialize(using = DateToLongSerializer.class) - private Date sendTime; } diff --git a/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/PrivateMessageInfo.java b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/PrivateMessageInfo.java index 958b9ba..7c4c534 100644 --- a/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/PrivateMessageInfo.java +++ b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/model/PrivateMessageInfo.java @@ -1,42 +1,16 @@ package io.pisceshub.muchat.common.core.model; -import io.pisceshub.muchat.common.core.serializer.DateToLongSerializer; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data; import java.util.Date; @Data -public class PrivateMessageInfo { - - /* - * 消息id - */ - private long id; - - /* - * 发送者id - */ - private Long sendId; +public class PrivateMessageInfo extends CommonMessageInfo{ /* * 接收者id */ private Long recvId; - /* - * 发送内容 - */ - private String content; - - /* - * 消息内容类型 具体枚举值由应用层定义 - */ - private Integer type; - /** - * 发送时间 - */ - @JsonSerialize(using = DateToLongSerializer.class) - private Date sendTime; } diff --git a/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/utils/TPair.java b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/utils/TPair.java new file mode 100644 index 0000000..6269c2f --- /dev/null +++ b/im-commom/im-common-core/src/main/java/io/pisceshub/muchat/common/core/utils/TPair.java @@ -0,0 +1,21 @@ +package io.pisceshub.muchat.common.core.utils; + +import lombok.Getter; + +/** + * @author xiaochangbai + * @date 2023-07-01 11:36 + */ +@Getter +public class TPair { + + private L left; + + private R right; + + public TPair(L left,R right){ + this.left = left; + this.right = right; + } + +} diff --git a/im-commom/im-common-log/.gitignore b/im-commom/im-common-log/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/im-commom/im-common-log/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/im-commom/im-common-log/pom.xml b/im-commom/im-common-log/pom.xml new file mode 100644 index 0000000..fe968bf --- /dev/null +++ b/im-commom/im-common-log/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + io.pisceshub.muchat + im-commom + 1.0 + + + im-common-log + + + + + org.springframework.boot + spring-boot-starter + + + + com.alibaba + fastjson + + + + org.aspectj + aspectjweaver + + + + javax.servlet + javax.servlet-api + + + + org.springframework + spring-webmvc + + + + cn.hutool + hutool-all + + + io.pisceshub.muchat + im-common-core + + + io.swagger + swagger-annotations + + + + \ No newline at end of file diff --git a/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/LogAutoConfig.java b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/LogAutoConfig.java new file mode 100644 index 0000000..04b69d9 --- /dev/null +++ b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/LogAutoConfig.java @@ -0,0 +1,18 @@ +package io.pisceshub.muchat.common.log; + +import io.pisceshub.muchat.common.log.aop.ApiLogAspect; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author xiaochangbai + * @date 2023-07-01 11:23 + */ +@Configuration +public class LogAutoConfig { + + @Bean + public ApiLogAspect apiLogAspect(){ + return new ApiLogAspect(); + } +} diff --git a/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/annotation/ApiLog.java b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/annotation/ApiLog.java new file mode 100644 index 0000000..d2f444b --- /dev/null +++ b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/annotation/ApiLog.java @@ -0,0 +1,31 @@ +package io.pisceshub.muchat.common.log.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author xiaochangbai + * @date 2023-07-01 10:42 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ApiLog { + + /** + * 打印请求参数 + */ + boolean input() default true; + + /** + * 打印返回值 + */ + boolean output() default true; + + /** + * 是否持久化 + * @return + */ + boolean isPersistence() default false; +} diff --git a/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/aop/ApiLogAspect.java b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/aop/ApiLogAspect.java new file mode 100644 index 0000000..f7931d7 --- /dev/null +++ b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/aop/ApiLogAspect.java @@ -0,0 +1,122 @@ +package io.pisceshub.muchat.common.log.aop; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.SystemClock; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.json.JSON; +import com.alibaba.fastjson.JSONObject; +import io.pisceshub.muchat.common.core.utils.TPair; +import io.pisceshub.muchat.common.log.annotation.ApiLog; +import io.pisceshub.muchat.common.log.entity.ApiLogEntity; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.Data; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.multipart.MultipartFile; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Optional; + +/** + * @author xiaochangbai + * @date 2023-07-01 10:44 + */ +@Aspect + +public class ApiLogAspect { + + + + + /** + * 打印类或方法上的 + */ + @Around("@within(io.pisceshub.muchat.common.log.annotation.ApiLog) " + + "|| @annotation(io.pisceshub.muchat.common.log.annotation.ApiLog)") + public Object printMLog(ProceedingJoinPoint joinPoint) throws Throwable { + long startTime = SystemClock.now(); + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Logger log = LoggerFactory.getLogger(methodSignature.getDeclaringType()); + String beginTime = DateUtil.now(); + Object result = null; + try { + result = joinPoint.proceed(); + } finally { + Method targetMethod = joinPoint.getTarget().getClass().getDeclaredMethod(methodSignature.getName(), + methodSignature.getMethod().getParameterTypes()); + ApiLog logAnnotation = Optional.ofNullable(targetMethod.getAnnotation(ApiLog.class)) + .orElse(joinPoint.getTarget().getClass().getAnnotation(ApiLog.class)); + if (logAnnotation != null) { + ApiLogEntity logPrint = new ApiLogEntity(); + logPrint.setBeginTime(beginTime); + if (logAnnotation.input()) { + logPrint.setInputParams(buildInput(joinPoint)); + } + if (logAnnotation.output()) { + logPrint.setOutputParams(result); + } + TPair pair = buildApiInfo(joinPoint); + String methodType = "", requestURI = ""; + try { + ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + methodType = servletRequestAttributes.getRequest().getMethod(); + requestURI = servletRequestAttributes.getRequest().getRequestURI(); + } catch (Exception ignored) { + } + log.info("[{}:{}]-[{}] {}, executeTime: {}ms, info: {}",pair.getLeft(),pair.getRight(), methodType, + requestURI, SystemClock.now() - startTime, JSONObject.toJSONString(logPrint)); + } + } + return result; + } + + private TPair buildApiInfo(ProceedingJoinPoint joinPoint) throws NoSuchMethodException { + String moduleName = null; + String apiName = null; + Api apiAnnotation = joinPoint.getTarget().getClass().getAnnotation(Api.class); + if(apiAnnotation!=null && apiAnnotation.tags()!=null){ + String[] tags = apiAnnotation.tags(); + moduleName = tags.length>0?tags[0]:Arrays.toString(tags); + } + + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method targetMethod = joinPoint.getTarget().getClass().getDeclaredMethod(methodSignature.getName(), + methodSignature.getMethod().getParameterTypes()); + ApiOperation apiOperation = targetMethod.getAnnotation(ApiOperation.class); + if(apiAnnotation!=null){ + apiName = apiOperation.value(); + } + return new TPair<>(moduleName,apiName); + } + + private Object[] buildInput(ProceedingJoinPoint joinPoint) { + Object[] args = joinPoint.getArgs(); + Object[] printArgs = new Object[args.length]; + for (int i = 0; i < args.length; i++) { + if ((args[i] instanceof HttpServletRequest) || args[i] instanceof HttpServletResponse) { + continue; + } + if (args[i] instanceof byte[]) { + printArgs[i] = "byte array"; + } else if (args[i] instanceof MultipartFile) { + printArgs[i] = "file"; + } else { + printArgs[i] = args[i]; + } + } + return printArgs; + } + + +} diff --git a/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/entity/ApiLogEntity.java b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/entity/ApiLogEntity.java new file mode 100644 index 0000000..73b992f --- /dev/null +++ b/im-commom/im-common-log/src/main/java/io/pisceshub/muchat/common/log/entity/ApiLogEntity.java @@ -0,0 +1,22 @@ +package io.pisceshub.muchat.common.log.entity; + +import lombok.Data; + +/** + * @author xiaochangbai + * @date 2023-07-01 10:48 + */ +@Data +public class ApiLogEntity { + + private String apiModule; + + private String apiName; + + private String beginTime; + + private Object[] inputParams; + + private Object outputParams; + +} diff --git a/im-commom/im-common-log/src/main/resources/META-INF/spring.factories b/im-commom/im-common-log/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..20c0119 --- /dev/null +++ b/im-commom/im-common-log/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ + +org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.pisceshub.muchat.common.log.LogAutoConfig diff --git a/im-commom/pom.xml b/im-commom/pom.xml index 45ea55e..810b3dc 100644 --- a/im-commom/pom.xml +++ b/im-commom/pom.xml @@ -10,6 +10,7 @@ pom im-common-core + im-common-log 4.0.0 im-commom diff --git a/im-server/pom.xml b/im-server/pom.xml index 9c3e1f5..232c506 100644 --- a/im-server/pom.xml +++ b/im-server/pom.xml @@ -17,6 +17,10 @@ io.pisceshub.muchat im-common-core + + io.pisceshub.muchat + im-common-log + io.pisceshub.muchat im-sdk diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/aop/AnonymousUserAspect.java b/im-server/src/main/java/io/pisceshub/muchat/server/aop/AnonymousUserAspect.java index f2e24c0..acd6c8d 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/aop/AnonymousUserAspect.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/aop/AnonymousUserAspect.java @@ -1,16 +1,24 @@ package io.pisceshub.muchat.server.aop; import io.pisceshub.muchat.common.core.enums.ResultCode; +import io.pisceshub.muchat.common.log.annotation.ApiLog; +import io.pisceshub.muchat.server.aop.annotation.AnonymousUserCheck; +import io.pisceshub.muchat.server.common.enums.UserEnum; import io.pisceshub.muchat.server.exception.BusinessException; +import io.pisceshub.muchat.server.util.SessionContext; import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import java.lang.reflect.Method; +import java.util.Optional; import java.util.concurrent.TimeUnit; /** @@ -23,13 +31,24 @@ @Order(0) public class AnonymousUserAspect { - @Pointcut("@annotation(io.pisceshub.muchat.server.aop.annotation.AnonymousUserCheck)") - public void requestPointcut() { - } - - @Before("requestPointcut()") - public void interceptor(ProceedingJoinPoint pjp){ - throw new BusinessException(ResultCode.ANONYMOUSE_USER_NO_ACTION); + @Before("@within(io.pisceshub.muchat.server.aop.annotation.AnonymousUserCheck) " + + "|| @annotation(io.pisceshub.muchat.server.aop.annotation.AnonymousUserCheck)") + public void interceptor(JoinPoint point) throws NoSuchMethodException { + MethodSignature methodSignature = (MethodSignature) point.getSignature(); + Method targetMethod = point.getTarget().getClass().getDeclaredMethod(methodSignature.getName(), + methodSignature.getMethod().getParameterTypes()); + AnonymousUserCheck anonymousUserCheck = Optional.ofNullable(targetMethod.getAnnotation(AnonymousUserCheck.class)) + .orElse(point.getTarget().getClass().getAnnotation(AnonymousUserCheck.class)); + if(anonymousUserCheck==null){ + return; + } + SessionContext.UserSessionInfo session = SessionContext.getSession(); + if(session==null){ + throw new BusinessException(ResultCode.INVALID_TOKEN); + } + if(UserEnum.AccountType.Anonymous.getCode().equals(session.getAccountType())){ + throw new BusinessException(ResultCode.ANONYMOUSE_USER_NO_ACTION); + } } } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/aop/annotation/AnonymousUserCheck.java b/im-server/src/main/java/io/pisceshub/muchat/server/aop/annotation/AnonymousUserCheck.java index 696cdb5..3091b41 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/aop/annotation/AnonymousUserCheck.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/aop/annotation/AnonymousUserCheck.java @@ -6,7 +6,7 @@ * @author xiaochangbai * @date 2023-06-24 21:59 */ -@Target(ElementType.METHOD) +@Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AnonymousUserCheck { diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/ChatSessionInfoResp.java b/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/ChatSessionInfoResp.java index 48a2306..bf7e50f 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/ChatSessionInfoResp.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/ChatSessionInfoResp.java @@ -1,14 +1,15 @@ package io.pisceshub.muchat.server.common.vo.user; import io.pisceshub.muchat.common.core.enums.ChatType; -import io.swagger.annotations.ApiModelProperty; +import io.pisceshub.muchat.common.core.model.CommonMessageInfo; +import io.pisceshub.muchat.common.core.model.GroupMessageInfo; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import javax.validation.constraints.NotNull; import java.io.Serializable; +import java.util.List; import java.util.Objects; /** @@ -62,6 +63,11 @@ public class ChatSessionInfoResp implements Serializable { private String lastContent; + /** + * 消息列表 + */ + private List groupMessages; + @Override public boolean equals(Object o) { diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/UserVO.java b/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/UserVO.java index 664b10a..584e6d5 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/UserVO.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/common/vo/user/UserVO.java @@ -1,6 +1,7 @@ package io.pisceshub.muchat.server.common.vo.user; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -44,4 +45,9 @@ public class UserVO { @ApiModelProperty(value = "是否在线") private Boolean online; + /** + * 账号类型:0正常,1匿名 + */ + private Integer accountType; + } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/controller/FriendController.java b/im-server/src/main/java/io/pisceshub/muchat/server/controller/FriendController.java index 6d5c3f7..51820b8 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/controller/FriendController.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/controller/FriendController.java @@ -27,7 +27,6 @@ public class FriendController { @GetMapping("/list") @ApiOperation(value = "好友列表",notes="获取好友列表") - @AnonymousUserCheck public Result< List> findFriends(){ List friends = friendService.findFriendByUserId(SessionContext.getSession().getId()); List vos = friends.stream().map(f->{ diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupController.java b/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupController.java index 7c22983..ee69d9d 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupController.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupController.java @@ -56,7 +56,6 @@ public Result findGroup(@NotNull(message = "群聊id不能为空") @Pat return ResultUtils.success(groupService.findById(groupId)); } - @AnonymousUserCheck @ApiOperation(value = "查询群聊列表",notes="查询群聊列表") @GetMapping("/list") public Result> findGroups(){ diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupMessageController.java b/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupMessageController.java index 04ee914..4250a0e 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupMessageController.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/controller/GroupMessageController.java @@ -4,6 +4,7 @@ import io.pisceshub.muchat.common.core.model.GroupMessageInfo; import io.pisceshub.muchat.common.core.utils.Result; import io.pisceshub.muchat.common.core.utils.ResultUtils; +import io.pisceshub.muchat.common.log.annotation.ApiLog; import io.pisceshub.muchat.server.service.IGroupMessageService; import io.pisceshub.muchat.server.common.vo.message.GroupMessageSendReq; import io.swagger.annotations.Api; @@ -25,6 +26,7 @@ public class GroupMessageController { private IGroupMessageService groupMessageService; + @ApiLog @PostMapping("/send") @ApiOperation(value = "发送群聊消息",notes="发送群聊消息") public Result sendMessage(@Valid @RequestBody GroupMessageSendReq vo){ @@ -48,9 +50,8 @@ public Result pullUnreadMessage(){ @GetMapping("/history") @ApiOperation(value = "查询聊天记录",notes="查询聊天记录") public Result> recallMessage(@NotNull(message = "群聊id不能为空") @RequestParam Long groupId, - @NotNull(message = "页码不能为空") @RequestParam Long page, - @NotNull(message = "size不能为空") @RequestParam Long size){ - return ResultUtils.success( groupMessageService.findHistoryMessage(groupId,page,size)); + @RequestParam(required = false) Long lastMessageId){ + return ResultUtils.success(groupMessageService.findHistoryMessage(groupId,lastMessageId)); } } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/controller/PrivateMessageController.java b/im-server/src/main/java/io/pisceshub/muchat/server/controller/PrivateMessageController.java index 9b615aa..e87b1d0 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/controller/PrivateMessageController.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/controller/PrivateMessageController.java @@ -4,6 +4,7 @@ import io.pisceshub.muchat.common.core.model.PrivateMessageInfo; import io.pisceshub.muchat.common.core.utils.Result; import io.pisceshub.muchat.common.core.utils.ResultUtils; +import io.pisceshub.muchat.common.log.annotation.ApiLog; import io.pisceshub.muchat.server.aop.annotation.AnonymousUserCheck; import io.pisceshub.muchat.server.service.IPrivateMessageService; import io.pisceshub.muchat.server.common.vo.message.PrivateMessageSendReq; @@ -16,6 +17,7 @@ import javax.validation.constraints.NotNull; import java.util.List; +@AnonymousUserCheck @Api(tags = "私聊消息") @RestController @RequestMapping("/message/private") @@ -24,7 +26,7 @@ public class PrivateMessageController { @Autowired private IPrivateMessageService privateMessageService; - @AnonymousUserCheck + @ApiLog @PostMapping("/send") @ApiOperation(value = "发送消息",notes="发送私聊消息") public Result sendMessage(@Valid @RequestBody PrivateMessageSendReq vo){ @@ -32,7 +34,6 @@ public Result sendMessage(@Valid @RequestBody PrivateMessageSendReq vo){ } - @AnonymousUserCheck @DeleteMapping("/recall/{id}") @ApiOperation(value = "撤回消息",notes="撤回私聊消息") public Result recallMessage(@NotNull(message = "消息id不能为空") @PathVariable Long id){ @@ -41,7 +42,6 @@ public Result recallMessage(@NotNull(message = "消息id不能为空") @Pa } - @AnonymousUserCheck @PostMapping("/pullUnreadMessage") @ApiOperation(value = "拉取未读消息",notes="拉取未读消息") public Result pullUnreadMessage(){ @@ -50,7 +50,7 @@ public Result pullUnreadMessage(){ } - @AnonymousUserCheck + @GetMapping("/history") @ApiOperation(value = "查询聊天记录",notes="查询聊天记录") public Result> recallMessage(@NotNull(message = "好友id不能为空") @RequestParam Long friendId, diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/controller/UserController.java b/im-server/src/main/java/io/pisceshub/muchat/server/controller/UserController.java index 5c40197..c08d631 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/controller/UserController.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/controller/UserController.java @@ -43,7 +43,6 @@ public Result findSelfInfo(){ return ResultUtils.success(userVO); } - @AnonymousUserCheck @GetMapping("/find/{id}") @ApiOperation(value = "查找用户",notes="根据id查找用户") public Result findByIde(@NotEmpty @PathVariable("id") long id){ diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/exception/GlobalExceptionHandler.java b/im-server/src/main/java/io/pisceshub/muchat/server/exception/GlobalExceptionHandler.java index c3cb178..262f35a 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/exception/GlobalExceptionHandler.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/exception/GlobalExceptionHandler.java @@ -26,28 +26,6 @@ @Slf4j public class GlobalExceptionHandler { - @ExceptionHandler(value = Exception.class) - public Result handleException(Exception e){ - if(e instanceof GlobalException) { - GlobalException ex = (GlobalException)e; - log.error("全局异常捕获:msg:{},log:{},{}" , ex.getMessage(), e); - return ResultUtils.error(ex.getCode(), ex.getMessage()); - } - else if(e instanceof BusinessException) { - BusinessException ex = (BusinessException) e.getCause(); - log.error("全局异常捕获:msg:{},log:{},{}" , ex.getMessage(), e); - return ResultUtils.error(ex.getCode(), ex.getMessage()); - }else if(e instanceof UndeclaredThrowableException) { - GlobalException ex = (GlobalException) e.getCause(); - log.error("全局异常捕获:msg:{},log:{},{}" , ex.getMessage(), e); - return ResultUtils.error(ex.getCode(), ex.getMessage()); - }else{ - log.error("全局异常捕获:msg:{},{}" , e.getMessage(), e); - return ResultUtils.error(ResultCode.PROGRAM_ERROR); - } - } - - /** * 数据解析错误 **/ @@ -99,4 +77,22 @@ public Result handleBindException(BindException e){ return ResultUtils.error(ResultCode.PROGRAM_ERROR,errorMsg); } + @ExceptionHandler(value = Exception.class) + public Result handleException(Exception e){ + if(e instanceof GlobalException) { + GlobalException ge = (GlobalException)e; + log.error("全局异常捕获:msg:{},log:" , ge.getMessage(), ge); + return ResultUtils.error(ge.getCode(), ge.getMessage()); + } + else if(e instanceof BusinessException) { + BusinessException be = (BusinessException)e; + log.error("全局异常捕获:msg:{},log:" , be.getMessage(), e); + return ResultUtils.error(be.getCode(), be.getMessage()); + }else{ + log.error("全局异常捕获:msg:{}," , e.getMessage(), e); + return ResultUtils.error(ResultCode.PROGRAM_ERROR); + } + } + + } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/service/IGroupMessageService.java b/im-server/src/main/java/io/pisceshub/muchat/server/service/IGroupMessageService.java index 1d5be1f..3c6702e 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/service/IGroupMessageService.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/service/IGroupMessageService.java @@ -1,6 +1,7 @@ package io.pisceshub.muchat.server.service; import com.baomidou.mybatisplus.extension.service.IService; +import io.pisceshub.muchat.common.core.model.CommonMessageInfo; import io.pisceshub.muchat.common.core.model.GroupMessageInfo; import io.pisceshub.muchat.server.common.entity.GroupMessage; import io.pisceshub.muchat.server.common.vo.message.GroupMessageSendReq; @@ -17,5 +18,5 @@ public interface IGroupMessageService extends IService { void pullUnreadMessage(); - List findHistoryMessage(Long groupId, Long page, Long size); + List findHistoryMessage(Long groupId, Long lastMessageId); } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/ChatSessionServiceImpl.java b/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/ChatSessionServiceImpl.java index 6975079..5f5f0f4 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/ChatSessionServiceImpl.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/ChatSessionServiceImpl.java @@ -2,6 +2,7 @@ import cn.hutool.core.collection.CollUtil; import io.pisceshub.muchat.common.core.enums.ChatType; +import io.pisceshub.muchat.common.core.model.CommonMessageInfo; import io.pisceshub.muchat.common.core.model.GroupMessageInfo; import io.pisceshub.muchat.common.core.model.PrivateMessageInfo; import io.pisceshub.muchat.common.core.utils.Result; @@ -81,10 +82,11 @@ public Result> list() { .headImage(groupVO.getHeadImage()) .unReadCount(0L).build(); //查询消息 - List historyMessage = iGroupMessageService.findHistoryMessage(targetId, 1L, 30L); + List historyMessage = iGroupMessageService.findHistoryMessage(targetId, null); if(CollUtil.isNotEmpty(historyMessage)){ chatSessionInfoResp.setLastSendTime(historyMessage.get(0).getSendTime().getTime()); chatSessionInfoResp.setLastContent(historyMessage.get(0).getContent()); + chatSessionInfoResp.setGroupMessages(historyMessage); }else{ chatSessionInfoResp.setLastSendTime(dto.getCreateTime()); } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/GroupMessageServiceImpl.java b/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/GroupMessageServiceImpl.java index 6e27479..e0786bc 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/GroupMessageServiceImpl.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/GroupMessageServiceImpl.java @@ -1,7 +1,9 @@ package io.pisceshub.muchat.server.service.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import io.pisceshub.muchat.common.core.model.CommonMessageInfo; import io.pisceshub.muchat.sdk.IMClient; import io.pisceshub.muchat.common.core.contant.AppConst; import io.pisceshub.muchat.common.core.model.GroupMessageInfo; @@ -43,7 +45,7 @@ public class GroupMessageServiceImpl extends ServiceImpl redisTemplate; + private RedisTemplate redisTemplate; @Autowired private IMClient imClient; @@ -58,16 +60,16 @@ public class GroupMessageServiceImpl extends ServiceImpl userIds = groupMemberService.findUserIdsByGroupId(group.getId()); - if(!userIds.contains(userId)){ - throw new GlobalException(ResultCode.PROGRAM_ERROR,"您已不在群聊里面,无法发送消息"); + if (!userIds.contains(userId)) { + throw new GlobalException(ResultCode.PROGRAM_ERROR, "您已不在群聊里面,无法发送消息"); } // 保存消息 GroupMessage msg = BeanUtils.copyProperties(vo, GroupMessage.class); @@ -75,17 +77,15 @@ public Long sendMessage(GroupMessageSendReq vo) { msg.setSendTime(new Date()); this.save(msg); // 不用发给自己 - userIds = userIds.stream().filter(id->userId!=id).collect(Collectors.toList()); + userIds = userIds.stream().filter(id -> userId != id).collect(Collectors.toList()); // 群发 - GroupMessageInfo msgInfo = BeanUtils.copyProperties(msg, GroupMessageInfo.class); - imClient.sendGroupMessage(userIds,msgInfo); - log.info("发送群聊消息,发送id:{},群聊id:{},内容:{}",userId,vo.getGroupId(),vo.getContent()); + GroupMessageInfo msgInfo = BeanUtils.copyProperties(msg, GroupMessageInfo.class); + imClient.sendGroupMessage(userIds, msgInfo); + log.info("发送群聊消息,发送id:{},群聊id:{},内容:{}", userId, vo.getGroupId(), vo.getContent()); return msg.getId(); } - - /** * 撤回消息 * @@ -95,19 +95,19 @@ public Long sendMessage(GroupMessageSendReq vo) { public void recallMessage(Long id) { Long userId = SessionContext.getSession().getId(); GroupMessage msg = this.getById(id); - if(msg == null){ - throw new GlobalException(ResultCode.PROGRAM_ERROR,"消息不存在"); + if (msg == null) { + throw new GlobalException(ResultCode.PROGRAM_ERROR, "消息不存在"); } - if(msg.getSendId() != userId){ - throw new GlobalException(ResultCode.PROGRAM_ERROR,"这条消息不是由您发送,无法撤回"); + if (msg.getSendId() != userId) { + throw new GlobalException(ResultCode.PROGRAM_ERROR, "这条消息不是由您发送,无法撤回"); } - if(System.currentTimeMillis() - msg.getSendTime().getTime() > AppConst.ALLOW_RECALL_SECOND * 1000){ - throw new GlobalException(ResultCode.PROGRAM_ERROR,"消息已发送超过5分钟,无法撤回"); + if (System.currentTimeMillis() - msg.getSendTime().getTime() > AppConst.ALLOW_RECALL_SECOND * 1000) { + throw new GlobalException(ResultCode.PROGRAM_ERROR, "消息已发送超过5分钟,无法撤回"); } // 判断是否在群里 - GroupMember member = groupMemberService.findByGroupAndUserId(msg.getGroupId(),userId); - if(member == null){ - throw new GlobalException(ResultCode.PROGRAM_ERROR,"您已不在群聊里面,无法撤回消息"); + GroupMember member = groupMemberService.findByGroupAndUserId(msg.getGroupId(), userId); + if (member == null) { + throw new GlobalException(ResultCode.PROGRAM_ERROR, "您已不在群聊里面,无法撤回消息"); } // 修改数据库 msg.setStatus(MessageStatus.RECALL.code()); @@ -115,14 +115,14 @@ public void recallMessage(Long id) { // 群发 List userIds = groupMemberService.findUserIdsByGroupId(msg.getGroupId()); // 不用发给自己 - userIds = userIds.stream().filter(uid->userId.equals(uid)).collect(Collectors.toList()); - GroupMessageInfo msgInfo = BeanUtils.copyProperties(msg, GroupMessageInfo.class); + userIds = userIds.stream().filter(uid -> userId.equals(uid)).collect(Collectors.toList()); + GroupMessageInfo msgInfo = BeanUtils.copyProperties(msg, GroupMessageInfo.class); msgInfo.setType(MessageType.TIP.code()); - String content = String.format("'%s'撤回了一条消息",member.getAliasName()); + String content = String.format("'%s'撤回了一条消息", member.getAliasName()); msgInfo.setContent(content); msgInfo.setSendTime(new Date()); - imClient.sendGroupMessage(userIds,msgInfo); - log.info("撤回群聊消息,发送id:{},群聊id:{},内容:{}",userId,msg.getGroupId(),msg.getContent()); + imClient.sendGroupMessage(userIds, msgInfo); + log.info("撤回群聊消息,发送id:{},群聊id:{},内容:{}", userId, msg.getGroupId(), msg.getContent()); } @@ -137,32 +137,32 @@ public void pullUnreadMessage() { List recvIds = new LinkedList(); recvIds.add(userId); List members = groupMemberService.findByUserId(userId); - for(GroupMember member:members){ + for (GroupMember member : members) { // 获取群聊已读的最大消息id,只推送未读消息 - String key = RedisKey.IM_GROUP_READED_POSITION + member.getGroupId()+":"+userId; - Integer maxReadedId = (Integer)redisTemplate.opsForValue().get(key); + String key = RedisKey.IM_GROUP_READED_POSITION + member.getGroupId() + ":" + userId; + Integer maxReadedId = (Integer) redisTemplate.opsForValue().get(key); QueryWrapper wrapper = new QueryWrapper(); - wrapper.lambda().eq(GroupMessage::getGroupId,member.getGroupId()) - .gt(GroupMessage::getSendTime,member.getCreatedTime()) + wrapper.lambda().eq(GroupMessage::getGroupId, member.getGroupId()) + .gt(GroupMessage::getSendTime, member.getCreatedTime()) .ne(GroupMessage::getSendId, userId) .ne(GroupMessage::getStatus, MessageStatus.RECALL.code()); - if(maxReadedId!=null){ - wrapper.lambda().gt(GroupMessage::getId,maxReadedId); + if (maxReadedId != null) { + wrapper.lambda().gt(GroupMessage::getId, maxReadedId); } wrapper.last("limit 100"); List messages = this.list(wrapper); - if(messages.isEmpty()){ + if (messages.isEmpty()) { continue; } // 组装消息,准备推送 - List messageInfos = messages.stream().map(m->{ - GroupMessageInfo msgInfo = BeanUtils.copyProperties(m, GroupMessageInfo.class); - return msgInfo; + List messageInfos = messages.stream().map(m -> { + GroupMessageInfo msgInfo = BeanUtils.copyProperties(m, GroupMessageInfo.class); + return msgInfo; }).collect(Collectors.toList()); // 发送消息 - GroupMessageInfo[] infoArr = messageInfos.toArray(new GroupMessageInfo[messageInfos.size()]); + GroupMessageInfo[] infoArr = messageInfos.toArray(new GroupMessageInfo[messageInfos.size()]); imClient.sendGroupMessage(Collections.singletonList(userId), infoArr); - log.info("拉取未读群聊消息,用户id:{},群聊id:{},数量:{}",userId,member.getGroupId(),messageInfos.size()); + log.info("拉取未读群聊消息,用户id:{},群聊id:{},数量:{}", userId, member.getGroupId(), messageInfos.size()); } } @@ -171,39 +171,34 @@ public void pullUnreadMessage() { * 拉取历史聊天记录 * * @param groupId 群聊id - * @param page 页码 - * @param size 页码大小 * @return 聊天记录列表 */ @Override - public List findHistoryMessage(Long groupId, Long page, Long size) { - page = page > 0 ? page:1; - size = size > 0 ? size:10; + public List findHistoryMessage(Long groupId, Long lastMessageId) { Long userId = SessionContext.getSession().getId(); - Long stIdx = (page-1)* size; // 群聊成员信息 - GroupMember member = groupMemberService.findByGroupAndUserId(groupId,userId); - if(member == null || member.getQuit()){ - throw new GlobalException(ResultCode.PROGRAM_ERROR,"您已不在群聊中"); + GroupMember member = groupMemberService.findByGroupAndUserId(groupId, userId); + if (member == null || member.getQuit()) { + throw new GlobalException(ResultCode.PROGRAM_ERROR, "您已不在群聊中"); } // 查询聊天记录,只查询加入群聊时间之后的消息 - QueryWrapper wrapper = new QueryWrapper<>(); - wrapper.lambda().eq(GroupMessage::getGroupId,groupId) - .gt(GroupMessage::getSendTime,member.getCreatedTime()) - .ne(GroupMessage::getStatus, MessageStatus.RECALL.code()) - .orderByDesc(GroupMessage::getId) - .last("limit "+stIdx + ","+size); - - List messages = this.list(wrapper); - List messageInfos = messages.stream().map(m->{ + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(GroupMessage::getGroupId, groupId) + .gt(GroupMessage::getSendTime, member.getCreatedTime()) + .ne(GroupMessage::getStatus, MessageStatus.RECALL.code()); + + if (lastMessageId != null) { + queryWrapper.lt(GroupMessage::getId, lastMessageId); + } + queryWrapper.orderByDesc(GroupMessage::getId) + .last("limit 15"); + List messages = this.list(queryWrapper); + List messageInfos = messages.stream().map(m -> { GroupMessageInfo info = BeanUtils.copyProperties(m, GroupMessageInfo.class); return info; }).collect(Collectors.toList()); - log.info("拉取群聊记录,用户id:{},群聊id:{},数量:{}",userId,groupId,messageInfos.size()); + log.info("拉取群聊记录,用户id:{},群聊id:{},数量:{}", userId, groupId, messageInfos.size()); return messageInfos; } - - - } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/UserServiceImpl.java b/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/UserServiceImpl.java index da5ec50..2109f69 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/UserServiceImpl.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/service/impl/UserServiceImpl.java @@ -327,13 +327,13 @@ public LoginResp anonymousLogin(AnonymousLoginReq req) { private void anonyUserInit(User user) { //加入默认群聊 GroupInviteReq inviteReq = - GroupInviteReq.builder().groupId(0L).friendIds(Arrays.asList(user.getId())).build(); + GroupInviteReq.builder().groupId(-1L).friendIds(Arrays.asList(user.getId())).build(); iGroupService.invite(inviteReq); //会话列表 ChatSessionAddReq sessionAddReq = new ChatSessionAddReq(); sessionAddReq.setChatType(ChatType.GROUP); - sessionAddReq.setTargetId(0L); + sessionAddReq.setTargetId(-1L); iChatSessionService.save(user.getId(),sessionAddReq); } diff --git a/im-server/src/main/java/io/pisceshub/muchat/server/util/SessionContext.java b/im-server/src/main/java/io/pisceshub/muchat/server/util/SessionContext.java index b6c0e35..6612360 100644 --- a/im-server/src/main/java/io/pisceshub/muchat/server/util/SessionContext.java +++ b/im-server/src/main/java/io/pisceshub/muchat/server/util/SessionContext.java @@ -1,5 +1,6 @@ package io.pisceshub.muchat.server.util; +import com.baomidou.mybatisplus.annotation.TableField; import io.pisceshub.muchat.common.core.enums.ResultCode; import io.pisceshub.muchat.server.exception.GlobalException; import lombok.Data; @@ -40,5 +41,10 @@ public static class UserSessionInfo { private Long id; private String userName; private String nickName; + + /** + * 账号类型:0正常,1匿名 + */ + private Integer accountType; } } diff --git a/pom.xml b/pom.xml index 48b0528..bc41031 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,7 @@ 2.9.2 2.6.15 4.1.2 - 2.6 + 2.6 1.6.1 3.7.0 4.2.0 @@ -56,6 +56,10 @@ spring-boot-starter-test test + + org.projectlombok + lombok + @@ -71,6 +75,11 @@ im-sdk 1.0 + + io.pisceshub.muchat + im-common-log + 1.0 +