Browse Source

微服务拆分

wangqi49 2 months ago
parent
commit
fae05682c4
38 changed files with 710 additions and 16 deletions
  1. BIN
      .DS_Store
  2. 8 2
      .idea/compiler.xml
  3. 4 1
      .idea/encodings.xml
  4. 3 0
      .idea/misc.xml
  5. 4 3
      pom.xml
  6. 0 0
      resources/database-sql/webchat-core.sql
  7. 0 0
      resources/database-sql/webchat-event.sql
  8. 12 0
      resources/nacos-yaml/webchat-connect-service-dev.yaml
  9. 23 0
      resources/nacos-yaml/webchat-pay-service-dev.yaml
  10. 30 0
      resources/nacos-yaml/webchat-pgc-service-dev.yaml
  11. 21 0
      resources/nacos-yaml/webchat-user-service-dev.yaml
  12. 51 0
      webchat-act/pom.xml
  13. 19 0
      webchat-act/src/main/java/com/webchat/pgc/WebchatPGCApplication.java
  14. 34 0
      webchat-act/src/main/java/com/webchat/pgc/controller/TestController.java
  15. 1 0
      webchat-act/src/main/resources/application.yml
  16. 16 0
      webchat-act/src/main/resources/bootstrap.yml
  17. 0 0
      webchat-client-chat/.DS_Store
  18. 0 0
      webchat-client-chat/.mvn/wrapper/maven-wrapper.properties
  19. 3 3
      webchat-client-chat/pom.xml
  20. 0 0
      webchat-client-chat/src/.DS_Store
  21. 0 0
      webchat-client-chat/src/main/.DS_Store
  22. 0 0
      webchat-client-chat/src/main/java/com/webchat/client/WebchatClientApplication.java
  23. 0 0
      webchat-client-chat/src/main/resources/application.properties
  24. 38 0
      webchat-common/src/main/java/com/webchat/common/config/annotation/SafeClick.java
  25. 55 0
      webchat-common/src/main/java/com/webchat/common/config/annotation/SafeClickInterceptor.java
  26. 20 0
      webchat-common/src/main/java/com/webchat/common/config/annotation/ValidateLogin.java
  27. 37 0
      webchat-common/src/main/java/com/webchat/common/config/annotation/ValidateLoginInterceptor.java
  28. 25 0
      webchat-common/src/main/java/com/webchat/common/config/annotation/ValidatePermission.java
  29. 54 0
      webchat-common/src/main/java/com/webchat/common/config/annotation/ValidatePermissionInterceptor.java
  30. 58 0
      webchat-common/src/main/java/com/webchat/common/config/configuration/WebChatWebMvcConfigurer.java
  31. 23 0
      webchat-common/src/main/java/com/webchat/common/service/RedisMessageSender.java
  32. 21 5
      webchat-connect/pom.xml
  33. 34 0
      webchat-connect/src/main/java/com/webchat/connect/javasse/EventStreamConnectController.java
  34. 97 0
      webchat-connect/src/main/java/com/webchat/connect/websocket/ChatWebSocketEndPoint.java
  35. 0 1
      webchat-connect/src/main/resources/application.properties
  36. 2 0
      webchat-connect/src/main/resources/application.yml
  37. 16 0
      webchat-connect/src/main/resources/bootstrap.yml
  38. 1 1
      webchat-gateway/src/main/resources/application.yml

BIN
.DS_Store


+ 8 - 2
.idea/compiler.xml

@@ -7,34 +7,40 @@
         <sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
         <outputRelativeToContentRoot value="true" />
         <module name="webchat-ugc" />
+        <module name="webchat-act" />
         <module name="webchat-remote" />
+        <module name="webchat-gateway" />
         <module name="webchat-connect" />
         <module name="webchat-common" />
+        <module name="webchat-client-chat" />
         <module name="webchat-domain" />
         <module name="webchat-user" />
         <module name="webchat-pay" />
         <module name="webchat-search" />
         <module name="webchat-aigc" />
         <module name="webchat-sso" />
-        <module name="webchat-client" />
         <module name="webchat-pgc" />
         <module name="webchat-admin" />
       </profile>
     </annotationProcessing>
     <bytecodeTargetLevel>
       <module name="webchat-api" target="17" />
+      <module name="webchat-client-shop" target="17" />
       <module name="webchat-nacos" target="17" />
     </bytecodeTargetLevel>
   </component>
   <component name="JavacSettings">
     <option name="ADDITIONAL_OPTIONS_OVERRIDE">
