Selaa lähdekoodia

新增业务包(mq,ws,stream)

lianghanqiang 5 vuotta sitten
vanhempi
commit
943170b753
59 muutettua tiedostoa jossa 2010 lisäystä ja 45 poistoa
  1. 1 1
      blade-biz-common/src/main/java/org/springblade/common/constant/LauncherConstant.java
  2. 25 0
      blade-ops-api/blade-stream-api/pom.xml
  3. 34 0
      blade-ops-api/blade-stream-api/src/main/java/org/springblade/example/stream/api/model/StreamBody.java
  4. 55 0
      blade-ops-api/blade-stream-api/src/main/java/org/springblade/example/stream/api/process/StreamProcess.java
  5. 35 0
      blade-ops-api/pom.xml
  6. 3 0
      blade-ops/blade-mq-rabbit/README.md
  7. 38 0
      blade-ops/blade-mq-rabbit/pom.xml
  8. 35 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/RabbitApplication.java
  9. 162 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/config/RabbitMqConfiguration.java
  10. 58 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/constant/RabbitConstant.java
  11. 42 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/DelayQueueHandler.java
  12. 50 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/DirectQueueOneHandler.java
  13. 42 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/QueueThreeHandler.java
  14. 42 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/QueueTwoHandler.java
  15. 23 0
      blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/message/MessageStruct.java
  16. 15 0
      blade-ops/blade-mq-rabbit/src/main/resources/application.yml
  17. 84 0
      blade-ops/blade-mq-rabbit/src/test/java/org/springblade/example/mq/rabbit/RabbitTest.java
  18. 38 0
      blade-ops/blade-stream-consumer/pom.xml
  19. 35 0
      blade-ops/blade-stream-consumer/src/main/java/org/springblade/example/stream/consumer/StreamConsumerApplication.java
  20. 45 0
      blade-ops/blade-stream-consumer/src/main/java/org/springblade/example/stream/consumer/handler/StreamInputHandler.java
  21. 44 0
      blade-ops/blade-stream-consumer/src/main/resources/application-dev.yml
  22. 2 0
      blade-ops/blade-stream-consumer/src/main/resources/application.yml
  23. 39 0
      blade-ops/blade-stream-provider/pom.xml
  24. 35 0
      blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/StreamProviderApplication.java
  25. 45 0
      blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/controller/StreamMessageController.java
  26. 35 0
      blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/service/IMessageProvider.java
  27. 47 0
      blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/service/impl/MessageProviderImpl.java
  28. 44 0
      blade-ops/blade-stream-provider/src/main/resources/application-dev.yml
  29. 2 0
      blade-ops/blade-stream-provider/src/main/resources/application.yml
  30. 54 0
      blade-ops/blade-stream-provider/src/test/java/org/springblade/example/stream/StreamProviderTest.java
  31. 46 0
      blade-ops/blade-websocket/pom.xml
  32. 19 0
      blade-ops/blade-websocket/src/main/java/org/springblade/websocket/WebSocketApplication.java
  33. 36 0
      blade-ops/blade-websocket/src/main/java/org/springblade/websocket/config/WebSocketConfig.java
  34. 33 0
      blade-ops/blade-websocket/src/main/java/org/springblade/websocket/controller/ChatController.java
  35. 45 0
      blade-ops/blade-websocket/src/main/java/org/springblade/websocket/event/WebSocketEventListener.java
  36. 32 0
      blade-ops/blade-websocket/src/main/java/org/springblade/websocket/model/ChatMessage.java
  37. 11 0
      blade-ops/blade-websocket/src/main/resources/application.yml
  38. 8 0
      blade-ops/blade-websocket/src/main/resources/banner.txt
  39. 298 0
      blade-ops/blade-websocket/src/main/resources/static/css/main.css
  40. 53 0
      blade-ops/blade-websocket/src/main/resources/static/index.html
  41. 121 0
      blade-ops/blade-websocket/src/main/resources/static/js/main.js
  42. 1 0
      blade-ops/blade-websocket/src/main/resources/static/js/sockjs.min.js
  43. 7 0
      blade-ops/blade-websocket/src/main/resources/static/js/stomp.min.js
  44. 32 0
      blade-ops/pom.xml
  45. 1 0
      blade-service/community/src/main/java/org/springblade/community/controller/AgencyController.java
  46. 4 4
      blade-service/community/src/main/resources/application-test.yml
  47. 4 4
      blade-service/device/src/main/resources/application-prod.yml
  48. 10 4
      blade-service/device/src/main/resources/application-test.yml
  49. 4 4
      blade-service/enterprise/src/main/resources/application-test.yml
  50. 4 4
      blade-service/estate/src/main/resources/application-test.yml
  51. 3 0
      blade-service/grid/src/main/java/org/springblade/community/grid/service/impl/GridResourceServiceImpl.java
  52. 4 4
      blade-service/grid/src/main/resources/application-test.yml
  53. 4 4
      blade-service/person/src/main/resources/application-test.yml
  54. 6 3
      blade-service/smart-party/src/main/resources/application-dev.yml
  55. 4 4
      blade-service/smart-party/src/main/resources/application-test.yml
  56. 4 4
      blade-service/system-expand/src/main/resources/application-test.yml
  57. 1 1
      blade-service/work-order/src/main/java/org/springblade/workorder/publicevent/service/impl/PublicEventServiceImpl.java
  58. 4 4
      blade-service/work-order/src/main/resources/application-test.yml
  59. 2 0
      pom.xml

+ 1 - 1
blade-biz-common/src/main/java/org/springblade/common/constant/LauncherConstant.java

@@ -47,7 +47,7 @@ public interface LauncherConstant {
 	/**
 	 * nacos test 地址
 	 */
-	String NACOS_TEST_ADDR = "192.168.0.76:8848";
+	String NACOS_TEST_ADDR = "192.168.1.202:8848";
 	/**
 	 * sentinel dev 地址
 	 */

+ 25 - 0
blade-ops-api/blade-stream-api/pom.xml

@@ -0,0 +1,25 @@
+<?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>blade-ops-api</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.7.2.RELEASE</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-stream-api</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 34 - 0
blade-ops-api/blade-stream-api/src/main/java/org/springblade/example/stream/api/model/StreamBody.java

@@ -0,0 +1,34 @@
+/*
+ *      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.example.stream.api.model;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 传输消息体
+ *
+ * @author Chill
+ */
+@Data
+public class StreamBody implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	private String title;
+	private String message;
+}

+ 55 - 0
blade-ops-api/blade-stream-api/src/main/java/org/springblade/example/stream/api/process/StreamProcess.java

@@ -0,0 +1,55 @@
+/*
+ *      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.example.stream.api.process;
+
+import org.springframework.cloud.stream.annotation.Input;
+import org.springframework.cloud.stream.annotation.Output;
+import org.springframework.messaging.MessageChannel;
+import org.springframework.messaging.SubscribableChannel;
+
+/**
+ * 通道定义
+ *
+ * @author Chill
+ */
+public interface StreamProcess {
+	/**
+	 * 输出通道名称
+	 */
+	String OUTPUT = "stream-output";
+	/**
+	 * 输入通道名称
+	 */
+	String INPUT = "stream-input";
+
+	/**
+	 * 输出通道定义
+	 *
+	 * @return MessageChannel
+	 */
+	@Output(StreamProcess.OUTPUT)
+	MessageChannel output();
+
+	/**
+	 * 输入通道定义
+	 *
+	 * @return SubscribableChannel
+	 */
+	@Input(StreamProcess.INPUT)
+	SubscribableChannel input();
+
+}

