caozj 3 سال پیش
والد
کامیت
f310b096da
40فایلهای تغییر یافته به همراه1242 افزوده شده و 69 حذف شده
  1. 90 28
      bladex-tool/blade-core-tool/src/main/java/org/springblade/core/tool/api/R.java
  2. 56 0
      bladex/blade-common/src/main/java/org/springblade/common/constant/ApiConstant.java
  3. 21 0
      bladex/blade-common/src/main/java/org/springblade/common/constant/RedisCacheKeyConstant.java
  4. 22 1
      bladex/blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java
  5. 12 0
      bladex/blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java
  6. 1 0
      hx-saas-project/pom.xml
  7. 54 0
      hx-saas-project/saas-entity/src/main/java/com/fjhx/message/MessageNotice.java
  8. 64 0
      hx-saas-project/saas-entity/src/main/java/com/fjhx/message/enums/MessageNoticeEnum.java
  9. 66 0
      hx-saas-project/saas-entity/src/main/java/com/fjhx/message/enums/MsgSourceEnum.java
  10. 0 1
      hx-saas-project/saas-entity/src/main/java/com/fjhx/rocketmq/Message.java
  11. 0 2
      hx-saas-project/saas-feign-api/pom.xml
  12. 1 1
      hx-saas-project/saas-feign-api/saas-rocketmq-api/pom.xml
  13. 1 2
      hx-saas-project/saas-rocketmq/pom.xml
  14. 2 3
      hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/HxRocketMqApplication.java
  15. 3 3
      hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/consumer/ConsumerService.java
  16. 18 0
      hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/producer/ProducerController.java
  17. 67 0
      hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/service/Impl/RocketMqServiceImpl.java
  18. 25 0
      hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/service/RocketMqService.java
  19. 11 6
      hx-saas-project/saas-rocketmq/src/main/resources/application-dev.yml
  20. 9 5
      hx-saas-project/saas-rocketmq/src/main/resources/application-prod.yml
  21. 9 4
      hx-saas-project/saas-rocketmq/src/main/resources/application-test.yml
  22. 96 0
      hx-saas-project/saas-socket/pom.xml
  23. 21 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/SocketApplication.java
  24. 36 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/consumer/ConsumerService.java
  25. 22 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/notice/service/ISendNoticeService.java
  26. 78 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/notice/service/impl/SendNoticeServiceImpl.java
  27. 21 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/config/WebSocketConfig.java
  28. 148 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/endpoint/NoticeServerEndpoint.java
  29. 63 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/service/IWebSocketService.java
  30. 105 0
      hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/service/impl/WebSocketServiceImpl.java
  31. 24 0
      hx-saas-project/saas-socket/src/main/resources/application-dev.yml
  32. 24 0
      hx-saas-project/saas-socket/src/main/resources/application-prod.yml
  33. 24 0
      hx-saas-project/saas-socket/src/main/resources/application-test.yml
  34. 6 3
      hx-saas-project/saas-storage/pom.xml
  35. 2 3
      hx-saas-project/saas-storage/src/main/java/com/fjhx/HxStorageApplication.java
  36. 8 5
      hx-saas-project/saas-storage/src/main/java/com/fjhx/attachment/service/impl/StockAttachmentServiceImpl.java
  37. 10 0
      hx-saas-project/saas-storage/src/main/resources/application-dev.yml
  38. 10 1
      hx-saas-project/saas-storage/src/main/resources/application-prod.yml
  39. 10 0
      hx-saas-project/saas-storage/src/main/resources/application-test.yml
  40. 2 1
      hx-service/storage/src/main/java/com/fjhx/supplier/service/impl/SupplierServiceImpl.java

+ 90 - 28
bladex-tool/blade-core-tool/src/main/java/org/springblade/core/tool/api/R.java

@@ -1,19 +1,3 @@
-/*
- *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are met:
- *
- *  Redistributions of source code must retain the above copyright notice,
- *  this list of conditions and the following disclaimer.
- *  Redistributions in binary form must reproduce the above copyright
- *  notice, this list of conditions and the following disclaimer in the
- *  documentation and/or other materials provided with the distribution.
- *  Neither the name of the dreamlu.net developer nor the names of its
- *  contributors may be used to endorse or promote products derived from
- *  this software without specific prior written permission.
- *  Author: Chill 庄骞 (smallchill@163.com)
- */
 package org.springblade.core.tool.api;
 
 import io.swagger.annotations.ApiModel;