+      <module name="webchat-act" options="-parameters" />
       <module name="webchat-admin" options="-parameters" />
       <module name="webchat-aigc" options="-parameters" />
       <module name="webchat-api" options="-parameters" />
-      <module name="webchat-client" options="-parameters" />
+      <module name="webchat-client-chat" options="-parameters" />
+      <module name="webchat-client-shop" options="-parameters" />
       <module name="webchat-common" options="-parameters" />
       <module name="webchat-connect" options="-parameters" />
       <module name="webchat-domain" options="-parameters" />
+      <module name="webchat-gateway" options="-parameters" />
       <module name="webchat-nacos" options="-parameters" />
       <module name="webchat-pay" options="-parameters" />
       <module name="webchat-pgc" options="-parameters" />

+ 4 - 1
.idea/encodings.xml

@@ -3,13 +3,16 @@
   <component name="Encoding">
     <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/webchat-act/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-admin/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-aigc/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-api/src/main/java" charset="UTF-8" />
-    <file url="file://$PROJECT_DIR$/webchat-client/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/webchat-client-chat/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/webchat-client-shop/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-common/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-connect/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-domain/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/webchat-gateway/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-nacos/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-pay/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/webchat-pgc/src/main/java" charset="UTF-8" />

+ 3 - 0
.idea/misc.xml

@@ -17,11 +17,14 @@
         <option value="$PROJECT_DIR$/webchat-api/pom.xml" />
         <option value="$PROJECT_DIR$/webchat-client/pom.xml" />
         <option value="$PROJECT_DIR$/webchat-search/pom.xml" />
+        <option value="$PROJECT_DIR$/webchat-act/pom.xml" />
+        <option value="$PROJECT_DIR$/webchat-client-shop/pom.xml" />
       </list>
     </option>
     <option name="ignoredFiles">
       <set>
         <option value="$PROJECT_DIR$/webchat-api/pom.xml" />
+        <option value="$PROJECT_DIR$/webchat-client-shop/pom.xml" />
         <option value="$PROJECT_DIR$/webchat-nacos/pom.xml" />
         <option value="$PROJECT_DIR$/webchat-web/pom.xml" />
       </set>

+ 4 - 3
pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>3.2.2</version>
+        <version>3.2.12</version>
     </parent>
 
     <groupId>com.webchat</groupId>
@@ -18,6 +18,8 @@
     <modules>
         <module>webchat-gateway</module>
         <module>webchat-sso</module>
+        <module>webchat-admin</module>
+        <module>webchat-client-chat</module>
         <module>webchat-domain</module>
         <module>webchat-common</module>
         <module>webchat-remote</module>
@@ -26,10 +28,9 @@
         <module>webchat-aigc</module>
         <module>webchat-connect</module>
         <module>webchat-user</module>
-        <module>webchat-client</module>
-        <module>webchat-admin</module>
         <module>webchat-pay</module>
         <module>webchat-search</module>
+        <module>webchat-act</module>
     </modules>
 
     <properties>

+ 0 - 0
resources/database-sql/webchat-core.sql


+ 0 - 0
resources/database-sql/webchat-event.sql


+ 12 - 0
resources/nacos-yaml/webchat-connect-service-dev.yaml

@@ -0,0 +1,12 @@
+spring:
+  data:
+    redis:
+      host: 127.0.0.1
+      port: 6379
+      database: 0
+      jedis:
+      timeout: 5000
+      pool:
+        max-active: 100
+        max-wait: -1
+        min-idle: 10

+ 23 - 0
resources/nacos-yaml/webchat-pay-service-dev.yaml

@@ -0,0 +1,23 @@
+spring:
+  # set mysql config
+  datasource:
+    url: jdbc:mysql://127.0.0.1:3306/webchat?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&useSSL=false
+    username: root
+    password: 12345678
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      maximum-pool-size: 50
+  jpa:
+    show-sql: true
+  # set redis config
+  data:
+    redis:
+      host: 127.0.0.1
+      port: 6379
+      database: 0
+      jedis:
+        timeout: 5000
+        pool:
+          max-active: 100
+          max-wait: -1
+          min-idle: 10

+ 30 - 0
resources/nacos-yaml/webchat-pgc-service-dev.yaml