+ 35 - 0
blade-ops-api/pom.xml

@@ -0,0 +1,35 @@
+<?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>BladeX-Biz</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.7.2.RELEASE</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-example-api</artifactId>
+    <name>${project.artifactId}</name>
+    <version>2.8.1.RELEASE</version>
+    <packaging>pom</packaging>
+    <description>BladeX 微服务范例API集合</description>
+
+    <modules>
+        <module>blade-stream-api</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                    <finalName>${project.name}</finalName>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 3 - 0
blade-ops/blade-mq-rabbit/README.md

@@ -0,0 +1,3 @@
+## 如何启动rabbitmq
+* docker启动,自带延迟插件:[https://hub.docker.com/r/bladex/rabbitmq](https://hub.docker.com/r/bladex/rabbitmq)
+* 安装包启动及延迟插件安装,请自行谷歌百度

+ 38 - 0
blade-ops/blade-mq-rabbit/pom.xml

@@ -0,0 +1,38 @@
+<?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>blade-ops</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.7.2.RELEASE</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-mq-rabbit</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-launch</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-tool</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 35 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/RabbitApplication.java

@@ -0,0 +1,35 @@
+/*
+ *      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.example.mq.rabbit;
+
+import org.springblade.common.constant.LauncherConstant;
+import org.springblade.core.launch.BladeApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * RabbitApplication
+ *
+ * @author Chill
+ */
+@SpringBootApplication
+public class RabbitApplication {
+
+	public static void main(String[] args) {
+		BladeApplication.run(LauncherConstant.APPLICATION_RABBIT_NAME, RabbitApplication.class, args);
+	}
+
+}

+ 162 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/config/RabbitMqConfiguration.java

@@ -0,0 +1,162 @@
+package org.springblade.example.mq.rabbit.config;
+
+import com.google.common.collect.Maps;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.example.mq.rabbit.constant.RabbitConstant;
+import org.springframework.amqp.core.*;
+import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.Map;
+
+/**
+ * RabbitMQ配置,主要是配置队列,如果提前存在该队列,可以省略本配置类
+ *
+ * @author yangkai.shen
+ */
+@Slf4j
+@Configuration
+public class RabbitMqConfiguration {
+
+	@Bean
+	public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory) {
+		connectionFactory.setPublisherConfirms(true);
+		connectionFactory.setPublisherReturns(true);
+		RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
+		rabbitTemplate.setMandatory(true);
+		rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> log.info("消息发送成功:correlationData({}),ack({}),cause({})", correlationData, ack, cause));
+		rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}", exchange, routingKey, replyCode, replyText, message));
+		return rabbitTemplate;
+	}
+
+	/**
+	 * 直接模式队列1
+	 */
+	@Bean
+	public Queue directOneQueue() {
+		return new Queue(RabbitConstant.DIRECT_MODE_QUEUE_ONE);
+	}
+
+	/**
+	 * 队列2
+	 */
+	@Bean
+	public Queue queueTwo() {
+		return new Queue(RabbitConstant.QUEUE_TWO);
+	}
+
+	/**
+	 * 队列3
+	 */
+	@Bean
+	public Queue queueThree() {
+		return new Queue(RabbitConstant.QUEUE_THREE);
+	}
+
+	/**
+	 * 分列模式队列
+	 */
+	@Bean
+	public FanoutExchange fanoutExchange() {
+		return new FanoutExchange(RabbitConstant.FANOUT_MODE_QUEUE);
+	}
+
+	/**
+	 * 分列模式绑定队列1
+	 *
+	 * @param directOneQueue 绑定队列1
+	 * @param fanoutExchange 分列模式交换器
+	 */
+	@Bean
+	public Binding fanoutBinding1(Queue directOneQueue, FanoutExchange fanoutExchange) {
+		return BindingBuilder.bind(directOneQueue).to(fanoutExchange);
+	}
+
+	/**
+	 * 分列模式绑定队列2
+	 *
+	 * @param queueTwo       绑定队列2
+	 * @param fanoutExchange 分列模式交换器
+	 */
+	@Bean
+	public Binding fanoutBinding2(Queue queueTwo, FanoutExchange fanoutExchange) {
+		return BindingBuilder.bind(queueTwo).to(fanoutExchange);
+	}
+
+	/**
+	 * 主题模式队列
+	 * <li>路由格式必须以 . 分隔,比如 user.email 或者 user.aaa.email</li>
+	 * <li>通配符 * ,代表一个占位符,或者说一个单词,比如路由为 user.*,那么 user.email 可以匹配,但是 user.aaa.email 就匹配不了</li>
+	 * <li>通配符 # ,代表一个或多个占位符,或者说一个或多个单词,比如路由为 user.#,那么 user.email 可以匹配,user.aaa.email 也可以匹配</li>
+	 */
+	@Bean
+	public TopicExchange topicExchange() {
+		return new TopicExchange(RabbitConstant.TOPIC_MODE_QUEUE);
+	}
+
+
+	/**
+	 * 主题模式绑定分列模式
+	 *
+	 * @param fanoutExchange 分列模式交换器
+	 * @param topicExchange  主题模式交换器
+	 */
+	@Bean
+	public Binding topicBinding1(FanoutExchange fanoutExchange, TopicExchange topicExchange) {
+		return BindingBuilder.bind(fanoutExchange).to(topicExchange).with(RabbitConstant.TOPIC_ROUTING_KEY_ONE);
+	}
+
+	/**
+	 * 主题模式绑定队列2
+	 *
+	 * @param queueTwo      队列2
+	 * @param topicExchange 主题模式交换器
+	 */
+	@Bean
+	public Binding topicBinding2(Queue queueTwo, TopicExchange topicExchange) {
+		return BindingBuilder.bind(queueTwo).to(topicExchange).with(RabbitConstant.TOPIC_ROUTING_KEY_TWO);
+	}
+
+	/**
+	 * 主题模式绑定队列3
+	 *
+	 * @param queueThree    队列3
+	 * @param topicExchange 主题模式交换器
+	 */
+	@Bean
+	public Binding topicBinding3(Queue queueThree, TopicExchange topicExchange) {
+		return BindingBuilder.bind(queueThree).to(topicExchange).with(RabbitConstant.TOPIC_ROUTING_KEY_THREE);
+	}
+
+	/**
+	 * 延迟队列
+	 */
+	@Bean
+	public Queue delayQueue() {
+		return new Queue(RabbitConstant.DELAY_QUEUE, true);
+	}
+
+	/**
+	 * 延迟队列交换器, x-delayed-type 和 x-delayed-message 固定
+	 */
+	@Bean
+	public CustomExchange delayExchange() {
+		Map<String, Object> args = Maps.newHashMap();
+		args.put("x-delayed-type", "direct");
+		return new CustomExchange(RabbitConstant.DELAY_MODE_QUEUE, "x-delayed-message", true, false, args);
+	}
+
+	/**
+	 * 延迟队列绑定自定义交换器
+	 *
+	 * @param delayQueue    队列
+	 * @param delayExchange 延迟交换器
+	 */
+	@Bean
+	public Binding delayBinding(Queue delayQueue, CustomExchange delayExchange) {
+		return BindingBuilder.bind(delayQueue).to(delayExchange).with(RabbitConstant.DELAY_QUEUE).noargs();
+	}
+
+}

+ 58 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/constant/RabbitConstant.java