@@ -28,6 +12,10 @@ import org.springframework.lang.Nullable;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -46,13 +34,16 @@ public class R<T> implements Serializable {
 
     @ApiModelProperty(value = "状态码", required = true)
     private int code;
+
     @ApiModelProperty(value = "是否成功", required = true)
     private boolean success;
-    @ApiModelProperty(value = "承载数据")
-    private T data;
+
     @ApiModelProperty(value = "返回消息", required = true)
     private String msg;
 
+    @ApiModelProperty(value = "承载数据")
+    private T data;
+
     private R(IResultCode resultCode) {
         this(resultCode, null, resultCode.getMessage());
     }
@@ -71,9 +62,69 @@ public class R<T> implements Serializable {
 
     private R(int code, T data, String msg) {
         this.code = code;
-        this.data = data;
         this.msg = msg;
         this.success = ResultCode.SUCCESS.code == code;
+        this.data = data;
+    }
+
+    /**
+     * 返回统一列表报文
+     *
+     * @param data 数据
+     * @return R
+     */
+    public static <T> R<T> list(List<?> data) {
+        Map<String, List<?>> map = new HashMap<>();
+        map.put("list", Optional.ofNullable(data).orElse(new ArrayList<>()));
+        return success(map);
+    }
+
+    /**
+     * 返回统一数字报文
+     *
+     * @param count 数据
+     * @return R
+     */
+    public static <T> R<T> count(Integer count) {
+        Map<String, Integer> map = new HashMap<>();
+        map.put("count", Optional.ofNullable(count).orElse(0));
+        return success(map);
+    }
+
+    /**
+     * 返回统一数字报文
+     *
+     * @param count 数据
+     * @return R
+     */
+    public static <T> R<T> count(Long count) {
+        Map<String, Long> map = new HashMap<>();
+        map.put("count", Optional.ofNullable(count).orElse(0L));
+        return success(map);
+    }
+
+    /**
+     * 返回统一详情报文
+     *
+     * @param data 数据
+     * @return R
+     */
+    public static <T> R<T> details(Object data) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("details", Optional.ofNullable(data).orElse(new HashMap<>()));
+        return success(map);
+    }
+
+    /**
+     * 返回统一id报文
+     *
+     * @param id 数据id
+     * @return R
+     */
+    public static <T> R<T> id(Object id) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", Optional.ofNullable(id).orElse(""));
+        return success(map);
     }
 
     /**
@@ -137,6 +188,26 @@ public class R<T> implements Serializable {
     /**
      * 返回R
      *
+     * @param <T> T 泛型标记
+     * @return R
+     */
+    public static <T> R<T> success() {
+        return new R<>(ResultCode.SUCCESS, BladeConstant.DEFAULT_SUCCESS_MESSAGE);
+    }
+
+    /**
+     * 返回R
+     *
+     * @param <T> T 泛型标记
+     * @return R
+     */
+    public static <T> R<T> success(Object data) {
+        return new R(ResultCode.SUCCESS, data, BladeConstant.DEFAULT_SUCCESS_MESSAGE);
+    }
+
+    /**
+     * 返回R
+     *
      * @param msg 消息
      * @param <T> T 泛型标记
      * @return R
@@ -179,7 +250,6 @@ public class R<T> implements Serializable {
         return new R<>(ResultCode.FAILURE, msg);
     }
 
-
     /**
      * 返回R
      *
@@ -225,12 +295,4 @@ public class R<T> implements Serializable {
         return flag ? success(BladeConstant.DEFAULT_SUCCESS_MESSAGE) : fail(BladeConstant.DEFAULT_FAILURE_MESSAGE);
     }
 
-    public static <T> R<T> success() {
-        return R.success(BladeConstant.DEFAULT_SUCCESS_MESSAGE);
-    }
-
-    public static <T> R<T> success(T data) {
-        return data(data, BladeConstant.DEFAULT_SUCCESS_MESSAGE);
-    }
-
 }

+ 56 - 0
bladex/blade-common/src/main/java/org/springblade/common/constant/ApiConstant.java

@@ -0,0 +1,56 @@
+package org.springblade.common.constant;
+
+/**
+ * API常量
+ * @Author:caozj
+ * @DATE:2022/7/18 10:56
+ */
+public class ApiConstant {
+
+    /**
+     * 应用名前缀:SAAS
+     */
+    public static final String APPLICATION_NAME_PREFIX_SAAS = "saas-";
+
+
+    /**
+     * 系统服务名
+     */
+    public static class APP_NAME {
+
+        /**
+         * 仓库模块
+         */
+        public static final String STORAGE_APP_NAME = APPLICATION_NAME_PREFIX_SAAS + "storage";
+
+        /**
+         * 仓库模块
+         */
+        public static final String ROCKETMQ_APP_NAME = APPLICATION_NAME_PREFIX_SAAS + "rocketmq";
+
+        /**
+         * 仓库模块
+         */
+        public static final String SOCKET_APP_NAME = APPLICATION_NAME_PREFIX_SAAS + "socket";
+
+    }
+    /**
+     * 项目常量
+     */
+    public static class Project {
+        /**
+         * 业务服务请求路径前缀
+         */
+        public static final String SAAS_ROCKETMQ_REQUEST_PREFIX = "/hx/rocketmq";
+
+        /**
+         * 业务服务请求路径前缀
+         */
+        public static final String SAAS_SOCKET_REQUEST_PREFIX = "/hx/socket";
+
+        /**
+         * 业务服务请求路径前缀
+         */
+        public static final String SAAS_STORAGE_REQUEST_PREFIX = "/hx/storage";
+    }
+}

+ 21 - 0
bladex/blade-common/src/main/java/org/springblade/common/constant/RedisCacheKeyConstant.java

@@ -0,0 +1,21 @@
+package org.springblade.common.constant;
+
+/**
+ * @Description:
+ * @ClassName: RedisCacheKeyConstant
+ * @Author: caozj
+ * @Date: 2022/7/20 13:45
+ * @Version: 1.0
+ */
+public class RedisCacheKeyConstant {
+
+    /**
+     * 邮箱回执缓存key前缀
+     */
+    public static final String MAIL_RECEIPT_KEY = "mail:receipt:";
+
+    /**
+     * 用户登录记录缓存
+     */
+    public static final String USER_LOGIN_REDIS_CACHE_KEY = "websocket:login:user:";
+}

+ 22 - 1
bladex/blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java

@@ -28,6 +28,8 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 
+import java.util.List;
+
 /**
  * User Feign接口类
  *
@@ -46,7 +48,8 @@ public interface IUserClient {
 	String USER_AUTH_INFO = API_PREFIX + "/user-auth-info";
 	String SAVE_USER = API_PREFIX + "/save-user";
 	String REMOVE_USER = API_PREFIX + "/remove-user";
-
+	String INFO_USER= API_PREFIX + "/info-user";
+	String USER_INFO_BY_IDS = API_PREFIX + "/user-info-by-ids";
 	/**
 	 * 获取用户信息
 	 *
@@ -115,4 +118,22 @@ public interface IUserClient {
 	@PostMapping(REMOVE_USER)
 	R<Boolean> removeUser(@RequestParam("tenantIds") String tenantIds);
 
+	/**
+	 * 删除用户
+	 *
+	 * @param id 主键
+	 * @return
+	 */
+	@PostMapping(INFO_USER)
+	User infoUser(@RequestParam("id") String id);
+
+
+	/**
+	 * 根据用户id查询用户信息
+	 *
+	 * @param ids 用户id集合
+	 * @return
+	 */
+	@PostMapping(USER_INFO_BY_IDS)
+	List<User> userInfoByIds(@RequestBody List<String> ids);
 }

+ 12 - 0
bladex/blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java