@@ -0,0 +1,30 @@
+#---------------------------------数据库配置----------------------------------#
+spring:
+  datasource:
+    url: jdbc:mysql://127.0.0.1:3306/webchat?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8&&useSSL=false
+    username: root
+    password: 12345678
+    driver-class-name: com.mysql.jdbc.Driver
+    type: com.zaxxer.hikari.HikariDataSource
+    hikari:
+    minimum-idle: 10
+    maximum-pool-size: 50
+    auto-commit: false
+    idle-timeout: 30000
+    pool-name: DatebookHikariCP
+    max-lifetime: 1800000
+    connection-timeout: 30000
+    connection-test-query: SELECT 1
+    connection-init-sql: set names utf8mb4
+  jpa:
+    show-sql: true
+  #---------------------------------redis----------------------------------#
+  data:
+    redis:
+    port: 6379
+    database: 0
+    jedis:
+      pool:
+      max-active: 100
+      max-wait: -1
+      min-idle: 10

+ 21 - 0
resources/nacos-yaml/webchat-user-service-dev.yaml

@@ -0,0 +1,21 @@
+spring:
+  datasource:
+    url: jdbc:mysql://127.0.0.1:3306/webchat_user?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT%2b8
+    username: root
+    password: 12345678
+    driver-class-name: com.mysql.jdbc.Driver
+    hikari:
+      maximum-pool-size: 50
+  jpa:
+    show-sql: true
+  data:
+    redis:
+      host: 127.0.0.1
+      port: 6379
+      database: 0
+      jedis:
+        timeout: 5000
+        pool:
+          max-active: 100
+          max-wait: -1
+          min-idle: 10

+ 51 - 0
webchat-act/pom.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.webchat</groupId>
+        <artifactId>webchat</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+
+    <groupId>com.webchat</groupId>
+    <artifactId>webchat-act</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>webchat-act</name>
+    <description>webchat-act</description>
+
+    <properties>
+        <java.version>17</java.version>
+    </properties>
+    <dependencies>
+
+        <!--引入mysql驱动-->
+<!--        <dependency>-->
+<!--            <groupId>mysql</groupId>-->
+<!--            <artifactId>mysql-connector-java</artifactId>-->
+<!--            <version>5.1.46</version>-->
+<!--        </dependency>-->
+        <!--使用JPA作为ORM框架 -->
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-data-jpa</artifactId>-->
+<!--        </dependency>-->
+
+        <dependency>
+            <groupId>com.webchat</groupId>
+            <artifactId>webchat-remote</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 19 - 0
webchat-act/src/main/java/com/webchat/pgc/WebchatPGCApplication.java

@@ -0,0 +1,19 @@
+package com.webchat.pgc;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.ComponentScan;
+
+@SpringBootApplication
+@EnableDiscoveryClient
+@ComponentScan("com.webchat")
+@EnableFeignClients("com.webchat.rmi")
+public class WebchatPGCApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(WebchatPGCApplication.class, args);
+    }
+
+}

+ 34 - 0
webchat-act/src/main/java/com/webchat/pgc/controller/TestController.java

@@ -0,0 +1,34 @@
+package com.webchat.pgc.controller;
+
+import com.webchat.common.bean.APIResponseBean;
+import com.webchat.common.bean.APIResponseBeanUtil;
+import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
+import com.webchat.rmi.user.UserServiceClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Author 程序员七七
+ * @webSite https://www.coderutil.com
+ * @Date 2025/1/14 00:55
+ * @description
+ */
+@RefreshScope
+@RestController
+@RequestMapping("/pgc-service")
+public class TestController {
+
+    @Autowired
+    private UserServiceClient userServiceClient;
+
+    @GetMapping("/user/{userId}")
+    public APIResponseBean<UserBaseResponseInfoVO> user(@PathVariable String userId) {
+
+        return APIResponseBeanUtil.success(userServiceClient.userInfo(userId));
+    }
+
+}

+ 1 - 0
webchat-act/src/main/resources/application.yml

@@ -0,0 +1 @@
+server:
  port: 8018

+ 16 - 0
webchat-act/src/main/resources/bootstrap.yml

@@ -0,0 +1,16 @@
+spring:
+  application:
+    name: webchat-act-service
+  profiles:
+    active: dev
+  cloud:
+    nacos:
+      config:
+        server-addr: 127.0.0.1:8848
+        namespace: 2cdfb8e3-f127-4020-93df-2d4c3dc805b5
+        file-extension: yaml
+        group: DEFAULT_GROUP
+        refresh-enabled: true
+      discovery:
+        server-addr: 127.0.0.1:8848
+        namespace: 2cdfb8e3-f127-4020-93df-2d4c3dc805b5