@@ -0,0 +1,58 @@
+package org.springblade.example.mq.rabbit.constant;
+
+/**
+ * RabbitMQ常量池
+ *
+ * @author yangkai.shen
+ */
+public interface RabbitConstant {
+	/**
+	 * 直接模式1
+	 */
+	String DIRECT_MODE_QUEUE_ONE = "queue.direct.1";
+
+	/**
+	 * 队列2
+	 */
+	String QUEUE_TWO = "queue.2";
+
+	/**
+	 * 队列3
+	 */
+	String QUEUE_THREE = "3.queue";
+
+	/**
+	 * 分列模式
+	 */
+	String FANOUT_MODE_QUEUE = "fanout.mode";
+
+	/**
+	 * 主题模式
+	 */
+	String TOPIC_MODE_QUEUE = "topic.mode";
+
+	/**
+	 * 路由1
+	 */
+	String TOPIC_ROUTING_KEY_ONE = "queue.#";
+
+	/**
+	 * 路由2
+	 */
+	String TOPIC_ROUTING_KEY_TWO = "*.queue";
+
+	/**
+	 * 路由3
+	 */
+	String TOPIC_ROUTING_KEY_THREE = "3.queue";
+
+	/**
+	 * 延迟队列
+	 */
+	String DELAY_QUEUE = "delay.queue";
+
+	/**
+	 * 延迟队列交换器
+	 */
+	String DELAY_MODE_QUEUE = "delay.mode";
+}

+ 42 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/DelayQueueHandler.java

@@ -0,0 +1,42 @@
+package org.springblade.example.mq.rabbit.handler;
+
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.jackson.JsonUtil;
+import org.springblade.example.mq.rabbit.constant.RabbitConstant;
+import org.springblade.example.mq.rabbit.message.MessageStruct;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * 延迟队列处理器
+ *
+ * @author yangkai.shen
+ */
+@Slf4j
+@Component
+@RabbitListener(queues = RabbitConstant.DELAY_QUEUE)
+public class DelayQueueHandler {
+
+	@RabbitHandler
+	public void directHandlerManualAck(MessageStruct messageStruct, Message message, Channel channel) {
+		//  如果手动ACK,消息会被监听消费,但是消息在队列中依旧存在,如果 未配置 acknowledge-mode 默认是会在消费完毕后自动ACK掉
+		final long deliveryTag = message.getMessageProperties().getDeliveryTag();
+		try {
+			log.info("延迟队列,手动ACK,接收消息:{}", JsonUtil.toJson(messageStruct));
+			// 通知 MQ 消息已被成功消费,可以ACK了
+			channel.basicAck(deliveryTag, false);
+		} catch (IOException e) {
+			try {
+				// 处理失败,重新压入MQ
+				channel.basicRecover();
+			} catch (IOException e1) {
+				e1.printStackTrace();
+			}
+		}
+	}
+}

+ 50 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/DirectQueueOneHandler.java

@@ -0,0 +1,50 @@
+package org.springblade.example.mq.rabbit.handler;
+
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.jackson.JsonUtil;
+import org.springblade.example.mq.rabbit.constant.RabbitConstant;
+import org.springblade.example.mq.rabbit.message.MessageStruct;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * 直接队列1 处理器
+ *
+ * @author yangkai.shen
+ */
+@Slf4j
+@RabbitListener(queues = RabbitConstant.DIRECT_MODE_QUEUE_ONE)
+@Component
+public class DirectQueueOneHandler {
+
+	/**
+	 * 如果 spring.rabbitmq.listener.direct.acknowledge-mode: auto,则可以用这个方式,会自动ack
+	 */
+	// @RabbitHandler
+	public void directHandlerAutoAck(MessageStruct message) {
+		log.info("直接队列处理器,接收消息:{}", JsonUtil.toJson(message));
+	}
+
+	@RabbitHandler
+	public void directHandlerManualAck(MessageStruct messageStruct, Message message, Channel channel) {
+		//  如果手动ACK,消息会被监听消费,但是消息在队列中依旧存在,如果 未配置 acknowledge-mode 默认是会在消费完毕后自动ACK掉
+		final long deliveryTag = message.getMessageProperties().getDeliveryTag();
+		try {
+			log.info("直接队列1,手动ACK,接收消息:{}", JsonUtil.toJson(messageStruct));
+			// 通知 MQ 消息已被成功消费,可以ACK了
+			channel.basicAck(deliveryTag, false);
+		} catch (IOException e) {
+			try {
+				// 处理失败,重新压入MQ
+				channel.basicRecover();
+			} catch (IOException e1) {
+				e1.printStackTrace();
+			}
+		}
+	}
+}

+ 42 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/QueueThreeHandler.java

@@ -0,0 +1,42 @@
+package org.springblade.example.mq.rabbit.handler;
+
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.jackson.JsonUtil;
+import org.springblade.example.mq.rabbit.constant.RabbitConstant;
+import org.springblade.example.mq.rabbit.message.MessageStruct;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * 队列2 处理器
+ *
+ * @author yangkai.shen
+ */
+@Slf4j
+@RabbitListener(queues = RabbitConstant.QUEUE_THREE)
+@Component
+public class QueueThreeHandler {
+
+	@RabbitHandler
+	public void directHandlerManualAck(MessageStruct messageStruct, Message message, Channel channel) {
+		//  如果手动ACK,消息会被监听消费,但是消息在队列中依旧存在,如果 未配置 acknowledge-mode 默认是会在消费完毕后自动ACK掉
+		final long deliveryTag = message.getMessageProperties().getDeliveryTag();
+		try {
+			log.info("队列3,手动ACK,接收消息:{}", JsonUtil.toJson(messageStruct));
+			// 通知 MQ 消息已被成功消费,可以ACK了
+			channel.basicAck(deliveryTag, false);
+		} catch (IOException e) {
+			try {
+				// 处理失败,重新压入MQ
+				channel.basicRecover();
+			} catch (IOException e1) {
+				e1.printStackTrace();
+			}
+		}
+	}
+}

+ 42 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/handler/QueueTwoHandler.java

@@ -0,0 +1,42 @@
+package org.springblade.example.mq.rabbit.handler;
+
+import com.rabbitmq.client.Channel;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.jackson.JsonUtil;
+import org.springblade.example.mq.rabbit.constant.RabbitConstant;
+import org.springblade.example.mq.rabbit.message.MessageStruct;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * 队列2 处理器
+ *
+ * @author yangkai.shen
+ */
+@Slf4j
+@RabbitListener(queues = RabbitConstant.QUEUE_TWO)
+@Component
+public class QueueTwoHandler {
+
+	@RabbitHandler
+	public void directHandlerManualAck(MessageStruct messageStruct, Message message, Channel channel) {
+		//  如果手动ACK,消息会被监听消费,但是消息在队列中依旧存在,如果 未配置 acknowledge-mode 默认是会在消费完毕后自动ACK掉
+		final long deliveryTag = message.getMessageProperties().getDeliveryTag();
+		try {
+			log.info("队列2,手动ACK,接收消息:{}", JsonUtil.toJson(messageStruct));
+			// 通知 MQ 消息已被成功消费,可以ACK了
+			channel.basicAck(deliveryTag, false);
+		} catch (IOException e) {
+			try {
+				// 处理失败,重新压入MQ
+				channel.basicRecover();
+			} catch (IOException e1) {
+				e1.printStackTrace();
+			}
+		}
+	}
+}

+ 23 - 0
blade-ops/blade-mq-rabbit/src/main/java/org/springblade/example/mq/rabbit/message/MessageStruct.java