@@ -31,6 +31,8 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.List;
+
 /**
  * 用户服务Feign实现类
  *
@@ -84,5 +86,15 @@ public class UserClient implements IUserClient {
 	public R<Boolean> removeUser(String tenantIds) {
 		return R.data(service.remove(Wrappers.<User>query().lambda().in(User::getTenantId, Func.toStrList(tenantIds))));
 	}
+	@PostMapping(INFO_USER)
+	@Override
+	public User infoUser(String id) {
+		return service.getById(id);
+	}
+	@PostMapping(USER_INFO_BY_IDS)
+	@Override
+	public List<User> userInfoByIds(List<String> ids) {
+		return service.list(Wrappers.<User>query().lambda().in(User::getId,ids));
+	}
 
 }

+ 1 - 0
hx-saas-project/pom.xml

@@ -41,6 +41,7 @@
         <module>saas-entity</module>
         <module>saas-storage</module>
         <module>saas-rocketmq</module>
+        <module>saas-socket</module>
     </modules>
 
     <dependencyManagement>

+ 54 - 0
hx-saas-project/saas-entity/src/main/java/com/fjhx/message/MessageNotice.java

@@ -0,0 +1,54 @@
+package com.fjhx.message;
+
+import lombok.Data;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.redis.core.index.Indexed;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * @ClassName: MessageNotice
+ * @Author: caozj
+ * @Date: 2021/10/22 10:39
+ * @Version: 1.0
+ */
+@Data
+public class MessageNotice implements Serializable {
+
+    /**
+     * 消息id
+     */
+    @Id
+    @Indexed
+    private String id;
+
+    /**
+     * 业务id
+     */
+    @Indexed
+    private String busiId;
+
+    /**
+     * 内容
+     */
+    private String content;
+
+    /**
+     * 消息类型
+     *
+     * @see com.fjhx.message.enums.MessageNoticeEnum
+     */
+    private Integer msgType;
+
+    /**
+     * 接受用户id
+     */
+    @Indexed
+    private String userId;
+
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+}

+ 64 - 0
hx-saas-project/saas-entity/src/main/java/com/fjhx/message/enums/MessageNoticeEnum.java