+ 0 - 0
webchat-client/.DS_Store → webchat-client-chat/.DS_Store


+ 0 - 0
webchat-client/.mvn/wrapper/maven-wrapper.properties → webchat-client-chat/.mvn/wrapper/maven-wrapper.properties


+ 3 - 3
webchat-client/pom.xml → webchat-client-chat/pom.xml

@@ -9,12 +9,12 @@
     </parent>
 
     <groupId>com.webchat</groupId>
-    <artifactId>webchat-client</artifactId>
+    <artifactId>webchat-client-chat</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <packaging>jar</packaging>
 
-    <name>webchat-client</name>
-    <description>webchat-client</description>
+    <name>webchat-client-chat</name>
+    <description>webchat-client-chat</description>
 
     <properties>
         <java.version>17</java.version>

+ 0 - 0
webchat-client/src/.DS_Store → webchat-client-chat/src/.DS_Store


+ 0 - 0
webchat-client/src/main/.DS_Store → webchat-client-chat/src/main/.DS_Store


+ 0 - 0
webchat-client/src/main/java/com/webchat/client/WebchatClientApplication.java → webchat-client-chat/src/main/java/com/webchat/client/WebchatClientApplication.java


+ 0 - 0
webchat-client/src/main/resources/application.properties → webchat-client-chat/src/main/resources/application.properties


+ 38 - 0
webchat-common/src/main/java/com/webchat/common/config/annotation/SafeClick.java

@@ -0,0 +1,38 @@
+package com.webchat.common.config.annotation;
+
+import com.webchat.common.enums.ClickEvent;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @Author: 程序员七七
+ * @Date: 27.11.21 12:26 上午
+ * 安全点击时间拦截自定义注解
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Documented
+public @interface SafeClick {
+
+    /***
+     * 事件KEY
+     * @return
+     */
+    ClickEvent event();
+
+    /***
+     * 默认500ml内只能允许一次点击操作,单位:毫秒
+     * @return
+     */
+    long time() default 500L;
+
+    /***
+     * 异常文案提示
+     * @return
+     */
+    String message() default "点击太频繁,休息会吧";
+}

+ 55 - 0
webchat-common/src/main/java/com/webchat/common/config/annotation/SafeClickInterceptor.java

@@ -0,0 +1,55 @@
+package com.webchat.common.config.annotation;
+
+import com.webchat.common.constants.WebConstant;
+import com.webchat.common.exception.AuthException;
+import com.webchat.common.exception.BusinessException;
+import com.webchat.common.helper.SessionHelper;
+import com.webchat.common.service.RedisService;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import java.lang.reflect.Method;
+
+/**
+ * 异常点击事件拦截
+ */
+@Slf4j
+public class SafeClickInterceptor implements HandlerInterceptor {
+
+    @Autowired
+    private RedisService redisService;
+    /**
+     * 在调用方法之前执行拦截
+     */
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+
+        HandlerMethod handlerMethod = (HandlerMethod) handler;
+        Method method = handlerMethod.getMethod();
+        SafeClick safeClick = method.getAnnotation(SafeClick.class);
+        if (safeClick == null) {
+            return true;
+        }
+        // 操作人
+        String userId = SessionHelper.getCurrentUserId();
+        if (StringUtils.isBlank(userId)) {
+            throw new AuthException("未登录!");
+        }
+        // 事件
+        String action = safeClick.event().name();
+        // 允许多长时间操作一次
+        long liveTime = safeClick.time();
+        String key = action.concat("-").concat(userId);
+        boolean installLockResult = redisService.installLockForMS(key, WebConstant.CACHE_NONE, liveTime);
+        if (installLockResult) {
+            return true;
+        }
+        log.error("<<<< {} >>>>, userId: {}, action: {}", safeClick.message(), userId, action);
+        throw new BusinessException(safeClick.message());
+    }
+}

+ 20 - 0
webchat-common/src/main/java/com/webchat/common/config/annotation/ValidateLogin.java

@@ -0,0 +1,20 @@
+package com.webchat.common.config.annotation;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @Author: 程序员七七
+ * @Date: 26.11.21 11:56 下午
+ * 自定义注解实现:校验是否登录
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Documented
+public @interface ValidateLogin {
+
+}