@@ -0,0 +1,23 @@
+package org.springblade.example.mq.rabbit.message;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * 测试消息体
+ *
+ * @author yangkai.shen
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MessageStruct implements Serializable {
+	private static final long serialVersionUID = 392365881428311040L;
+
+	private String message;
+}

+ 15 - 0
blade-ops/blade-mq-rabbit/src/main/resources/application.yml

@@ -0,0 +1,15 @@
+server:
+  port: 8602
+spring:
+  rabbitmq:
+    host: localhost
+    port: 5672
+    username: guest
+    password: guest
+    virtual-host: /
+    # 手动提交消息
+    listener:
+      simple:
+        acknowledge-mode: manual
+      direct:
+        acknowledge-mode: manual

+ 84 - 0
blade-ops/blade-mq-rabbit/src/test/java/org/springblade/example/mq/rabbit/RabbitTest.java

@@ -0,0 +1,84 @@
+package org.springblade.example.mq.rabbit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springblade.core.test.BladeBootTest;
+import org.springblade.core.test.BladeSpringRunner;
+import org.springblade.core.tool.utils.DateUtil;
+import org.springblade.example.mq.rabbit.constant.RabbitConstant;
+import org.springblade.example.mq.rabbit.message.MessageStruct;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@RunWith(BladeSpringRunner.class)
+@SpringBootTest(classes = RabbitApplication.class)
+@BladeBootTest(appName = "blade-rabbit", profile = "test", enableLoader = true)
+public class RabbitTest {
+	@Autowired
+	private RabbitTemplate rabbitTemplate;
+
+	/**
+	 * 测试直接模式发送
+	 */
+	@Test
+	public void sendDirect() {
+		rabbitTemplate.convertAndSend(RabbitConstant.DIRECT_MODE_QUEUE_ONE, new MessageStruct("direct message"));
+	}
+
+	/**
+	 * 测试分列模式发送
+	 */
+	@Test
+	public void sendFanout() {
+		rabbitTemplate.convertAndSend(RabbitConstant.FANOUT_MODE_QUEUE, "", new MessageStruct("fanout message"));
+	}
+
+	/**
+	 * 测试主题模式发送1
+	 */
+	@Test
+	public void sendTopic1() {
+		rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_MODE_QUEUE, "queue.aaa.bbb", new MessageStruct("topic message"));
+	}
+
+	/**
+	 * 测试主题模式发送2
+	 */
+	@Test
+	public void sendTopic2() {
+		rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_MODE_QUEUE, "ccc.queue", new MessageStruct("topic message"));
+	}
+
+	/**
+	 * 测试主题模式发送3
+	 */
+	@Test
+	public void sendTopic3() {
+		rabbitTemplate.convertAndSend(RabbitConstant.TOPIC_MODE_QUEUE, "3.queue", new MessageStruct("topic message"));
+	}
+
+	/**
+	 * 测试延迟队列发送
+	 */
+	@Test
+	public void sendDelay() {
+		rabbitTemplate.convertAndSend(RabbitConstant.DELAY_MODE_QUEUE, RabbitConstant.DELAY_QUEUE,
+			new MessageStruct("delay message, delay 5s, " + DateUtil.now()), message -> {
+				message.getMessageProperties().setHeader("x-delay", 5000);
+				return message;
+			});
+		rabbitTemplate.convertAndSend(RabbitConstant.DELAY_MODE_QUEUE, RabbitConstant.DELAY_QUEUE,
+			new MessageStruct("delay message,  delay 2s, " + DateUtil.now()), message -> {
+				message.getMessageProperties().setHeader("x-delay", 2000);
+				return message;
+			});
+		rabbitTemplate.convertAndSend(RabbitConstant.DELAY_MODE_QUEUE, RabbitConstant.DELAY_QUEUE,
+			new MessageStruct("delay message,  delay 8s, " + DateUtil.now()), message -> {
+				message.getMessageProperties().setHeader("x-delay", 8000);
+				return message;
+			});
+	}
+
+}
+

+ 38 - 0
blade-ops/blade-stream-consumer/pom.xml