@@ -0,0 +1,64 @@
+package com.fjhx.message.enums;
+
+import org.apache.commons.collections4.MapUtils;
+import org.springblade.core.tool.utils.StringPool;
+
+import java.util.LinkedHashMap;
+
+/**
+ * 消息通知类型枚举
+ */
+public enum MessageNoticeEnum {
+
+    MESSAGE_NOTICE_TYPE_1(1, "申购"),
+    ;
+
+    private int key;
+
+    private String value;
+
+    private static LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
+
+    MessageNoticeEnum(int key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    /**
+     * 获取枚举map
+     *
+     * @return
+     */
+    public static LinkedHashMap<Integer, String> getMap() {
+        if (MapUtils.isNotEmpty(map)) {
+            return map;
+        }
+        for (MessageNoticeEnum ms : values()) {
+            map.put(ms.key, ms.value);
+        }
+        return map;
+    }
+
+    /**
+     * 通过key获取名称
+     *
+     * @param key
+     * @return
+     */
+    public static String getNameByKey(Integer key) {
+        if (key == null || key < 0) {
+            return "";
+        }
+        LinkedHashMap<Integer, String> map = getMap();
+        return map.getOrDefault(key, StringPool.EMPTY);
+    }
+
+    public int getKey() {
+        return key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}

+ 66 - 0
hx-saas-project/saas-entity/src/main/java/com/fjhx/message/enums/MsgSourceEnum.java

@@ -0,0 +1,66 @@
+package com.fjhx.message.enums;
+
+import org.apache.commons.collections4.MapUtils;
+import org.springblade.core.tool.utils.StringPool;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 消息来源枚举
+ */
+public enum MsgSourceEnum {
+
+    MSG_SOURCE_1(1, "消息通知"),
+
+    ;
+
+    private int key;
+
+    private String value;
+
+    private static Map<Integer, String> map = new HashMap<>();
+
+    MsgSourceEnum(int key, String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    /**
+     * 获取枚举map
+     *
+     * @return
+     */
+    public static Map<Integer, String> getMap() {
+        if (MapUtils.isNotEmpty(map)) {
+            return map;
+        }
+        for (MsgSourceEnum ms : values()) {
+            map.put(ms.key, ms.value);
+        }
+        return map;
+    }
+
+    /**
+     * 通过key获取名称
+     *
+     * @param key
+     * @return
+     */
+    public static String getNameByKey(Integer key) {
+        if (key == null || key < 0) {
+            return StringPool.EMPTY;
+        }
+        Map<Integer, String> map = getMap();
+        return map.getOrDefault(key, StringPool.EMPTY);
+    }
+
+    public int getKey() {
+        return key;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+}

+ 0 - 1
hx-saas-project/saas-entity/src/main/java/com/fjhx/rocketmq/Message.java

@@ -12,6 +12,5 @@ public class Message {
     private String tag;
     private Object content;
     private String key;
-    private String
 
 }

+ 0 - 2
hx-saas-project/saas-feign-api/pom.xml

@@ -10,8 +10,6 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>saas-feign-api</artifactId>
-    <groupId>com.fjhx</groupId>
-    <name>${project.artifactId}</name>
     <version>2.8.2.RELEASE</version>
     <packaging>pom</packaging>
     <description>saas 微服务API集合</description>

+ 1 - 1
hx-saas-project/saas-feign-api/saas-rocketmq-api/pom.xml

@@ -9,7 +9,7 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>saas-business-api</artifactId>
+    <artifactId>saas-rocketmq-api</artifactId>
     <name>${project.artifactId}</name>
     <version>2.8.2.RELEASE</version>
     <description>saas 业务模块 微服务API</description>

+ 1 - 2
hx-saas-project/saas-rocketmq/pom.xml

@@ -10,7 +10,6 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>saas-rocketmq</artifactId>
-    <name>${project.artifactId}</name>
     <version>2.8.2.RELEASE</version>
     <packaging>jar</packaging>
 
@@ -25,7 +24,7 @@
         </dependency>
         <dependency>
             <groupId>com.fjhx</groupId>
-            <artifactId>saas-feign-api</artifactId>
+            <artifactId>saas-rocketmq-api</artifactId>
             <version>${bladex.project.version}</version>
         </dependency>
     </dependencies>

+ 2 - 3
hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/HxRocketMqApplication.java

@@ -1,5 +1,6 @@
 package com.fjhx;
 
+import org.springblade.common.constant.ApiConstant;
 import org.springblade.core.cloud.feign.EnableBladeFeign;
 import org.springblade.core.launch.BladeApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -17,10 +18,8 @@ import org.springframework.scheduling.annotation.EnableAsync;
 @SpringBootApplication
 public class HxRocketMqApplication {
 
-    private static final String APP_NAME = "hx-rocketmq";
-
     public static void main(String[] args) {
-        BladeApplication.run(APP_NAME, HxRocketMqApplication.class, args);
+        BladeApplication.run(ApiConstant.APP_NAME.ROCKETMQ_APP_NAME, HxRocketMqApplication.class, args);
     }
 
 }

+ 3 - 3
hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/consumer/ConsumerService.java

@@ -11,9 +11,9 @@ import org.springframework.stereotype.Service;
  * @date 2020/6/22
  */
 @Service
-@RocketMQMessageListener(topic = "topicOne",
-        consumerGroup = "consumerOne",
-        selectorExpression = "tagOne")
+@RocketMQMessageListener(topic = "topic-rocketmq",
+        consumerGroup = "consumer-rocketmq",
+        selectorExpression = "tag-rocketmq")
 public class ConsumerService implements RocketMQListener<String> {
 
     private DefaultMQPushConsumer consumer;

+ 18 - 0
hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/producer/ProducerController.java

@@ -1,5 +1,13 @@
 package com.fjhx.rocketmq.producer;
 
+import com.fjhx.attachment.StockAttachmentVo;
+import com.fjhx.rocketmq.Message;
+import com.fjhx.rocketmq.service.RocketMqService;
+import org.springblade.core.tool.api.R;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.UUID;
@@ -10,6 +18,16 @@ import java.util.UUID;
  * @date 2020/5/19
  */
 @RestController
+@RequestMapping("/rocketmq")
 public class ProducerController {
 
+    @Autowired
+    private RocketMqService rocketMqService;
+
+
+    @PostMapping("/senMsg")
+    public R add(@RequestBody Message message){
+        rocketMqService.send(message);
+        return R.success();
+    }
 }

+ 67 - 0
hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/service/Impl/RocketMqServiceImpl.java

@@ -1,14 +1,24 @@
 package com.fjhx.rocketmq.service.Impl;
 
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.message.MessageNotice;
+import com.fjhx.message.enums.MsgSourceEnum;
 import com.fjhx.rocketmq.Message;
 import com.fjhx.rocketmq.service.RocketMqService;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.rocketmq.client.producer.SendCallback;
 import org.apache.rocketmq.client.producer.SendResult;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.messaging.support.MessageBuilder;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
 /**
  * @Author:caozj
  * @DATE:2022/7/15 23:36
@@ -19,6 +29,8 @@ public class RocketMqServiceImpl implements RocketMqService {
     @Autowired
     private RocketMQTemplate rocketMQTemplate;
 
+    @Autowired
+    private IUserClient iUserClient;
     /**
      * 普通消息
      * @param msg
@@ -59,4 +71,59 @@ public class RocketMqServiceImpl implements RocketMqService {
         System.err.println("syncSendOrderly发送消息:"+msg);
         rocketMQTemplate.sendOneWay(msg.getTopic() + ":" + msg.getTag(), msg.getContent());
     }
+
+    /**
+     * 同步消息
+     */
+    public void syncSend(Message msg) {
+        System.err.println("同步消息:"+msg);
+        SendResult sendMessage = rocketMQTemplate.syncSend(msg.getTopic() + ":" + msg.getTag(),  msg.getContent());
+        System.out.println(sendMessage);
+    }
+
+    /**
+     * 通用发送消息
+     * @param busiId  业务id
+     * @param userIds 接受用户id集合
+     * @param content 内容
+     * @param msgType 消息类型
+     */
+    @Override
+    public void send(String topic,String tag,String key,String busiId, List<String> userIds, String content, Integer msgType) {
+        List<MessageNotice> notices = new ArrayList<>();
+        if (CollectionUtils.isEmpty(userIds)) {
+            return;
+        }
+        for (String userId : userIds) {
+            MessageNotice notice = new MessageNotice();
+            notice.setBusiId(busiId);
+            notice.setContent(content);
+            notice.setMsgType(msgType);
+            notice.setUserId(userId);
+            notice.setCreateTime(new Date());
+            notices.add(notice);
+        }
+        //储存消息体
+        try {
+            // -------------------- 往websocket推送消息 --------------------
+            // 查询用户数据
+            List<User> users = iUserClient.userInfoByIds(userIds);
+
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("messageId", busiId);
+            jsonObject.put("msgSource", MsgSourceEnum.MSG_SOURCE_1.getKey());
+            jsonObject.put("userIds", userIds);
+            jsonObject.put("users", users);
+            jsonObject.put("notices", notices);
+            //发送消息
+            Message msg = new Message();
+            msg.setTopic(topic);
+            msg.setTag(tag);
+            msg.setKey(key);
+            msg.setContent(jsonObject);
+            this.syncSend(msg);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 }

+ 25 - 0
hx-saas-project/saas-rocketmq/src/main/java/com/fjhx/rocketmq/service/RocketMqService.java

@@ -1,6 +1,9 @@
 package com.fjhx.rocketmq.service;
 
 import com.fjhx.rocketmq.Message;
+import org.springframework.scheduling.annotation.Async;
+
+import java.util.List;
 
 /**
  * @Author:caozj
@@ -19,4 +22,26 @@ public interface RocketMqService {
      * 单向发送消息,不关心返回结果,容易消息丢失,适合日志收集、不精确统计等消息发送;
      */
     void syncSendOrderly(Message mqMsg);
+
+    /**
+     * 同步消息
+     * @param mqMsg
+     */
+    void syncSend(Message mqMsg);
+
+
+    /**
+     *
+     * @param topic 主题
+     * @param tag 消息类型
+     * @param key key值
+     * @param busiId  业务id
+     * @param userIds 接受用户id集合
+     * @param content 内容
+     * @param msgType 消息类型
+     */
+    @Async
+    void send(String topic,String tag,String key,String busiId, List<String> userIds, String content, Integer msgType);
+
+
 }

+ 11 - 6
hx-saas-project/saas-rocketmq/src/main/resources/application-dev.yml

@@ -1,6 +1,6 @@
 # 服务器端口
 server:
-  port: 8301
+  port: 8302
 logging:
   level:
     org.springframework.data.mongodb.core: DEBUG
@@ -8,12 +8,17 @@ logging:
 spring:
   # 数据库
   datasource:
-    url: ${blade.datasource.storage.dev.url}
-    username: ${blade.datasource.storage.dev.username}
-    password: ${blade.datasource.storage.dev.password}
+    url: ${blade.datasource.rocketmq.dev.url}
+    username: ${blade.datasource.rocketmq.dev.username}
+    password: ${blade.datasource.rocketmq.dev.password}
 
 #rocketmq 配置
 rocketmq:
-  name-server: 127.0.0.1:9876
+  name-server: 114.116.8.29:9876
   producer:
-    group: java
+    group: my-group  # 指定发送者组名
+    send-message-timeout: 3000 #超时时间
+    compress-message-body-threshold: 4096 #消息压缩
+    max-message-size: 4194304 #消息体最大大小
+    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次。
+    retry-times-when-send-async-failed: 3 # 异步发送消息时,失败重试次数。默认为 2 次

+ 9 - 5
hx-saas-project/saas-rocketmq/src/main/resources/application-prod.yml

@@ -1,12 +1,16 @@
 # 服务器端口
 server:
-  port: 8301
+  port: 8302
 
 # 数据源配置
 spring:
   # 数据库
   datasource:
-    url: ${blade.datasource.storage.prod.url}
-    username: ${blade.datasource.storage.prod.username}
-    password: ${blade.datasource.storage.prod.password}
-
+    url: ${blade.datasource.rocketmq.prod.url}
+    username: ${blade.datasource.rocketmq.prod.username}
+    password: ${blade.datasource.rocketmq.prod.password}
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: java

+ 9 - 4
hx-saas-project/saas-rocketmq/src/main/resources/application-test.yml

@@ -1,11 +1,16 @@
 # 服务器端口
 server:
-  port: 8301
+  port: 8302
 
 # 数据源配置
 spring:
   # 数据库
   datasource:
-    url: ${blade.datasource.storage.test.url}
-    username: ${blade.datasource.storage.test.username}
-    password: ${blade.datasource.storage.test.password}
+    url: ${blade.datasource.rocketmq.test.url}
+    username: ${blade.datasource.rocketmq.test.username}
+    password: ${blade.datasource.rocketmq.test.password}
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: java

+ 96 - 0
hx-saas-project/saas-socket/pom.xml

@@ -0,0 +1,96 @@
+<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>hx-saas-project</artifactId>
+        <groupId>com.fjhx</groupId>
+        <version>2.8.2.RELEASE</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.fjhx</groupId>
+    <artifactId>saas-socket</artifactId>
+    <name>${project.artifactId}</name>
+    <version>2.8.2.RELEASE</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-boot</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-starter-excel</artifactId>
+        </dependency>
+        <!-- websocket -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx</groupId>
+            <artifactId>saas-rocketmq-api</artifactId>
+            <version>${bladex.project.version}</version>
+        </dependency>
+        <!-- 过滤掉内嵌的tomcat,防止websocket bean注入失败 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>com.spotify</groupId>
+                <artifactId>dockerfile-maven-plugin</artifactId>
+                <configuration>
+                    <username>${docker.username}</username>
+                    <password>${docker.password}</password>
+                    <repository>${docker.registry.url}/${docker.namespace}/${project.artifactId}</repository>
+                    <tag>${project.version}</tag>
+                    <useMavenSettingsForAuth>true</useMavenSettingsForAuth>
+                    <buildArgs>
+                        <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
+                    </buildArgs>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+
+                <configuration>
+                    <includeSystemScope>true</includeSystemScope>
+                    <mainClass>com.fjhx.SocketApplication</mainClass>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 21 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/SocketApplication.java

@@ -0,0 +1,21 @@
+package com.fjhx;
+
+import org.springblade.common.constant.ApiConstant;
+import org.springblade.core.cloud.feign.EnableBladeFeign;
+import org.springblade.core.launch.BladeApplication;
+import org.springframework.cloud.client.SpringCloudApplication;
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ * 外贸业务模块启动器
+ */
+@EnableBladeFeign
+@SpringCloudApplication
+@ComponentScan({"org.springblade", "com.fjhx"})
+public class SocketApplication {
+
+    public static void main(String[] args) {
+        BladeApplication.run(ApiConstant.APP_NAME.SOCKET_APP_NAME, SocketApplication.class, args);
+    }
+
+}

+ 36 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/consumer/ConsumerService.java

@@ -0,0 +1,36 @@
+package com.fjhx.consumer;
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.message.enums.MsgSourceEnum;
+import com.fjhx.notice.service.ISendNoticeService;
+import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
+import org.apache.rocketmq.spring.core.RocketMQListener;
+import org.springblade.core.tool.utils.SpringUtils;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * @author caozhoujun
+ * @version 1.2
+ * @date 2020/6/22
+ */
+@Service
+@RocketMQMessageListener(topic = "topic-ws",
+        consumerGroup = "consumer-ws",
+        selectorExpression = "tag-ws")
+public class ConsumerService implements RocketMQListener<String> {
+
+    private ISendNoticeService iSendNoticeService = SpringUtils.getBean(ISendNoticeService.class);
+
+    @Override
+    public void onMessage(String message) {
+        System.out.println(message);
+        JSONObject jsonObject = JSONObject.parseObject(message);
+        /**
+         * 消息来源
+         */
+        Integer msgSource = jsonObject.getInteger("msgSource");
+        if (MsgSourceEnum.MSG_SOURCE_1.getKey() == msgSource) {//如果等于消息通知
+            iSendNoticeService.send(jsonObject);
+        }
+    }
+}

+ 22 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/notice/service/ISendNoticeService.java

@@ -0,0 +1,22 @@
+package com.fjhx.notice.service;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.scheduling.annotation.Async;
+
+/**
+ * @Description: 消息通知接口
+ * @ClassName: ISendNoticeService
+ * @Author: caozj
+ * @Date: 2022/07/17 13:36
+ * @Version: 1.0
+ */
+public interface ISendNoticeService {
+
+    /**
+     * 发送消息
+     *
+     * @param jsonObject
+     */
+    @Async
+    void send(JSONObject jsonObject);
+}

+ 78 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/notice/service/impl/SendNoticeServiceImpl.java

@@ -0,0 +1,78 @@
+package com.fjhx.notice.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.message.MessageNotice;
+import com.fjhx.notice.service.ISendNoticeService;
+import com.fjhx.websocket.service.IWebSocketService;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.springblade.system.user.entity.User;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @Description: 消息通知接口实现类
+ * @ClassName: SendNoticeServiceImpl
+ * @Author: linqt
+ * @Date: 2021/11/9 13:37
+ * @Version: 1.0
+ */
+@Service
+public class SendNoticeServiceImpl implements ISendNoticeService {
+
+    @Autowired
+    private IWebSocketService iWebSocketService;
+
+    /**
+     * 发送消息
+     *
+     * @param jsonObject
+     */
+    @Override
+    public void send(JSONObject jsonObject) {
+        List<String> userIds = jsonObject.getJSONArray("userIds").toJavaList(String.class);
+        List<User> users = jsonObject.getJSONArray("users").toJavaList(User.class);
+        List<MessageNotice> notices = jsonObject.getJSONArray("notices").toJavaList(MessageNotice.class);
+
+        /**
+         * 消息来源
+         */
+        Integer msgSource = jsonObject.getInteger("msgSource");
+
+        Map<String, User> usersMap = new HashMap<>();
+        if (CollectionUtils.isNotEmpty(users)) {
+            usersMap = users.stream().collect(Collectors.toMap(o -> String.valueOf(o.getId()), Function.identity(), (key1, key2) -> key2));
+        }
+        // 消息对象集合map
+        Map<String, MessageNotice> noticesMap = notices.stream().collect(Collectors.toMap(MessageNotice::getUserId, Function.identity(), (key1, key2) -> key2));
+        for (String userId : userIds) {
+            // 获取用户id
+            if (MapUtils.isEmpty(usersMap) || usersMap.get(userId) == null) {
+                continue;
+            }
+            // 用户对象
+            User user = usersMap.get(userId);
+
+            // 获取消息体
+            if (MapUtils.isEmpty(noticesMap) || noticesMap.get(userId) == null) {
+                continue;
+            }
+            // 消息体
+            MessageNotice notice = noticesMap.get(userId);
+
+            JSONObject object = new JSONObject();
+            object.put("msgSource", msgSource);
+            object.put("notice", notice);
+
+            // 推送消息
+            iWebSocketService.pushByUserId(String.valueOf(user.getId()), object.toJSONString());
+        }
+    }
+
+}

+ 21 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/config/WebSocketConfig.java

@@ -0,0 +1,21 @@
+package com.fjhx.websocket.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+/**
+ * @Description:
+ * @ClassName: WebSocketConfig
+ * @Author: linqt
+ * @Date: 2022/2/22 20:35
+ * @Version: 1.0
+ */
+@Configuration
+public class WebSocketConfig {
+    
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+}

+ 148 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/endpoint/NoticeServerEndpoint.java

@@ -0,0 +1,148 @@
+package com.fjhx.websocket.endpoint;
+
+import com.alibaba.fastjson.JSONObject;
+import com.fjhx.websocket.service.IWebSocketService;
+import lombok.extern.log4j.Log4j2;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springblade.common.constant.ApiConstant;
+import org.springblade.common.constant.RedisCacheKeyConstant;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.tool.utils.SpringUtils;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.OnClose;
+import javax.websocket.OnError;
+import javax.websocket.OnMessage;
+import javax.websocket.OnOpen;
+import javax.websocket.Session;
+import javax.websocket.server.ServerEndpoint;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * websocket endpoint
+ */
+@Log4j2
+@Component
+@ServerEndpoint(value = ApiConstant.Project.SAAS_SOCKET_REQUEST_PREFIX + "/websocket/notice")
+public class NoticeServerEndpoint {
+
+    private IWebSocketService webSocketService = SpringUtils.getBean(IWebSocketService.class);
+
+    private BladeRedis redisCache = SpringUtils.getBean(BladeRedis.class);
+
+    private IUserClient iUserClient = SpringUtils.getBean(IUserClient.class);
+
+    /**
+     * 全部在线会话,key=登录账号ID
+     */
+    public static ConcurrentHashMap<String, Session> ONLINE_SESSIONS = new ConcurrentHashMap<>();
+
+    /**
+     * 客户端连接到服务端
+     *
+     * @param session
+     */
+    @OnOpen
+    public void onOpen(Session session) {
+        // 登入账号ID
+        String userId = getUserId(session);
+        if (StringUtils.isBlank(userId)) {
+            return;
+        }
+
+        User details = iUserClient.infoUser(userId);
+
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("userId", details.getId());
+        jsonObject.put("userName", details.getRealName());
+
+        //登陆成功,存入缓存
+        redisCache.set(RedisCacheKeyConstant.USER_LOGIN_REDIS_CACHE_KEY + userId, jsonObject);
+
+        log.info("账户:{} 连接系统", userId);
+        ONLINE_SESSIONS.put(userId, session);
+    }
+
+    /**
+     * 客户端发送消息给系统
+     *
+     * @param session
+     * @param msg
+     */
+    @OnMessage
+    public void onMessage(Session session, String msg) {
+        String userId = getUserId(session);
+        log.info("客户端账户:{} 发送消息到服务端,消息内容:{}", userId, msg);
+
+        webSocketService.pushByUserId(userId, "测试发送消息");
+    }
+
+    /**
+     * 客户端关闭连接,移除会话对象
+     *
+     * @param session
+     */
+    @OnClose
+    public void onClose(Session session) {
+        // 登入账号ID
+        String userId = getUserId(session);
+        if (StringUtils.isBlank(userId)) {
+            return;
+        }
+
+        //登出成功,清空缓存
+        redisCache.del(RedisCacheKeyConstant.USER_LOGIN_REDIS_CACHE_KEY + userId, userId);
+
+        log.info("账户:{} 断开连接", userId);
+        ONLINE_SESSIONS.remove(userId);
+    }
+
+    /**
+     * 当通信发生异常
+     *
+     * @param session
+     * @param error
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        error.printStackTrace();
+    }
+
+    /**
+     * 获取登录账号ID
+     *
+     * @param session
+     * @return
+     */
+    private static String getUserId(Session session) {
+        Map<String, String> requestParameterMap = getRequestParameterMap(session);
+        // 登录账号ID
+        String userId = requestParameterMap.get("userId");
+        return userId;
+    }
+
+    /**
+     * 获取请求参数
+     *
+     * @param session
+     * @return
+     */
+    public static Map<String, String> getRequestParameterMap(Session session) {
+        Map<String, List<String>> requestParameterMap = session.getRequestParameterMap();
+        if (MapUtils.isEmpty(requestParameterMap)) {
+            return new HashMap<>();
+        }
+        HashMap<String, String> hashMap = new HashMap<>();
+        for (Map.Entry<String, List<String>> entry : requestParameterMap.entrySet()) {
+            hashMap.put(entry.getKey(), entry.getValue().get(0));
+        }
+        return hashMap;
+    }
+
+}

+ 63 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/service/IWebSocketService.java

@@ -0,0 +1,63 @@
+package com.fjhx.websocket.service;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springblade.core.tool.api.R;
+import org.springframework.scheduling.annotation.Async;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * web socket 消息推送
+ */
+public interface IWebSocketService {
+
+    default String msgJson(List<String> msg) {
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("rows", msg);
+        String jsonStr = JSONObject.toJSONString(R.details(jsonObject));
+        return jsonStr;
+    }
+
+    default String msgJson(String msg) {
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("rows", Arrays.asList(msg));
+        String jsonStr = JSONObject.toJSONString(R.details(jsonObject));
+        return jsonStr;
+    }
+
+    /**
+     * 推送给在线所有人
+     *
+     * @param msg
+     */
+    @Async
+    void pushAll(String msg);
+
+    /**
+     * 根据登入账号ID推送
+     *
+     * @param userId
+     * @param msg
+     */
+    @Async
+    void pushByUserId(String userId, String msg);
+
+    /**
+     * 根据登入账号ID推送
+     *
+     * @param userId
+     * @param msg
+     */
+    @Async
+    void pushByUserId(String userId, List<String> msg);
+
+
+    /**
+     * 退出
+     *
+     * @param userId
+     */
+    void destroy(String userId);
+
+}

+ 105 - 0
hx-saas-project/saas-socket/src/main/java/com/fjhx/websocket/service/impl/WebSocketServiceImpl.java

@@ -0,0 +1,105 @@
+package com.fjhx.websocket.service.impl;
+
+import com.fjhx.websocket.endpoint.NoticeServerEndpoint;
+import com.fjhx.websocket.service.IWebSocketService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import javax.websocket.RemoteEndpoint;
+import javax.websocket.Session;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * web socket 消息推送
+ */
+@Slf4j
+@Service
+public class WebSocketServiceImpl implements IWebSocketService {
+
+    /**
+     * 推送给在线所有人
+     *
+     * @param msg
+     */
+    @Override
+    public void pushAll(String msg) {
+        NoticeServerEndpoint.ONLINE_SESSIONS.forEach((id, session) -> {
+            try {
+                RemoteEndpoint.Basic basicRemote = session.getBasicRemote();
+                basicRemote.sendText(msgJson(msg));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        });
+    }
+
+    /**
+     * 根据登入账号ID推送在线用户
+     *
+     * @param userId
+     * @param msg
+     */
+    @Override
+    public void pushByUserId(String userId, String msg) {
+        try {
+            if (StringUtils.isBlank(userId)) {
+                return;
+            }
+            Session session = NoticeServerEndpoint.ONLINE_SESSIONS.get(userId);
+            if (session == null) {
+                return;
+            }
+            RemoteEndpoint.Basic basicRemote = session.getBasicRemote();
+            basicRemote.sendText(msgJson(msg));
+            log.info("推送消息给:{} ,消息内容:{}", userId, msg);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 根据登入账号ID推送在线用户
+     *
+     * @param userId
+     * @param msg
+     */
+    @Override
+    public void pushByUserId(String userId, List<String> msg) {
+        try {
+            Session session = NoticeServerEndpoint.ONLINE_SESSIONS.get(userId);
+            if (session == null) {
+                return;
+            }
+            RemoteEndpoint.Basic basicRemote = session.getBasicRemote();
+            basicRemote.sendText(msgJson(msg));
+            log.info("推送消息给:{} ,消息内容:{}", userId, msg);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 退出
+     *
+     * @param userId
+     */
+    @Override
+    public void destroy(String userId) {
+        if (StringUtils.isNotBlank(userId)) {
+            try {
+                //关闭session
+                Session session = NoticeServerEndpoint.ONLINE_SESSIONS.get(userId);
+                session.close();
+                //从在线会话map中移除
+                NoticeServerEndpoint.ONLINE_SESSIONS.remove(userId);
+            } catch (Exception e) {
+                log.debug("退出web socket失败:" + userId + "," + e.getMessage());
+            }
+        }
+    }
+
+}

+ 24 - 0
hx-saas-project/saas-socket/src/main/resources/application-dev.yml

@@ -0,0 +1,24 @@
+# 服务器端口
+server:
+  port: 8303
+logging:
+  level:
+    org.springframework.data.mongodb.core: DEBUG
+# 数据源配置
+spring:
+  # 数据库
+  datasource:
+    url: ${blade.datasource.socket.dev.url}
+    username: ${blade.datasource.socket.dev.username}
+    password: ${blade.datasource.socket.dev.password}
+
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: my-group  # 指定发送者组名
+    send-message-timeout: 3000 #超时时间
+    compress-message-body-threshold: 4096 #消息压缩
+    max-message-size: 4194304 #消息体最大大小
+    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次。
+    retry-times-when-send-async-failed: 3 # 异步发送消息时,失败重试次数。默认为 2 次

+ 24 - 0
hx-saas-project/saas-socket/src/main/resources/application-prod.yml

@@ -0,0 +1,24 @@
+# 服务器端口
+server:
+  port: 8303
+logging:
+  level:
+    org.springframework.data.mongodb.core: DEBUG
+# 数据源配置
+spring:
+  # 数据库
+  datasource:
+    url: ${blade.datasource.socket.prod.url}
+    username: ${blade.datasource.socket.prod.username}
+    password: ${blade.datasource.socket.prod.password}
+
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: my-group  # 指定发送者组名
+    send-message-timeout: 3000 #超时时间
+    compress-message-body-threshold: 4096 #消息压缩
+    max-message-size: 4194304 #消息体最大大小
+    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次。
+    retry-times-when-send-async-failed: 3 # 异步发送消息时,失败重试次数。默认为 2 次

+ 24 - 0
hx-saas-project/saas-socket/src/main/resources/application-test.yml

@@ -0,0 +1,24 @@
+# 服务器端口
+server:
+  port: 8303
+logging:
+  level:
+    org.springframework.data.mongodb.core: DEBUG
+# 数据源配置
+spring:
+  # 数据库
+  datasource:
+    url: ${blade.datasource.socket.test.url}
+    username: ${blade.datasource.socket.test.username}
+    password: ${blade.datasource.socket.test.password}
+
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: my-group  # 指定发送者组名
+    send-message-timeout: 3000 #超时时间
+    compress-message-body-threshold: 4096 #消息压缩
+    max-message-size: 4194304 #消息体最大大小
+    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次。
+    retry-times-when-send-async-failed: 3 # 异步发送消息时,失败重试次数。默认为 2 次

+ 6 - 3
hx-saas-project/saas-storage/pom.xml

@@ -9,9 +9,7 @@
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <groupId>com.fjhx</groupId>
     <artifactId>saas-storage</artifactId>
-    <name>${project.artifactId}</name>
     <version>2.8.2.RELEASE</version>
     <packaging>jar</packaging>
 
@@ -26,7 +24,12 @@
         </dependency>
         <dependency>
             <groupId>com.fjhx</groupId>
-            <artifactId>saas-feign-api</artifactId>
+            <artifactId>saas-rocketmq-api</artifactId>
+            <version>${bladex.project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fjhx</groupId>
+            <artifactId>saas-rocketmq</artifactId>
             <version>${bladex.project.version}</version>
         </dependency>
     </dependencies>

+ 2 - 3
hx-saas-project/saas-storage/src/main/java/com/fjhx/HxStorageApplication.java

@@ -1,5 +1,6 @@
 package com.fjhx;
 
+import org.springblade.common.constant.ApiConstant;
 import org.springblade.core.cloud.feign.EnableBladeFeign;
 import org.springblade.core.launch.BladeApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -17,10 +18,8 @@ import org.springframework.scheduling.annotation.EnableAsync;
 @SpringBootApplication
 public class HxStorageApplication {
 
-    private static final String APP_NAME = "hx-storage";
-
     public static void main(String[] args) {
-        BladeApplication.run(APP_NAME, HxStorageApplication.class, args);
+        BladeApplication.run(ApiConstant.APP_NAME.STORAGE_APP_NAME, HxStorageApplication.class, args);
     }
 
 }

+ 8 - 5
hx-saas-project/saas-storage/src/main/java/com/fjhx/attachment/service/impl/StockAttachmentServiceImpl.java

@@ -1,22 +1,21 @@
 package com.fjhx.attachment.service.impl;
 
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fjhx.attachment.StockAttachment;
 import com.fjhx.attachment.StockAttachmentVo;
 import com.fjhx.attachment.mapper.StockAttachmentMapper;
 import com.fjhx.attachment.service.StockAttachmentService;
+import com.fjhx.message.enums.MessageNoticeEnum;
+import com.fjhx.rocketmq.service.RocketMqService;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tenant.annotation.TenantIgnore;
 import org.springblade.core.tool.utils.StringUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * <p>
@@ -29,6 +28,8 @@ import java.util.Map;
 @Service
 public class StockAttachmentServiceImpl extends ServiceImpl<StockAttachmentMapper, StockAttachment> implements StockAttachmentService {
 
+    @Autowired
+    private RocketMqService rocketMqService;
     /**
      * 添加
      * @param stockAttachmentVo
@@ -84,6 +85,8 @@ public class StockAttachmentServiceImpl extends ServiceImpl<StockAttachmentMappe
         if(StringUtil.isEmpty(busi)){
             throw new ServiceException("参数异常");
         }
+        rocketMqService.send("topic-ws","tag-ws","",busi, Collections.singletonList("1123598821738675202")
+                ,"你有一条消息",MessageNoticeEnum.MESSAGE_NOTICE_TYPE_1.getKey());
         return list(Wrappers.<StockAttachment>query().lambda().eq(StockAttachment::getBusiId,busi));
     }
 }

+ 10 - 0
hx-saas-project/saas-storage/src/main/resources/application-dev.yml

@@ -11,3 +11,13 @@ spring:
     url: ${blade.datasource.storage.dev.url}
     username: ${blade.datasource.storage.dev.username}
     password: ${blade.datasource.storage.dev.password}
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: my-group  # 指定发送者组名
+    send-message-timeout: 3000 #超时时间
+    compress-message-body-threshold: 4096 #消息压缩
+    max-message-size: 4194304 #消息体最大大小
+    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次。
+    retry-times-when-send-async-failed: 3 # 异步发送消息时,失败重试次数。默认为 2 次

+ 10 - 1
hx-saas-project/saas-storage/src/main/resources/application-prod.yml

@@ -9,4 +9,13 @@ spring:
     url: ${blade.datasource.storage.prod.url}
     username: ${blade.datasource.storage.prod.username}
     password: ${blade.datasource.storage.prod.password}
-
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: my-group  # 指定发送者组名
+    send-message-timeout: 3000 #超时时间
+    compress-message-body-threshold: 4096 #消息压缩
+    max-message-size: 4194304 #消息体最大大小
+    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次。
+    retry-times-when-send-async-failed: 3 # 异步发送消息时,失败重试次数。默认为 2 次

+ 10 - 0
hx-saas-project/saas-storage/src/main/resources/application-test.yml

@@ -9,3 +9,13 @@ spring:
     url: ${blade.datasource.storage.test.url}
     username: ${blade.datasource.storage.test.username}
     password: ${blade.datasource.storage.test.password}
+#rocketmq 配置
+rocketmq:
+  name-server: 114.116.8.29:9876
+  producer:
+    group: my-group  # 指定发送者组名
+    send-message-timeout: 3000 #超时时间
+    compress-message-body-threshold: 4096 #消息压缩
+    max-message-size: 4194304 #消息体最大大小
+    retry-times-when-send-failed: 3 # 同步发送消息时,失败重试次数。默认为 2 次。
+    retry-times-when-send-async-failed: 3 # 异步发送消息时,失败重试次数。默认为 2 次

+ 2 - 1
hx-service/storage/src/main/java/com/fjhx/supplier/service/impl/SupplierServiceImpl.java

@@ -121,8 +121,9 @@ public class SupplierServiceImpl extends ServiceImpl<SupplierMapper, Supplier> i
                 s.setBusiType(AttachmentTypeEnum.TYPE_TWO.getKey());
                 s.setCreatedTime(new Date());
             }
+            stockAttachmentService.saveBatch(attr);
         }
-        stockAttachmentService.saveBatch(attr);
+
         return supplier.getId();
     }