+ 37 - 0
webchat-common/src/main/java/com/webchat/common/config/annotation/ValidateLoginInterceptor.java

@@ -0,0 +1,37 @@
+package com.webchat.common.config.annotation;
+
+import com.webchat.common.exception.AuthException;
+import com.webchat.common.helper.SessionHelper;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import java.lang.reflect.Method;
+
+/**
+ * @Author: 程序员七七
+ * @Date: 27.11.21 12:07 上午
+ */
+public class ValidateLoginInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+        HandlerMethod handlerMethod = (HandlerMethod) handler;
+        // 获取拦截到的方法
+        Method method = handlerMethod.getMethod();
+        // 获取方法到的ValidateLogin注解
+        ValidateLogin validateLogin = method.getAnnotation(ValidateLogin.class);
+        if (validateLogin == null) {
+            // 未获取到登录鉴权注解,说明不需要拦截,直接放过
+            return true;
+        }
+        String userId = SessionHelper.getCurrentUserId();
+        if (StringUtils.isBlank(userId)) {
+            // 未登录!权限校验失败
+            throw new AuthException("未登录!");
+        }
+        return true;
+    }
+}

+ 25 - 0
webchat-common/src/main/java/com/webchat/common/config/annotation/ValidatePermission.java

@@ -0,0 +1,25 @@
+package com.webchat.common.config.annotation;
+
+import com.webchat.common.enums.RoleCodeEnum;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 自定义注解实现:校验是否管理员
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+@Documented
+public @interface ValidatePermission {
+
+    /***
+     * 需要进行校验的权限类型,默认校验管理员
+     * @see RoleCodeEnum
+     * @return
+     */
+    RoleCodeEnum[] role() default {RoleCodeEnum.ADMIN};
+}

+ 54 - 0
webchat-common/src/main/java/com/webchat/common/config/annotation/ValidatePermissionInterceptor.java

@@ -0,0 +1,54 @@
+package com.webchat.common.config.annotation;
+
+import com.webchat.common.enums.RoleCodeEnum;
+import com.webchat.common.exception.AuthException;
+import com.webchat.common.helper.SessionHelper;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import java.lang.reflect.Method;
+
+/**
+ * @Author: 程序员七七
+ * @Date: 27.11.21 12:07 上午
+ */
+public class ValidatePermissionInterceptor implements HandlerInterceptor {
+
+//    @Autowired
+//    private RoleService roleService;
+//
+//    @Override
+//    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+//        HandlerMethod handlerMethod = (HandlerMethod) handler;
+//        // 获取拦截到的方法
+//        Method method = handlerMethod.getMethod();
+//        // 获取方法到的RequestPermission注解
+//        ValidatePermission requestPermission = method.getAnnotation(ValidatePermission.class);
+//        if (requestPermission == null) {
+//            // 未获取到权控注解,说明不需要拦截,直接放过
+//            return true;
+//        }
+//        /***
+//         * 权限校验
+//         */
+//        if (requestPermission.role().length > 0) {
+//            RoleCodeEnum[] roleEnums = requestPermission.role();
+//            // 获取当前登录的用户ID
+//            String userId = SessionHelper.getCurrentUserId();
+//            if (StringUtils.isBlank(userId)) {
+//                // 未登录!权限校验失败
+//                throw new AuthException("未登录!");
+//            }
+//            // 一个一个校验,或者的关系:即满足任一权限则通过
+//            for (RoleCodeEnum roleEnum : roleEnums) {
+//                // 用户任一权限校验通过,则认为拥有操作权限
+//                if (roleService.hasRole(userId, roleEnum.getCode())) {
+//                    return true;
+//                }
+//            }
+//        }
+//        throw new AuthException("无权限!");
+//    }
+}

+ 58 - 0
webchat-common/src/main/java/com/webchat/common/config/configuration/WebChatWebMvcConfigurer.java