@@ -0,0 +1,38 @@
+<?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>blade-ops</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.7.2.RELEASE</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-stream-consumer</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-boot</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-stream-api</artifactId>
+            <version>${bladex.project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 35 - 0
blade-ops/blade-stream-consumer/src/main/java/org/springblade/example/stream/consumer/StreamConsumerApplication.java

@@ -0,0 +1,35 @@
+/*
+ *      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.example.stream.consumer;
+
+import org.springblade.common.constant.LauncherConstant;
+import org.springblade.core.launch.BladeApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * StreamApplication
+ *
+ * @author Chill
+ */
+@SpringBootApplication
+public class StreamConsumerApplication {
+
+	public static void main(String[] args) {
+		BladeApplication.run(LauncherConstant.APPLICATION_STREAM_CONSUMER_NAME, StreamConsumerApplication.class, args);
+	}
+
+}

+ 45 - 0
blade-ops/blade-stream-consumer/src/main/java/org/springblade/example/stream/consumer/handler/StreamInputHandler.java

@@ -0,0 +1,45 @@
+/*
+ *      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.example.stream.consumer.handler;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.jackson.JsonUtil;
+import org.springblade.example.stream.api.model.StreamBody;
+import org.springblade.example.stream.api.process.StreamProcess;
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.cloud.stream.annotation.StreamListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * StreamChannelHandler
+ *
+ * @author Chill
+ */
+@Slf4j
+@Component
+@EnableBinding(StreamProcess.class)
+public class StreamInputHandler {
+
+	/**
+	 * 对消息的监听处理
+	 */
+	@StreamListener(StreamProcess.INPUT)
+	private void receiver(StreamBody body) {
+		log.info("hello : " + JsonUtil.toJson(body));
+	}
+
+}

+ 44 - 0
blade-ops/blade-stream-consumer/src/main/resources/application-dev.yml

@@ -0,0 +1,44 @@
+spring:
+  cloud:
+    stream:
+      # 进行rabbit的相关绑定配置
+      rabbit:
+        bindings:
+          stream-input:
+            # 进行消费端配置
+            consumer:
+              # 设置一个RoutingKey信息
+              bindingRoutingKey: stream-key
+      # 在此处配置要绑定的rabbitmq的服务信息;
+      binders:
+        # 表示定义的名称,用于于binding整合
+        default-rabbit:
+          # 消息组件类型
+          type: rabbit
+          # 设置rabbitmq的相关的环境配置
+          environment:
+            spring:
+              rabbitmq:
+                host: 127.0.0.1
+                port: 5672
+                username: guest
+                password: guest
+                virtual-host: /
+      # 服务的整合处理
+      bindings:
+        # 设定通道的名称
+        stream-input:
+          # 设定Exchange名称定义
+          destination: queue.stream.messages
+          # 设定消息类型,对象类型,如果是文本则设置"text/plain"
+          content-type: application/json
+          # 设置要绑定的消息服务的定义名称
+          binder: default-rabbit
+          # 进行操作的分组,表示持久化
+          group: stream-group
+  #数据源配置
+  datasource:
+    url: ${blade.datasource.dev.url}
+    username: ${blade.datasource.dev.username}
+    password: ${blade.datasource.dev.password}
+

+ 2 - 0
blade-ops/blade-stream-consumer/src/main/resources/application.yml

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

+ 39 - 0
blade-ops/blade-stream-provider/pom.xml

@@ -0,0 +1,39 @@
+<?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>blade-ops</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.7.2.RELEASE</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-stream-provider</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-boot</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-stream-api</artifactId>
+            <version>${bladex.project.version}</version>
+        </dependency>
+    </dependencies>
+
+
+</project>

+ 35 - 0
blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/StreamProviderApplication.java

@@ -0,0 +1,35 @@
+/*
+ *      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.example.stream.provider;
+
+import org.springblade.common.constant.LauncherConstant;
+import org.springblade.core.launch.BladeApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * StreamApplication
+ *
+ * @author Chill
+ */
+@SpringBootApplication
+public class StreamProviderApplication {
+
+	public static void main(String[] args) {
+		BladeApplication.run(LauncherConstant.APPLICATION_STREAM_PROVIDER_NAME, StreamProviderApplication.class, args);
+	}
+
+}

+ 45 - 0
blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/controller/StreamMessageController.java

@@ -0,0 +1,45 @@
+/*
+ *      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.example.stream.provider.controller;
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.tool.api.R;
+import org.springblade.example.stream.api.model.StreamBody;
+import org.springblade.example.stream.provider.service.IMessageProvider;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * StreamProviderController
+ *
+ * @author Chill
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("message")
+public class StreamMessageController {
+
+	private final IMessageProvider messageProvider;
+
+	@PostMapping("send")
+	public R send(StreamBody body) {
+		messageProvider.send(body);
+		return R.success("消息发送成功");
+	}
+
+}

+ 35 - 0
blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/service/IMessageProvider.java

@@ -0,0 +1,35 @@
+/*
+ *      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.example.stream.provider.service;
+
+import org.springblade.example.stream.api.model.StreamBody;
+
+/**
+ * IMessageProvider
+ *
+ * @author Chill
+ */
+public interface IMessageProvider {
+
+	/**
+	 * 消息发送
+	 *
+	 * @param body 消息体
+	 */
+	void send(StreamBody body);
+
+}

+ 47 - 0
blade-ops/blade-stream-provider/src/main/java/org/springblade/example/stream/provider/service/impl/MessageProviderImpl.java

@@ -0,0 +1,47 @@
+/*
+ *      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.example.stream.provider.service.impl;
+
+import lombok.AllArgsConstructor;
+import org.springblade.example.stream.api.model.StreamBody;
+import org.springblade.example.stream.api.process.StreamProcess;
+import org.springblade.example.stream.provider.service.IMessageProvider;
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.integration.support.MessageBuilder;
+import org.springframework.stereotype.Component;
+
+/**
+ * MessageProviderImpl
+ *
+ * @author Chill
+ */
+@Component
+@AllArgsConstructor
+@EnableBinding(StreamProcess.class)
+public class MessageProviderImpl implements IMessageProvider {
+
+	/**
+	 * 消息的发送管道
+	 */
+	private final StreamProcess process;
+
+	@Override
+	public void send(StreamBody body) {
+		process.output().send(MessageBuilder.withPayload(body).build());
+	}
+
+}

+ 44 - 0
blade-ops/blade-stream-provider/src/main/resources/application-dev.yml

@@ -0,0 +1,44 @@
+spring:
+  cloud:
+    stream:
+      # 进行rabbit的相关绑定配置
+      rabbit:
+        bindings:
+          stream-output:
+            # 进行生产端端配置
+            producer:
+              #定义 RoutingKey 的表达式配置
+              routing-key-expression: '''stream-key'''
+      # 在此处配置要绑定的rabbitmq的服务信息;
+      binders:
+        # 表示定义的名称,用于于binding整合
+        default-rabbit:
+          # 消息组件类型
+          type: rabbit
+          # 设置rabbitmq的相关的环境配置
+          environment:
+            spring:
+              rabbitmq:
+                host: 127.0.0.1
+                port: 5672
+                username: guest
+                password: guest
+                virtual-host: /
+      # 服务的整合处理
+      bindings:
+        # 设定通道的名称
+        stream-output:
+          # 设定Exchange名称定义
+          destination: queue.stream.messages
+          # 设定消息类型,对象类型,如果是文本则设置"text/plain"
+          content-type: application/json
+          # 设置要绑定的消息服务的定义名称
+          binder: default-rabbit
+          # 进行操作的分组,表示持久化
+          group: stream-group
+  #数据源配置
+  datasource:
+    url: ${blade.datasource.dev.url}
+    username: ${blade.datasource.dev.username}
+    password: ${blade.datasource.dev.password}
+

+ 2 - 0
blade-ops/blade-stream-provider/src/main/resources/application.yml

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

+ 54 - 0
blade-ops/blade-stream-provider/src/test/java/org/springblade/example/stream/StreamProviderTest.java

@@ -0,0 +1,54 @@
+/*
+ *      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.example.stream;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springblade.core.test.BladeBootTest;
+import org.springblade.core.test.BladeSpringRunner;
+import org.springblade.example.stream.api.model.StreamBody;
+import org.springblade.example.stream.provider.StreamProviderApplication;
+import org.springblade.example.stream.provider.service.IMessageProvider;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+
+/**
+ * StreamProviderTest
+ *
+ * @author Chill
+ */
+@RunWith(BladeSpringRunner.class)
+@SpringBootTest(classes = StreamProviderApplication.class)
+@BladeBootTest(appName = "blade-rabbit", profile = "test", enableLoader = true)
+public class StreamProviderTest {
+
+	@Resource
+	private IMessageProvider messageProvider;
+
+	/**
+	 * 测试通道模式发送
+	 */
+	@Test
+	public void sendChannel() {
+		StreamBody sb = new StreamBody();
+		sb.setTitle("this is title");
+		sb.setMessage("this is message");
+		messageProvider.send(sb);
+	}
+
+}

+ 46 - 0
blade-ops/blade-websocket/pom.xml

@@ -0,0 +1,46 @@
+<?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>blade-ops</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.7.2.RELEASE</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-websocket</artifactId>
+    <name>${project.artifactId}</name>
+    <version>${bladex.project.version}</version>
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-launch</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-amqp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-reactor-netty</artifactId>
+        </dependency>
+    </dependencies>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 19 - 0
blade-ops/blade-websocket/src/main/java/org/springblade/websocket/WebSocketApplication.java

@@ -0,0 +1,19 @@
+package org.springblade.websocket;
+
+import org.springblade.core.launch.BladeApplication;
+import org.springblade.core.launch.constant.AppConstant;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * WebSocketApplication
+ *
+ * @author Chill
+ */
+@SpringBootApplication
+public class WebSocketApplication {
+
+	public static void main(String[] args) {
+		BladeApplication.run(AppConstant.APPLICATION_WEBSOCKET_NAME, WebSocketApplication.class, args);
+	}
+
+}

+ 36 - 0
blade-ops/blade-websocket/src/main/java/org/springblade/websocket/config/WebSocketConfig.java

@@ -0,0 +1,36 @@
+package org.springblade.websocket.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.messaging.simp.config.MessageBrokerRegistry;
+import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
+import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
+
+/**
+ * WebSocketConfig
+ *
+ * @author rajeevkumarsingh
+ */
+@Configuration
+@EnableWebSocketMessageBroker
+public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
+
+	@Override
+	public void registerStompEndpoints(StompEndpointRegistry registry) {
+		registry.addEndpoint("/ws").withSockJS();
+	}
+
+	@Override
+	public void configureMessageBroker(MessageBrokerRegistry registry) {
+		registry.setApplicationDestinationPrefixes("/app");
+		// Enables a simple in-memory broker
+		registry.enableSimpleBroker("/topic");
+
+		// Use this for enabling a Full featured broker like RabbitMQ
+		/*registry.enableStompBrokerRelay("/topic")
+			.setRelayHost("localhost")
+			.setRelayPort(61613)
+			.setClientLogin("guest")
+			.setClientPasscode("guest");*/
+	}
+}

+ 33 - 0
blade-ops/blade-websocket/src/main/java/org/springblade/websocket/controller/ChatController.java

@@ -0,0 +1,33 @@
+package org.springblade.websocket.controller;
+
+import org.springblade.websocket.model.ChatMessage;
+import org.springframework.messaging.handler.annotation.MessageMapping;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.messaging.handler.annotation.SendTo;
+import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
+import org.springframework.stereotype.Controller;
+
+/**
+ * ChatController
+ *
+ * @author rajeevkumarsingh
+ */
+@Controller
+public class ChatController {
+
+	@MessageMapping("/chat.sendMessage")
+	@SendTo("/topic/public")
+	public ChatMessage sendMessage(@Payload ChatMessage chatMessage) {
+		return chatMessage;
+	}
+
+	@MessageMapping("/chat.addUser")
+	@SendTo("/topic/public")
+	public ChatMessage addUser(@Payload ChatMessage chatMessage,
+							   SimpMessageHeaderAccessor headerAccessor) {
+		// Add username in web socket session
+		headerAccessor.getSessionAttributes().put("username", chatMessage.getSender());
+		return chatMessage;
+	}
+
+}

+ 45 - 0
blade-ops/blade-websocket/src/main/java/org/springblade/websocket/event/WebSocketEventListener.java

@@ -0,0 +1,45 @@
+package org.springblade.websocket.event;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.websocket.model.ChatMessage;
+import org.springframework.context.event.EventListener;
+import org.springframework.messaging.simp.SimpMessageSendingOperations;
+import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.messaging.SessionConnectedEvent;
+import org.springframework.web.socket.messaging.SessionDisconnectEvent;
+
+/**
+ * WebSocketEventListener
+ *
+ * @author rajeevkumarsingh
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class WebSocketEventListener {
+
+	private final SimpMessageSendingOperations messagingTemplate;
+
+	@EventListener
+	public void handleWebSocketConnectListener(SessionConnectedEvent event) {
+		log.info("Received a new web socket connection");
+	}
+
+	@EventListener
+	public void handleWebSocketDisconnectListener(SessionDisconnectEvent event) {
+		StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(event.getMessage());
+
+		String username = (String) headerAccessor.getSessionAttributes().get("username");
+		if (username != null) {
+			log.info("User Disconnected : " + username);
+
+			ChatMessage chatMessage = new ChatMessage();
+			chatMessage.setType(ChatMessage.MessageType.LEAVE);
+			chatMessage.setSender(username);
+
+			messagingTemplate.convertAndSend("/topic/public", chatMessage);
+		}
+	}
+}

+ 32 - 0
blade-ops/blade-websocket/src/main/java/org/springblade/websocket/model/ChatMessage.java

@@ -0,0 +1,32 @@
+package org.springblade.websocket.model;
+
+import lombok.Data;
+
+/**
+ * ChatMessage
+ *
+ * @author rajeevkumarsingh
+ */
+@Data
+public class ChatMessage {
+
+	public enum MessageType {
+		/**
+		 * 聊天
+		 */
+		CHAT,
+		/**
+		 * 加入
+		 */
+		JOIN,
+		/**
+		 * 离开
+		 */
+		LEAVE
+	}
+
+	private MessageType type;
+	private String content;
+	private String sender;
+
+}

+ 11 - 0
blade-ops/blade-websocket/src/main/resources/application.yml

@@ -0,0 +1,11 @@
+server:
+  port: 7006
+  undertow:
+    # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
+    io-threads: 4
+    # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
+    worker-threads: 20
+    # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
+    buffer-size: 1024
+    # 是否分配的直接内存
+    direct-buffers: true

+ 8 - 0
blade-ops/blade-websocket/src/main/resources/banner.txt

@@ -0,0 +1,8 @@
+${AnsiColor.BLUE}            ______  _             _       ___   ___
+${AnsiColor.BLUE}            | ___ \| |           | |      \  \ /  /
+${AnsiColor.BLUE}            | |_/ /| |  __ _   __| |  ___  \  V  /
+${AnsiColor.BLUE}            | ___ \| | / _` | / _` | / _ \   > <
+${AnsiColor.BLUE}            | |_/ /| || (_| || (_| ||  __/ /  .  \
+${AnsiColor.BLUE}            \____/ |_| \__,_| \__,_| \___|/__/ \__\
+
+${AnsiColor.BLUE}:: BladeX :: ${spring.application.name}:${AnsiColor.RED}${blade.env}${AnsiColor.BLUE} :: Running SpringBoot ${spring-boot.version} :: ${AnsiColor.BRIGHT_BLACK}

+ 298 - 0
blade-ops/blade-websocket/src/main/resources/static/css/main.css

@@ -0,0 +1,298 @@
+* {
+    -webkit-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    box-sizing: border-box;
+}
+
+html,body {
+    height: 100%;
+    overflow: hidden;
+}
+
+body {
+    margin: 0;
+    padding: 0;
+    font-weight: 400;
+    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+    font-size: 1rem;
+    line-height: 1.58;
+    color: #333;
+    background-color: #f4f4f4;
+    height: 100%;
+}
+
+body:before {
+    height: 50%;
+    width: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    background: #128ff2;
+    content: "";
+    z-index: 0;
+}
+
+.clearfix:after {
+    display: block;
+    content: "";
+    clear: both;
+}
+
+.hidden {
+    display: none;
+}
+
+.form-control {
+    width: 100%;
+    min-height: 38px;
+    font-size: 15px;
+    border: 1px solid #c8c8c8;
+}
+
+.form-group {
+    margin-bottom: 15px;
+}
+
+input {
+    padding-left: 10px;
+    outline: none;
+}
+
+h1, h2, h3, h4, h5, h6 {
+    margin-top: 20px;
+    margin-bottom: 20px;
+}
+
+h1 {
+    font-size: 1.7em;
+}
+
+a {
+    color: #128ff2;
+}
+
+button {
+    box-shadow: none;
+    border: 1px solid transparent;
+    font-size: 14px;
+    outline: none;
+    line-height: 100%;
+    white-space: nowrap;
+    vertical-align: middle;
+    padding: 0.6rem 1rem;
+    border-radius: 2px;
+    transition: all 0.2s ease-in-out;
+    cursor: pointer;
+    min-height: 38px;
+}
+
+button.default {
+    background-color: #e8e8e8;
+    color: #333;
+    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.12);
+}
+
+button.primary {
+    background-color: #128ff2;
+    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.12);
+    color: #fff;
+}
+
+button.accent {
+    background-color: #ff4743;
+    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.12);
+    color: #fff;
+}
+
+#username-page {
+    text-align: center;
+}
+
+.username-page-container {
+    background: #fff;
+    box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27);
+    border-radius: 2px;
+    width: 100%;
+    max-width: 500px;
+    display: inline-block;
+    margin-top: 42px;
+    vertical-align: middle;
+    position: relative;
+    padding: 35px 55px 35px;
+    min-height: 250px;
+    position: absolute;
+    top: 50%;
+    left: 0;
+    right: 0;
+    margin: 0 auto;
+    margin-top: -160px;
+}
+
+.username-page-container .username-submit {
+    margin-top: 10px;
+}
+
+
+#chat-page {
+    position: relative;
+    height: 100%;
+}
+
+.chat-container {
+    max-width: 700px;
+    margin-left: auto;
+    margin-right: auto;
+    background-color: #fff;
+    box-shadow: 0 1px 11px rgba(0, 0, 0, 0.27);
+    margin-top: 30px;
+    height: calc(100% - 60px);
+    max-height: 600px;
+    position: relative;
+}
+
+#chat-page ul {
+    list-style-type: none;
+    background-color: #FFF;
+    margin: 0;
+    overflow: auto;
+    overflow-y: scroll;
+    padding: 0 20px 0px 20px;
+    height: calc(100% - 150px);
+}
+
+#chat-page #messageForm {
+    padding: 20px;
+}
+
+#chat-page ul li {
+    line-height: 1.5rem;
+    padding: 10px 20px;
+    margin: 0;
+    border-bottom: 1px solid #f4f4f4;
+}
+
+#chat-page ul li p {
+    margin: 0;
+}
+
+#chat-page .event-message {
+    width: 100%;
+    text-align: center;
+    clear: both;
+}
+
+#chat-page .event-message p {
+    color: #777;
+    font-size: 14px;
+    word-wrap: break-word;
+}
+
+#chat-page .chat-message {
+    padding-left: 68px;
+    position: relative;
+}
+
+#chat-page .chat-message i {
+    position: absolute;
+    width: 42px;
+    height: 42px;
+    overflow: hidden;
+    left: 10px;
+    display: inline-block;
+    vertical-align: middle;
+    font-size: 18px;
+    line-height: 42px;
+    color: #fff;
+    text-align: center;
+    border-radius: 50%;
+    font-style: normal;
+    text-transform: uppercase;
+}
+
+#chat-page .chat-message span {
+    color: #333;
+    font-weight: 600;
+}
+
+#chat-page .chat-message p {
+    color: #43464b;
+}
+
+#messageForm .input-group input {
+    float: left;
+    width: calc(100% - 85px);
+}
+
+#messageForm .input-group button {
+    float: left;
+    width: 80px;
+    height: 38px;
+    margin-left: 5px;
+}
+
+.chat-header {
+    text-align: center;
+    padding: 15px;
+    border-bottom: 1px solid #ececec;
+}
+
+.chat-header h2 {
+    margin: 0;
+    font-weight: 500;
+}
+
+.connecting {
+    padding-top: 5px;
+    text-align: center;
+    color: #777;
+    position: absolute;
+    top: 65px;
+    width: 100%;
+}
+
+
+@media screen and (max-width: 730px) {
+
+    .chat-container {
+        margin-left: 10px;
+        margin-right: 10px;
+        margin-top: 10px;
+    }
+}
+
+@media screen and (max-width: 480px) {
+    .chat-container {
+        height: calc(100% - 30px);
+    }
+
+    .username-page-container {
+        width: auto;
+        margin-left: 15px;
+        margin-right: 15px;
+        padding: 25px;
+    }
+
+    #chat-page ul {
+        height: calc(100% - 120px);
+    }
+
+    #messageForm .input-group button {
+        width: 65px;
+    }
+
+    #messageForm .input-group input {
+        width: calc(100% - 70px);
+    }
+
+    .chat-header {
+        padding: 10px;
+    }
+
+    .connecting {
+        top: 60px;
+    }
+
+    .chat-header h2 {
+        font-size: 1.1em;
+    }
+}