@@ -0,0 +1,58 @@
+package com.webchat.common.config.configuration;
+
+import com.webchat.common.config.annotation.SafeClickInterceptor;
+import com.webchat.common.config.annotation.ValidateLoginInterceptor;
+import com.webchat.common.config.annotation.ValidatePermissionInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/***
+ * Web 拦截器配置
+ **/
+@Configuration
+public class WebChatWebMvcConfigurer implements WebMvcConfigurer {
+
+    /***
+     * 注册自定义拦截器
+     * @param registry
+     */
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        /**
+         * 注册权限控制拦截器
+         */
+        registry.addInterceptor(validatePermissionInterceptor()).addPathPatterns("/api/**");
+        /**
+         * 注册登录核验拦截器
+         */
+        registry.addInterceptor(validateLoginInterceptor()).addPathPatterns("/api/**");
+        /**
+         * 防重复操作,安全点击
+         */
+        registry.addInterceptor(safeClickInterceptor()).addPathPatterns("/api/**");
+    }
+
+    /***
+     * 登录核验拦截器
+     * @return
+     */
+    @Bean
+    public ValidateLoginInterceptor validateLoginInterceptor() {
+        return new ValidateLoginInterceptor();
+    }
+    /***
+     * 权限控制拦截器
+     * @return
+     */
+    @Bean
+    public ValidatePermissionInterceptor validatePermissionInterceptor() {
+        return new ValidatePermissionInterceptor();
+    }
+
+    @Bean
+    public SafeClickInterceptor safeClickInterceptor() {
+        return new SafeClickInterceptor();
+    }
+}

+ 23 - 0
webchat-common/src/main/java/com/webchat/common/service/RedisMessageSender.java

@@ -0,0 +1,23 @@
+package com.webchat.common.service;
+
+import jakarta.annotation.Resource;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class RedisMessageSender {
+
+    @Resource
+    private RedisTemplate redisTemplate;
+
+    /**
+     * 发布消息
+     *
+     * @param channel
+     * @param message
+     */
+    public void sendMessage(String channel, String message) {
+
+        redisTemplate.convertAndSend(channel, message);
+    }
+}

+ 21 - 5
webchat-connect/pom.xml

@@ -12,6 +12,7 @@
     <artifactId>webchat-connect</artifactId>
     <version>0.0.1-SNAPSHOT</version>
     <packaging>jar</packaging>
+
     <name>webchat-connect</name>
     <description>webchat-connect</description>
 
@@ -21,14 +22,29 @@
     </properties>
     <dependencies>
         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
+            <groupId>com.webchat</groupId>
+            <artifactId>webchat-remote</artifactId>
+            <version>1.0-SNAPSHOT</version>
         </dependency>
-
+        <!-- ################################### 集成websocket ################################### -->
+        <!-- 引入 websocket 依赖类-->
+        <!-- Springboot对websocket的能力支持-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+        <!-- ServerEndpoint注解来自于javax.websocket-api这个包 -->
+        <dependency>
+            <groupId>javax.websocket</groupId>
+            <artifactId>javax.websocket-api</artifactId>
+            <version>1.1</version>
+            <scope>provided</scope>
+        </dependency>
+        <!-- tomcat服务队websocket的支持 -->
+        <dependency>
+            <groupId>org.apache.tomcat.embed</groupId>
+            <artifactId>tomcat-embed-websocket</artifactId>
+            <version>9.0.33</version>
         </dependency>
     </dependencies>
 

+ 34 - 0
webchat-connect/src/main/java/com/webchat/connect/javasse/EventStreamConnectController.java

@@ -0,0 +1,34 @@
+package com.webchat.connect.javasse;
+
+import com.webchat.common.config.annotation.ValidateLogin;
+import com.webchat.common.exception.BusinessException;
+import com.webchat.common.helper.SessionHelper;
+import com.webchat.common.helper.SseEmitterHelper;
+import jakarta.servlet.http.HttpServletRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
+
+@RestController
+@RequestMapping("/connect-service/event/")
+public class EventStreamConnectController {
+
+    /**
+     * 获取SSE链接对象
+     *
+     * @param request
+     * @return
+     */
+    @ValidateLogin
+    @GetMapping(path = "/stream", produces = "text/event-stream")
+    public SseEmitter stream(HttpServletRequest request) {
+        String biz = request.getParameter("biz");
+        String userId = SessionHelper.getCurrentUserId();
+        if (StringUtils.isBlank(userId)) {
+            throw new BusinessException("对话Stream流长链接获取异常,用户未登录!");
+        }
+        return SseEmitterHelper.get(biz, userId);
+    }
+}

+ 97 - 0
webchat-connect/src/main/java/com/webchat/connect/websocket/ChatWebSocketEndPoint.java

@@ -0,0 +1,97 @@
+package com.webchat.connect.websocket;
+
+import com.webchat.common.enums.RedisMessageChannelTopicEnum;
+import com.webchat.common.service.RedisMessageSender;
+import com.webchat.common.util.SpringContextUtil;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * OnOpen 表示有浏览器链接过来的时候被调用
+ * OnClose 表示浏览器发出关闭请求的时候被调用
+ * OnMessage 表示浏览器发消息的时候被调用
+ * OnError 表示有错误发生,比如网络断开了等等
+ */
+@Data
+@Slf4j
+@Component
+@ServerEndpoint("/connect-service/ws/chat/{userId}")
+public class ChatWebSocketEndPoint {
+
+    /**
+     * 在线人数
+     */
+    public static int onlineNumber = 0;
+
+    /**
+     * 以用户的Id作为key,WebSocket为对象保存起来
+     */
+    public static Map<String, ChatWebSocketEndPoint> clients = new ConcurrentHashMap<String, ChatWebSocketEndPoint>();
+
+    /**
+     * 会话
+     */
+    private Session session;
+
+    /**
+     * 用户ID
+     */
+    private String userId;
+
+    /**
+     * 建立连接
+     *
+     * @param session
+     */
+    @OnOpen
+    public void onOpen(@PathParam("userId") String userId, Session session) {
+        this.onlineNumber++;
+        this.userId = userId;
+        this.session = session;
+        clients.put(userId, this);
+        log.info("onOpen success. sessionId:{}, userId:{}, online user count:{}", session.getId(), userId, onlineNumber);
+    }
+
+    @OnError
+    public void onError(Session session, Throwable error) {
+        log.info("服务端发生了错误, error message:{}", error.getMessage());
+    }
+
+    /**
+     * 连接关闭
+     */
+    @OnClose
+    public void onClose() {
+        this.onlineNumber--;
+        this.clients.remove(userId);
+        log.info("onClose success! online user count:P{}", this.onlineNumber);
+    }
+
+    /**
+     * 收到客户端的消息
+     *
+     * @param message 消息
+     * @param session 会话
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+        if ("heartbeat".equals(message)) {
+            // 心跳检测
+            clients.get(userId).session.getAsyncRemote().sendText("ok");
+            return;
+        }
+        /**
+         * 基于redis发布订阅模式的分布式WebSocketSession共享问题解决方案
+         * 发布消息事件到Chat Topic
+         */
+        RedisMessageSender redisMessageSender = SpringContextUtil.getBean(RedisMessageSender.class);
+        redisMessageSender.sendMessage(RedisMessageChannelTopicEnum.CHAT.getChannel(), message);
+    }
+}

+ 0 - 1
webchat-connect/src/main/resources/application.properties

@@ -1 +0,0 @@
-spring.application.name=webchat-connect

+ 2 - 0
webchat-connect/src/main/resources/application.yml

@@ -0,0 +1,2 @@
+server:
+  port: 8088

+ 16 - 0
webchat-connect/src/main/resources/bootstrap.yml

@@ -0,0 +1,16 @@
+spring:
+  application:
+    name: webchat-connect-service
+  profiles:
+    active: dev
+  cloud:
+    nacos:
+      config:
+        server-addr: 127.0.0.1:8848
+        namespace: 2cdfb8e3-f127-4020-93df-2d4c3dc805b5
+        file-extension: yaml
+        group: DEFAULT_GROUP
+        refresh-enabled: true
+      discovery:
+        server-addr: 127.0.0.1:8848
+        namespace: 2cdfb8e3-f127-4020-93df-2d4c3dc805b5

+ 1 - 1
webchat-gateway/src/main/resources/application.yml

@@ -1 +1 @@
-server:
  port: 8080
spring:
  main:
    web-application-type: reactive
  cloud:
    gateway:
      routes:
          # 路由规则id,自定义,唯一
        - id: webchat-user-service
          # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表
          uri: lb://webchat-user-service
          # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务
          predicates:
            # 这里是以请求路径作为判断规则
            - Path=/user-service/**
+server:
  port: 8080
spring:
  main:
    web-application-type: reactive
  cloud:
    gateway:
      routes:
        - id: webchat-connect-service
          uri: lb://webchat-connect-service
          predicates:
            - Path=/connect-service/**
        - id: webchat-user-service
          uri: lb://webchat-user-service
          predicates:
            - Path=/user-service/**
        - id: webchat-pgc-service
          uri: lb://webchat-pgc-service
          predicates:
            - Path=/pgc-service/**