+ 53 - 0
blade-ops/blade-websocket/src/main/resources/static/index.html

@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+  <head>
+      <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
+      <title>Spring Boot WebSocket Chat Application | CalliCoder</title>
+      <link rel="stylesheet" href="/css/main.css" />
+  </head>
+  <body>
+    <noscript>
+      <h2>Sorry! Your browser doesn't support Javascript</h2>
+    </noscript>
+
+    <div id="username-page">
+        <div class="username-page-container">
+            <h1 class="title">Type your username</h1>
+            <form id="usernameForm" name="usernameForm">
+                <div class="form-group">
+                    <input type="text" id="name" placeholder="Username" autocomplete="off" class="form-control" />
+                </div>
+                <div class="form-group">
+                    <button type="submit" class="accent username-submit">Start Chatting</button>
+                </div>
+            </form>
+        </div>
+    </div>
+
+    <div id="chat-page" class="hidden">
+        <div class="chat-container">
+            <div class="chat-header">
+                <h2>Spring WebSocket Chat Demo</h2>
+            </div>
+            <div class="connecting">
+                Connecting...
+            </div>
+            <ul id="messageArea">
+
+            </ul>
+            <form id="messageForm" name="messageForm" nameForm="messageForm">
+                <div class="form-group">
+                    <div class="input-group clearfix">
+                        <input type="text" id="message" placeholder="Type a message..." autocomplete="off" class="form-control"/>
+                        <button type="submit" class="primary">Send</button>
+                    </div>
+                </div>
+            </form>
+        </div>
+    </div>
+
+    <script src="/js/sockjs.min.js"></script>
+    <script src="/js/stomp.min.js"></script>
+    <script src="/js/main.js"></script>
+  </body>
+</html>

+ 121 - 0
blade-ops/blade-websocket/src/main/resources/static/js/main.js

@@ -0,0 +1,121 @@
+'use strict';
+
+var usernamePage = document.querySelector('#username-page');
+var chatPage = document.querySelector('#chat-page');
+var usernameForm = document.querySelector('#usernameForm');
+var messageForm = document.querySelector('#messageForm');
+var messageInput = document.querySelector('#message');
+var messageArea = document.querySelector('#messageArea');
+var connectingElement = document.querySelector('.connecting');
+
+var stompClient = null;
+var username = null;
+
+var colors = [
+    '#2196F3', '#32c787', '#00BCD4', '#ff5652',
+    '#ffc107', '#ff85af', '#FF9800', '#39bbb0'
+];
+
+function connect(event) {
+    username = document.querySelector('#name').value.trim();
+
+    if(username) {
+        usernamePage.classList.add('hidden');
+        chatPage.classList.remove('hidden');
+
+        var socket = new SockJS('/ws');
+        stompClient = Stomp.over(socket);
+
+        stompClient.connect({}, onConnected, onError);
+    }
+    event.preventDefault();
+}
+
+
+function onConnected() {
+    // Subscribe to the Public Topic
+    stompClient.subscribe('/topic/public', onMessageReceived);
+
+    // Tell your username to the server
+    stompClient.send("/app/chat.addUser",
+        {},
+        JSON.stringify({sender: username, type: 'JOIN'})
+    )
+
+    connectingElement.classList.add('hidden');
+}
+
+
+function onError(error) {
+    connectingElement.textContent = 'Could not connect to WebSocket server. Please refresh this page to try again!';
+    connectingElement.style.color = 'red';
+}
+
+
+function sendMessage(event) {
+    var messageContent = messageInput.value.trim();
+
+    if(messageContent && stompClient) {
+        var chatMessage = {
+            sender: username,
+            content: messageInput.value,
+            type: 'CHAT'
+        };
+
+        stompClient.send("/app/chat.sendMessage", {}, JSON.stringify(chatMessage));
+        messageInput.value = '';
+    }
+    event.preventDefault();
+}
+
+
+function onMessageReceived(payload) {
+    var message = JSON.parse(payload.body);
+
+    var messageElement = document.createElement('li');
+
+    if(message.type === 'JOIN') {
+        messageElement.classList.add('event-message');
+        message.content = message.sender + ' joined!';
+    } else if (message.type === 'LEAVE') {
+        messageElement.classList.add('event-message');
+        message.content = message.sender + ' left!';
+    } else {
+        messageElement.classList.add('chat-message');
+
+        var avatarElement = document.createElement('i');
+        var avatarText = document.createTextNode(message.sender[0]);
+        avatarElement.appendChild(avatarText);
+        avatarElement.style['background-color'] = getAvatarColor(message.sender);
+
+        messageElement.appendChild(avatarElement);
+
+        var usernameElement = document.createElement('span');
+        var usernameText = document.createTextNode(message.sender);
+        usernameElement.appendChild(usernameText);
+        messageElement.appendChild(usernameElement);
+    }
+
+    var textElement = document.createElement('p');
+    var messageText = document.createTextNode(message.content);
+    textElement.appendChild(messageText);
+
+    messageElement.appendChild(textElement);
+
+    messageArea.appendChild(messageElement);
+    messageArea.scrollTop = messageArea.scrollHeight;
+}
+
+
+function getAvatarColor(messageSender) {
+    var hash = 0;
+    for (var i = 0; i < messageSender.length; i++) {
+        hash = 31 * hash + messageSender.charCodeAt(i);
+    }
+
+    var index = Math.abs(hash % colors.length);
+    return colors[index];
+}
+
+usernameForm.addEventListener('submit', connect, true)
+messageForm.addEventListener('submit', sendMessage, true)

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
blade-ops/blade-websocket/src/main/resources/static/js/sockjs.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7 - 0
blade-ops/blade-websocket/src/main/resources/static/js/stomp.min.js


+ 32 - 0
blade-ops/pom.xml

@@ -0,0 +1,32 @@
+<?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>BladeX-Biz</artifactId>
+        <groupId>org.springblade</groupId>
+        <version>2.7.2.RELEASE</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>blade-example</artifactId>
+    <name>${project.artifactId}</name>
+    <version>2.8.1.RELEASE</version>
+    <packaging>pom</packaging>
+    <description>BladeX 微服务范例集合</description>
+
+    <modules>
+        <module>blade-mq-rabbit</module>
+        <module>blade-websocket</module>
+        <module>blade-stream-consumer</module>
+        <module>blade-stream-provider</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-biz-common</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>

+ 1 - 0
blade-service/community/src/main/java/org/springblade/community/controller/AgencyController.java

@@ -19,6 +19,7 @@ package org.springblade.community.controller;
 import cn.hutool.core.lang.Assert;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;

+ 4 - 4
blade-service/community/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9522
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.community.url}
+    username: ${blade.datasource.community.username}
+    password: ${blade.datasource.community.password}

+ 4 - 4
blade-service/device/src/main/resources/application-prod.yml

@@ -1,13 +1,13 @@
 #服务器端口
 server:
-  port: 9530
+  port: 9532
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.estate.url}
-    username: ${blade.datasource.estate.username}
-    password: ${blade.datasource.estate.password}
+    url: ${blade.datasource.device.url}
+    username: ${blade.datasource.device.username}
+    password: ${blade.datasource.device.password}
 
 #云梯
 yunti:

+ 10 - 4
blade-service/device/src/main/resources/application-test.yml

@@ -1,10 +1,16 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9532
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.estate.url}
+    username: ${blade.datasource.estate.username}
+    password: ${blade.datasource.estate.password}
+
+#云梯
+yunti:
+  url: https://zlopen.yun-ti.com
+  appKey: bnh6aHNxVmN5dEtGODJPNGdBS1ZMNXJp
+  appSecret: Ym5oNmFITnhWbU41ZEV0R09ESlBOR2RC

+ 4 - 4
blade-service/enterprise/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9529
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.enterprise.url}
+    username: ${blade.datasource.enterprise.username}
+    password: ${blade.datasource.enterprise.password}

+ 4 - 4
blade-service/estate/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9530
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.estate.url}
+    username: ${blade.datasource.estate.username}
+    password: ${blade.datasource.estate.password}

+ 3 - 0
blade-service/grid/src/main/java/org/springblade/community/grid/service/impl/GridResourceServiceImpl.java

@@ -21,6 +21,8 @@ import org.springblade.community.grid.vo.GridResourceVO;
 import org.springblade.community.grid.mapper.GridResourceMapper;
 import org.springblade.community.grid.service.IGridResourceService;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
@@ -38,4 +40,5 @@ public class GridResourceServiceImpl extends BaseServiceImpl<GridResourceMapper,
 		return page.setRecords(baseMapper.selectGridResourcePage(page, gridResource));
 	}
 
+
 }

+ 4 - 4
blade-service/grid/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9525
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.grid.url}
+    username: ${blade.datasource.grid.username}
+    password: ${blade.datasource.grid.password}

+ 4 - 4
blade-service/person/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 9530
+  port: 9531
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.person.url}
+    username: ${blade.datasource.person.username}
+    password: ${blade.datasource.person.password}

+ 6 - 3
blade-service/smart-party/src/main/resources/application-dev.yml

@@ -5,6 +5,9 @@ server:
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.smartparty.url}
-    username: ${blade.datasource.smartparty.username}
-    password: ${blade.datasource.smartparty.password}
+#    url: ${blade.datasource.smartparty.url}
+#    username: ${blade.datasource.smartparty.username}
+#    password: ${blade.datasource.smartparty.password}
+    url: jdbc:mysql://192.168.0.76:3306/smart_community?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&tinyInt1isBit=false&allowMultiQueries=true&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
+    username: root
+    password: 2e564ee5-d9ed-11e9-bab6-0242ac170005

+ 4 - 4
blade-service/smart-party/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9528
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.smartparty.url}
+    username: ${blade.datasource.smartparty.username}
+    password: ${blade.datasource.smartparty.password}

+ 4 - 4
blade-service/system-expand/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9526
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.systemExpand.url}
+    username: ${blade.datasource.systemExpand.username}
+    password: ${blade.datasource.systemExpand.password}

+ 1 - 1
blade-service/work-order/src/main/java/org/springblade/workorder/publicevent/service/impl/PublicEventServiceImpl.java

@@ -70,7 +70,7 @@ public class PublicEventServiceImpl extends BaseServiceImpl<PublicEventMapper, P
 		String businessTable = FlowUtil.getBusinessTable(ProcessConstant.PUBLIC_EVENT);
 		if (Func.isEmpty(publicEvent.getId())) {
 			publicEvent.setFlag(STEP_1.step);
-			// 保存leave
+			// 保存表单实体类
 			save(publicEvent);
 			// 启动流程
 			Kv variables = Kv.create()

+ 4 - 4
blade-service/work-order/src/main/resources/application-test.yml

@@ -1,10 +1,10 @@
 #服务器端口
 server:
-  port: 8102
+  port: 9533
 
 #数据源配置
 spring:
   datasource:
-    url: ${blade.datasource.test.url}
-    username: ${blade.datasource.test.username}
-    password: ${blade.datasource.test.password}
+    url: ${blade.datasource.workOrder.url}
+    username: ${blade.datasource.workOrder.username}
+    password: ${blade.datasource.workOrder.password}

+ 2 - 0
pom.xml

@@ -34,6 +34,8 @@
     <modules>
         <module>blade-biz-common</module>
         <module>blade-gateway</module>
+        <module>blade-ops</module>
+        <module>blade-ops-api</module>
         <module>blade-service</module>
         <module>blade-service-api</module>
         <module>community-app-gateway</module>

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä