diff --git a/bus/README.md b/bus/README.md
new file mode 100644
index 0000000..1069585
--- /dev/null
+++ b/bus/README.md
@@ -0,0 +1,6 @@
+# TwoStepsFromJava-Cloud-Bus
+
+Spring Cloud 示例项目:Bus
+
+
+Spring Cloud Release Trains: [Dalston.SR1](http://projects.spring.io/spring-cloud/)
\ No newline at end of file
diff --git a/bus/mall-web/pom.xml b/bus/mall-web/pom.xml
new file mode 100755
index 0000000..6476c20
--- /dev/null
+++ b/bus/mall-web/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ mall-web
+ MS Blog Projects(Bus): Mall Web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+ org.springframework.cloud
+ spring-cloud-starter-feign
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-kafka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-kafka
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/Application.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/Application.java
new file mode 100644
index 0000000..386b272
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/Application.java
@@ -0,0 +1,39 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+
+/**
+ * TwoStepsFromJava Cloud -- Mall Web Project
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableFeignClients
+@EnableDiscoveryClient
+@RemoteApplicationEventScan
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java
new file mode 100644
index 0000000..597ed94
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.bus;
+
+
+import com.google.common.base.MoreObjects;
+import org.springframework.cloud.bus.event.RemoteApplicationEvent;
+
+/**
+ * 商品事件
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductEvent extends RemoteApplicationEvent {
+ /** 消息类型:更新商品,值为: {@value} */
+ public static final String ET_UPDATE = "update";
+ /** 消息类型:删除商品,值为: {@value} */
+ public static final String ET_DELETE = "delete";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private String itemCode;
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductEvent() {
+ super();
+ }
+
+ public ProductEvent(Object source, String originService, String destinationService, String action, String itemCode) {
+ super(source, originService, destinationService);
+ this.action = action;
+ this.itemCode = itemCode;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("itemCode", this.getItemCode()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+}
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
new file mode 100644
index 0000000..ed312d5
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
@@ -0,0 +1,48 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.controller;
+
+import io.twostepsfromjava.cloud.web.mall.dto.ProductDto;
+import io.twostepsfromjava.cloud.web.mall.service.ProductService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+
+/**
+ * Product Controller
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/products")
+public class ProductController {
+ @Autowired
+ private ProductService productService;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public List list() {
+ return this.productService.findAll();
+ }
+
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.GET)
+ public ProductDto detail(@PathVariable String itemCode) {
+ return this.productService.loadByItemCode(itemCode);
+ }
+}
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/dto/ProductDto.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/dto/ProductDto.java
new file mode 100644
index 0000000..d3da9c9
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/dto/ProductDto.java
@@ -0,0 +1,84 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.dto;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品信息DTO对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class ProductDto {
+ private static final long serialVersionUID = 1L;
+
+ // ========================================================================
+ // fields =================================================================
+ private String itemCode; // 商品货号
+ private String name; // 商品名称
+ private String bandName; // 商品品牌名称
+ private int price; // 商品价格(分)
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductDto() {
+ }
+
+ public ProductDto(String itemCode, String name, String bandName, int price) {
+ this.itemCode = itemCode;
+ this.name = name;
+ this.bandName = bandName;
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("itemCode", this.getItemCode())
+ .add("name", this.getName())
+ .add("bandName", this.getBandName())
+ .add("price", this.getPrice()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBandName() {
+ return bandName;
+ }
+ public void setBandName(String bandName) {
+ this.bandName = bandName;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+ public void setPrice(int price) {
+ this.price = price;
+ }
+}
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsg.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsg.java
new file mode 100644
index 0000000..51303a1
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsg.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.mq;
+
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品消息
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductMsg {
+ /** 消息类型:更新商品,值为: {@value} */
+ public static final String MA_UPDATE = "update";
+ /** 消息类型:删除商品,值为: {@value} */
+ public static final String MA_DELETE = "delete";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private String itemCode;
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductMsg() { }
+
+ public ProductMsg(String action, String itemCode) {
+ this.action = action;
+ this.itemCode = itemCode;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("itemCode", this.getItemCode()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+}
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsgListener.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsgListener.java
new file mode 100644
index 0000000..0539db5
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsgListener.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.mq;
+
+
+import io.twostepsfromjava.cloud.web.mall.dto.ProductDto;
+import io.twostepsfromjava.cloud.web.mall.service.ProductService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+
+/**
+ * 商品消息监听器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductMsgListener {
+ protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired
+ protected ProductService productService;
+
+ public void onProductMsgSink(ProductMsg productMsg) {
+ if (ProductMsg.MA_UPDATE.equalsIgnoreCase(productMsg.getAction())) {
+ this.logger.debug("收到商品变更消息,商品货号: {}", productMsg.getItemCode());
+ // 重新获取该商品信息
+ ProductDto productDto = this.productService.loadByItemCode(productMsg.getItemCode());
+ if (null != productDto)
+ this.logger.debug("重新获取到的商品信息为:{}", productDto);
+ else
+ this.logger.debug("货号为:{} 的商品不存在", productMsg.getItemCode());
+ } else if (ProductMsg.MA_DELETE.equalsIgnoreCase(productMsg.getAction())) {
+ this.logger.debug("收到商品删除消息,所要删除商品货号为: {}", productMsg.getItemCode());
+ } else {
+ this.logger.debug("收到未知商品消息: {}", productMsg);
+ }
+ }
+}
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductEventListener.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductEventListener.java
new file mode 100644
index 0000000..cf54729
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductEventListener.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+import io.twostepsfromjava.cloud.bus.ProductEvent;
+import io.twostepsfromjava.cloud.web.mall.dto.ProductDto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 远程事件监听
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@Component
+public class ProductEventListener implements ApplicationListener {
+ protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired
+ protected ProductService productService;
+
+ @Override
+ public void onApplicationEvent(ProductEvent productEvent) {
+ if (ProductEvent.ET_UPDATE.equalsIgnoreCase(productEvent.getAction())) {
+ this.logger.debug("Web微服务收到商品变更事件,商品货号: {}", productEvent.getItemCode());
+ // 重新获取该商品信息
+ ProductDto productDto = this.productService.loadByItemCode(productEvent.getItemCode());
+ if (null != productDto)
+ this.logger.debug("重新获取到的商品信息为:{}", productDto);
+ else
+ this.logger.debug("货号为:{} 的商品不存在", productEvent.getItemCode());
+ } else if (ProductEvent.ET_DELETE.equalsIgnoreCase(productEvent.getAction())) {
+ this.logger.debug("Web微服务收到商品删除事件,所要删除商品货号为: {}", productEvent.getItemCode());
+ } else {
+ this.logger.debug("Web微服务收到未知商品事件: {}", productEvent);
+ }
+ }
+}
diff --git a/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
new file mode 100644
index 0000000..b0c769a
--- /dev/null
+++ b/bus/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
@@ -0,0 +1,38 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+import io.twostepsfromjava.cloud.web.mall.dto.ProductDto;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.util.List;
+
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@FeignClient("productservice")
+public interface ProductService {
+ @RequestMapping(value = "/products", method = RequestMethod.GET)
+ List findAll();
+
+ @RequestMapping(value = "/products/{itemCode}", method = RequestMethod.GET)
+ ProductDto loadByItemCode(@PathVariable("itemCode") String itemCode);
+}
diff --git a/bus/mall-web/src/main/resources/application.properties b/bus/mall-web/src/main/resources/application.properties
new file mode 100644
index 0000000..3594b0a
--- /dev/null
+++ b/bus/mall-web/src/main/resources/application.properties
@@ -0,0 +1,15 @@
+server.port=8080
+
+spring.application.name=MALL-WEB
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
+logging.level.io.twostepsfromjava=DEBUG
+
+# =====================================================================================================================
+# == stream / kafka ==
+# =====================================================================================================================
+spring.cloud.stream.kafka.binder.brokers=localhost
+spring.cloud.stream.kafka.binder.defaultBrokerPort=9092
+spring.cloud.stream.kafka.binder.zkNodes=localhost
\ No newline at end of file
diff --git a/bus/mall-web/src/main/resources/banner.txt b/bus/mall-web/src/main/resources/banner.txt
new file mode 100644
index 0000000..2d4682f
--- /dev/null
+++ b/bus/mall-web/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Consumer ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/bus/parent/pom.xml b/bus/parent/pom.xml
new file mode 100644
index 0000000..c6f3dbd
--- /dev/null
+++ b/bus/parent/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.2.RELEASE
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ MS Blog Projects(Bus): Parent Pom
+ pom
+
+
+ UTF-8
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ Dalston.SR3
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+ 1.8
+ 1.8
+
+
+
+
+
\ No newline at end of file
diff --git a/bus/pom.xml b/bus/pom.xml
new file mode 100755
index 0000000..63a0cb0
--- /dev/null
+++ b/bus/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ parent
+
+
+ twostepsfromjava-clouds
+ 1.0.0-SNAPSHOT
+ MS Blog Projects -- Bus
+ pom
+
+
+ parent
+ service-discovery
+
+ product-service
+ user-service
+
+ mall-web
+
+
diff --git a/bus/product-service/pom.xml b/bus/product-service/pom.xml
new file mode 100755
index 0000000..b011225
--- /dev/null
+++ b/bus/product-service/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ product-service
+ MS Blog Projects(Bus): Product Service Server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-kafka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-kafka
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/Application.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/Application.java
new file mode 100644
index 0000000..e6bd5ee
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/Application.java
@@ -0,0 +1,37 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * TwoStepsFromJava Cloud -- ProductDto Service 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableDiscoveryClient
+@RemoteApplicationEventScan
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java
new file mode 100644
index 0000000..597ed94
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.bus;
+
+
+import com.google.common.base.MoreObjects;
+import org.springframework.cloud.bus.event.RemoteApplicationEvent;
+
+/**
+ * 商品事件
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductEvent extends RemoteApplicationEvent {
+ /** 消息类型:更新商品,值为: {@value} */
+ public static final String ET_UPDATE = "update";
+ /** 消息类型:删除商品,值为: {@value} */
+ public static final String ET_DELETE = "delete";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private String itemCode;
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductEvent() {
+ super();
+ }
+
+ public ProductEvent(Object source, String originService, String destinationService, String action, String itemCode) {
+ super(source, originService, destinationService);
+ this.action = action;
+ this.itemCode = itemCode;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("itemCode", this.getItemCode()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/api/ProductEndpoint.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/api/ProductEndpoint.java
new file mode 100644
index 0000000..be39d8d
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/api/ProductEndpoint.java
@@ -0,0 +1,59 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.api;
+
+import io.twostepsfromjava.cloud.product.dto.ProductDto;
+import io.twostepsfromjava.cloud.product.service.ProductService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+/**
+ * ProductDto API服务
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/products")
+public class ProductEndpoint {
+ protected Logger logger = LoggerFactory.getLogger(ProductEndpoint.class);
+
+ @Autowired
+ ProductService productService;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public List list() {
+ return this.productService.findAll();
+ }
+
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.GET)
+ public ProductDto detail(@PathVariable String itemCode) {
+ return this.productService.findOne(itemCode);
+ }
+
+ // FIXME: 该端点仅仅是用来测试消息发送,并不包含任何业务逻辑处理
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.POST)
+ public ProductDto save(@PathVariable String itemCode) {
+ ProductDto productDto = this.productService.findOne(itemCode);
+ if (null != productDto) {
+ this.productService.save(productDto);
+ }
+ return productDto;
+ }
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/dto/ProductDto.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/dto/ProductDto.java
new file mode 100644
index 0000000..500fe43
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/dto/ProductDto.java
@@ -0,0 +1,84 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.dto;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品信息DTO对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class ProductDto {
+ private static final long serialVersionUID = 1L;
+
+ // ========================================================================
+ // fields =================================================================
+ private String itemCode; // 商品货号
+ private String name; // 商品名称
+ private String bandName; // 商品品牌名称
+ private int price; // 商品价格(分)
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductDto() {
+ }
+
+ public ProductDto(String itemCode, String name, String bandName, int price) {
+ this.itemCode = itemCode;
+ this.name = name;
+ this.bandName = bandName;
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("itemCode", this.getItemCode())
+ .add("name", this.getName())
+ .add("bandName", this.getBandName())
+ .add("price", this.getPrice()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBandName() {
+ return bandName;
+ }
+ public void setBandName(String bandName) {
+ this.bandName = bandName;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+ public void setPrice(int price) {
+ this.price = price;
+ }
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/entity/Product.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/entity/Product.java
new file mode 100644
index 0000000..ca56fce
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/entity/Product.java
@@ -0,0 +1,84 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.entity;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品信息实体对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class Product {
+ private static final long serialVersionUID = 1L;
+
+ // ========================================================================
+ // fields =================================================================
+ private String itemCode; // 商品货号
+ private String name; // 商品名称
+ private String bandName; // 商品品牌名称
+ private int price; // 商品价格(分)
+
+ // ========================================================================
+ // constructor ============================================================
+ public Product() {
+ }
+
+ public Product(String itemCode, String name, String bandName, int price) {
+ this.itemCode = itemCode;
+ this.name = name;
+ this.bandName = bandName;
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("itemCode", this.getItemCode())
+ .add("name", this.getName())
+ .add("bandName", this.getBandName())
+ .add("price", this.getPrice()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBandName() {
+ return bandName;
+ }
+ public void setBandName(String bandName) {
+ this.bandName = bandName;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+ public void setPrice(int price) {
+ this.price = price;
+ }
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/mq/ProductMsg.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/mq/ProductMsg.java
new file mode 100644
index 0000000..4d18bf7
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/mq/ProductMsg.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.mq;
+
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品消息
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductMsg {
+ /** 消息类型:更新商品,值为: {@value} */
+ public static final String MA_UPDATE = "update";
+ /** 消息类型:删除商品,值为: {@value} */
+ public static final String MA_DELETE = "delete";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private String itemCode;
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductMsg() { }
+
+ public ProductMsg(String action, String itemCode) {
+ this.action = action;
+ this.itemCode = itemCode;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("itemCode", this.getItemCode()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/service/ProductService.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/service/ProductService.java
new file mode 100644
index 0000000..462fd53
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/service/ProductService.java
@@ -0,0 +1,119 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.service;
+
+import io.twostepsfromjava.cloud.bus.ProductEvent;
+import io.twostepsfromjava.cloud.product.dto.ProductDto;
+import io.twostepsfromjava.cloud.product.mq.ProductMsg;
+import io.twostepsfromjava.cloud.product.util.ApplicationContextHolder;
+import io.twostepsfromjava.cloud.product.util.RemoteApplicationEventPublisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 商品服务
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@Service
+public class ProductService {
+ protected Logger logger = LoggerFactory.getLogger(ProductService.class);
+
+ private List productList;
+
+ @Autowired
+ public ProductService() {
+ this.productList = this.buildProducts();
+ }
+
+ /**
+ * 获取商品列表
+ * @return
+ */
+ public List findAll() {
+ return this.productList;
+ }
+
+ /**
+ * 根据ItemCode获取
+ * @param itemCode
+ * @return
+ */
+ public ProductDto findOne(String itemCode) {
+ for (ProductDto productDto : this.productList) {
+ if (productDto.getItemCode().equalsIgnoreCase(itemCode))
+ return productDto;
+ }
+
+ return null;
+ }
+
+ /**
+ * 保存或更新商品信息
+ * @param productDto
+ * @return
+ */
+ public ProductDto save(ProductDto productDto) {
+ // TODO: 实现商品保存处理
+ for (ProductDto sourceProductDto : this.productList) {
+ if (sourceProductDto.getItemCode().equalsIgnoreCase(productDto.getItemCode())) {
+ sourceProductDto.setName(sourceProductDto.getName() + "-new");
+ sourceProductDto.setPrice(sourceProductDto.getPrice() + 100);
+ productDto = sourceProductDto;
+ break;
+ }
+ }
+
+ // 发送商品消息
+ // this.sendMsg(ProductMsg.MA_UPDATE, productDto.getItemCode());
+ this.fireEvent(ProductEvent.ET_UPDATE, productDto);
+
+ return productDto;
+ }
+
+ protected void sendMsg(String msgAction, String itemCode) {
+ ProductMsg productMsg = new ProductMsg(msgAction, itemCode);
+ this.logger.debug("发送商品消息:{} ", productMsg);
+
+ // 发送消息
+ // this.source.output().send(MessageBuilder.withPayload(productMsg).build());
+ }
+
+ protected void fireEvent(String eventAction, ProductDto productDto) {
+ ProductEvent productEvent = new ProductEvent(productDto,
+ ApplicationContextHolder.getApplicationContext().getId(), "*:**",
+ eventAction, productDto.getItemCode());
+
+ // 发布事件
+ RemoteApplicationEventPublisher.publishEvent(productEvent);
+ }
+
+ protected List buildProducts() {
+ List products = new ArrayList<>();
+ products.add(new ProductDto("item-1", "测试商品-1", "TwoStepsFromJava", 100));
+ products.add(new ProductDto("item-2", "测试商品-2", "TwoStepsFromJava", 200));
+ products.add(new ProductDto("item-3", "测试商品-3", "TwoStepsFromJava", 300));
+ products.add(new ProductDto("item-4", "测试商品-4", "TwoStepsFromJava", 400));
+ products.add(new ProductDto("item-5", "测试商品-5", "TwoStepsFromJava", 500));
+ products.add(new ProductDto("item-6", "测试商品-6", "TwoStepsFromJava", 600));
+ return products;
+ }
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/util/ApplicationContextHolder.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/util/ApplicationContextHolder.java
new file mode 100755
index 0000000..0c96b70
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/util/ApplicationContextHolder.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+/**
+ * ApplicationContext辅助类
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@Component
+public class ApplicationContextHolder implements ApplicationContextAware, DisposableBean {
+ private static Logger logger = LoggerFactory.getLogger(ApplicationContextHolder.class);
+ private static ApplicationContext applicationContext = null;
+
+ @Override
+ public void destroy() throws Exception {
+ ApplicationContextHolder.clearHolder();
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ logger.debug("注入ApplicationContext到SpringContextHolder: {}", applicationContext);
+
+ if (ApplicationContextHolder.applicationContext != null) {
+ logger.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为: {}", ApplicationContextHolder.applicationContext);
+ }
+
+ ApplicationContextHolder.applicationContext = applicationContext;
+ }
+
+ /**
+ * 取得存储在静态变量中的ApplicationContext.
+ */
+ public static ApplicationContext getApplicationContext() {
+ assertContextInjected();
+ return applicationContext;
+ }
+
+ /**
+ * 清除SpringContextHolder中的ApplicationContext为Null.
+ */
+ public static void clearHolder() {
+ logger.debug("清除SpringContextHolder中的ApplicationContext: {}", applicationContext);
+ applicationContext = null;
+ }
+
+ /**
+ * 检查ApplicationContext不为空.
+ */
+ private static void assertContextInjected() {
+ Assert.notNull(applicationContext, "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
+ }
+}
diff --git a/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/util/RemoteApplicationEventPublisher.java b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/util/RemoteApplicationEventPublisher.java
new file mode 100755
index 0000000..b0dfecb
--- /dev/null
+++ b/bus/product-service/src/main/java/io/twostepsfromjava/cloud/product/util/RemoteApplicationEventPublisher.java
@@ -0,0 +1,44 @@
+/**
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.bus.event.RemoteApplicationEvent;
+import org.springframework.context.ApplicationContext;
+
+
+/**
+ * 远程事件发布者
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class RemoteApplicationEventPublisher {
+ protected static Logger logger = LoggerFactory.getLogger(RemoteApplicationEventPublisher.class);
+
+ /**
+ * 发布一个事件
+ * @param event
+ */
+ public static void publishEvent(RemoteApplicationEvent event){
+ ApplicationContext context = ApplicationContextHolder.getApplicationContext();
+ if(null != context) {
+ context.publishEvent(event);
+ logger.debug("已发布事件:{}", event);
+ }else{
+ logger.warn("无法获取到当前Spring上下文信息,不能够发布事件");
+ }
+ }
+}
\ No newline at end of file
diff --git a/bus/product-service/src/main/resources/application.properties b/bus/product-service/src/main/resources/application.properties
new file mode 100644
index 0000000..4860fdb
--- /dev/null
+++ b/bus/product-service/src/main/resources/application.properties
@@ -0,0 +1,15 @@
+server.port=2100
+
+spring.application.name=productservice
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
+logging.level.io.twostepsfromjava=DEBUG
+
+# =====================================================================================================================
+# == stream / kafka ==
+# =====================================================================================================================
+spring.cloud.stream.kafka.binder.brokers=localhost
+spring.cloud.stream.kafka.binder.defaultBrokerPort=9092
+spring.cloud.stream.kafka.binder.zkNodes=localhost
\ No newline at end of file
diff --git a/bus/product-service/src/main/resources/banner.txt b/bus/product-service/src/main/resources/banner.txt
new file mode 100644
index 0000000..a692d74
--- /dev/null
+++ b/bus/product-service/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Product ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/bus/service-discovery/pom.xml b/bus/service-discovery/pom.xml
new file mode 100755
index 0000000..5d93b2c
--- /dev/null
+++ b/bus/service-discovery/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ service-discovery
+ MS Blog Projects(Bus): Eureka Server
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka-server
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/bus/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java b/bus/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
new file mode 100644
index 0000000..31a533d
--- /dev/null
+++ b/bus/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
@@ -0,0 +1,35 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.discovery;
+
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+/**
+ * TwoStepsFromJava Cloud -- Service Discoery 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableEurekaServer
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(Application.class).web(true).run(args);
+ }
+
+}
diff --git a/bus/service-discovery/src/main/resources/application.properties b/bus/service-discovery/src/main/resources/application.properties
new file mode 100644
index 0000000..269e732
--- /dev/null
+++ b/bus/service-discovery/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+server.port=8260
+
+eureka.instance.hostname=localhost
+eureka.client.register-with-eureka=false
+eureka.client.fetch-registry=false
+eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/bus/service-discovery/src/main/resources/banner.txt b/bus/service-discovery/src/main/resources/banner.txt
new file mode 100644
index 0000000..e12a88a
--- /dev/null
+++ b/bus/service-discovery/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Discovery ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/bus/user-service/pom.xml b/bus/user-service/pom.xml
new file mode 100755
index 0000000..3e73894
--- /dev/null
+++ b/bus/user-service/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ user-service
+ MS Blog Projects(Bus): User Service Server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-kafka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bus-kafka
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/Application.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/Application.java
new file mode 100644
index 0000000..0635930
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/Application.java
@@ -0,0 +1,37 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * TwoStepsFromJava Cloud -- User Service 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableDiscoveryClient
+@RemoteApplicationEventScan
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java
new file mode 100644
index 0000000..597ed94
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/bus/ProductEvent.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.bus;
+
+
+import com.google.common.base.MoreObjects;
+import org.springframework.cloud.bus.event.RemoteApplicationEvent;
+
+/**
+ * 商品事件
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductEvent extends RemoteApplicationEvent {
+ /** 消息类型:更新商品,值为: {@value} */
+ public static final String ET_UPDATE = "update";
+ /** 消息类型:删除商品,值为: {@value} */
+ public static final String ET_DELETE = "delete";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private String itemCode;
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductEvent() {
+ super();
+ }
+
+ public ProductEvent(Object source, String originService, String destinationService, String action, String itemCode) {
+ super(source, originService, destinationService);
+ this.action = action;
+ this.itemCode = itemCode;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("itemCode", this.getItemCode()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+}
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/event/UserEvent.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/event/UserEvent.java
new file mode 100644
index 0000000..a92d676
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/event/UserEvent.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.event;
+
+
+import com.google.common.base.MoreObjects;
+import io.twostepsfromjava.cloud.user.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * 用户事件
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class UserEvent extends ApplicationEvent {
+ protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ /** 消息类型:更新用户,值为: {@value} */
+ public static final String ET_UPDATE = "update";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private User user;
+
+ // ========================================================================
+ // constructor ============================================================
+ public UserEvent(User user) {
+ super(user);
+ this.user = user;
+ }
+
+ public UserEvent(User user, String action) {
+ super(user);
+ this.action = action;
+ this.user = user;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("user", this.getUser()).toString();
+ }
+
+ /**
+ * 发布事件
+ */
+ public void fire() {
+ ApplicationContext context = ApplicationContextHolder.getApplicationContext();
+ if(null != context) {
+ logger.debug("发布事件:{}", this);
+ context.publishEvent(this);
+ }else{
+ logger.warn("无法获取到当前Spring上下文信息,不能够发布事件");
+ }
+ }
+
+ public void foo() {
+ new UserEvent(user, UserEvent.ET_UPDATE).fire();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public User getUser() {
+ return user;
+ }
+ public void setUser(User user) {
+ this.user = user;
+ }
+}
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/event/UserEventListener.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/event/UserEventListener.java
new file mode 100644
index 0000000..04d67ef
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/event/UserEventListener.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.event;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * 用户事件监听
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@Component
+public class UserEventListener implements ApplicationListener {
+ protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Override
+ public void onApplicationEvent(UserEvent userEvent) {
+ this.logger.debug("收到用户事件:{} ", userEvent);
+ // TODO: 实现具体的业务处理
+ }
+}
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/User.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/User.java
new file mode 100644
index 0000000..3de27a2
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/User.java
@@ -0,0 +1,83 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.user;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 用户信息DTO对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class User {
+ private static final long serialVersionUID = 1L;
+ // ========================================================================
+ // fields =================================================================
+ private String loginName; // 用户登陆名称
+ private String name; // 用户姓名
+ private String avatar; // 用户头像
+ private String memos; // 信息备注
+
+ // ========================================================================
+ // constructor ============================================================
+ public User() {
+ }
+
+ public User(String loginName, String name, String avatar, String memos) {
+ this.loginName = loginName;
+ this.name = name;
+ this.avatar = avatar;
+ this.memos = memos;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("loginName", this.getLoginName())
+ .add("name", this.getName())
+ .add("avatar", this.getAvatar())
+ .add("memos", this.getMemos()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getLoginName() {
+ return loginName;
+ }
+ public void setLoginName(String loginName) {
+ this.loginName = loginName;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getMemos() {
+ return memos;
+ }
+ public void setMemos(String memos) {
+ this.memos = memos;
+ }
+}
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/api/UserEndpoint.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/api/UserEndpoint.java
new file mode 100644
index 0000000..77d3e08
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/api/UserEndpoint.java
@@ -0,0 +1,42 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.user.api;
+
+import io.twostepsfromjava.cloud.user.dto.UserDto;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * User API服务
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/users")
+public class UserEndpoint {
+ protected Logger logger = LoggerFactory.getLogger(UserEndpoint.class);
+
+ @Value("${server.port:2200}")
+ private int serverPort = 2200;
+
+ @RequestMapping(value = "/{loginName}", method = RequestMethod.GET)
+ public UserDto detail(@PathVariable String loginName) {
+ String memos = "I come form " + this.serverPort;
+ return new UserDto(loginName, loginName, "/avatar/default.png", memos);
+ }
+}
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/dto/UserDto.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/dto/UserDto.java
new file mode 100644
index 0000000..5ca1eef
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/dto/UserDto.java
@@ -0,0 +1,83 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.user.dto;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 用户信息DTO对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class UserDto {
+ private static final long serialVersionUID = 1L;
+ // ========================================================================
+ // fields =================================================================
+ private String loginName; // 用户登陆名称
+ private String name; // 用户姓名
+ private String avatar; // 用户头像
+ private String memos; // 信息备注
+
+ // ========================================================================
+ // constructor ============================================================
+ public UserDto() {
+ }
+
+ public UserDto(String loginName, String name, String avatar, String memos) {
+ this.loginName = loginName;
+ this.name = name;
+ this.avatar = avatar;
+ this.memos = memos;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("loginName", this.getLoginName())
+ .add("name", this.getName())
+ .add("avatar", this.getAvatar())
+ .add("memos", this.getMemos()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getLoginName() {
+ return loginName;
+ }
+ public void setLoginName(String loginName) {
+ this.loginName = loginName;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAvatar() {
+ return avatar;
+ }
+ public void setAvatar(String avatar) {
+ this.avatar = avatar;
+ }
+
+ public String getMemos() {
+ return memos;
+ }
+ public void setMemos(String memos) {
+ this.memos = memos;
+ }
+}
diff --git a/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/service/ProductEventListener.java b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/service/ProductEventListener.java
new file mode 100644
index 0000000..4a5a448
--- /dev/null
+++ b/bus/user-service/src/main/java/io/twostepsfromjava/cloud/user/service/ProductEventListener.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.user.service;
+
+import io.twostepsfromjava.cloud.bus.ProductEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 远程事件监听
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@Component
+public class ProductEventListener implements ApplicationListener {
+ protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Override
+ public void onApplicationEvent(ProductEvent productEvent) {
+ if (ProductEvent.ET_UPDATE.equalsIgnoreCase(productEvent.getAction())) {
+ this.logger.debug("用户微服务收到商品变更事件,商品货号: {}", productEvent.getItemCode());
+ } else if (ProductEvent.ET_DELETE.equalsIgnoreCase(productEvent.getAction())) {
+ this.logger.debug("用户微服务收到商品删除事件,所要删除商品货号为: {}", productEvent.getItemCode());
+ } else {
+ this.logger.debug("用户微服务收到未知商品事件: {}", productEvent);
+ }
+ }
+}
diff --git a/bus/user-service/src/main/resources/application.properties b/bus/user-service/src/main/resources/application.properties
new file mode 100644
index 0000000..ee041f0
--- /dev/null
+++ b/bus/user-service/src/main/resources/application.properties
@@ -0,0 +1,15 @@
+server.port=2200
+
+spring.application.name=USER-SERVICE
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
+logging.level.io.twostepsfromjava=DEBUG
+
+# =====================================================================================================================
+# == stream / kafka ==
+# =====================================================================================================================
+spring.cloud.stream.kafka.binder.brokers=localhost
+spring.cloud.stream.kafka.binder.defaultBrokerPort=9092
+spring.cloud.stream.kafka.binder.zkNodes=localhost
\ No newline at end of file
diff --git a/bus/user-service/src/main/resources/banner.txt b/bus/user-service/src/main/resources/banner.txt
new file mode 100644
index 0000000..6d6d6bb
--- /dev/null
+++ b/bus/user-service/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- User ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/config/README.md b/config/README.md
new file mode 100644
index 0000000..bbf8a8b
--- /dev/null
+++ b/config/README.md
@@ -0,0 +1,6 @@
+# TwoStepsFromJava-Cloud-Feign
+
+Spring Cloud 示例项目:结合Ribbon和Feign实现声明式服务调用。
+
+
+Spring Cloud Release Trains: [Dalston.SR1](http://projects.spring.io/spring-cloud/)
\ No newline at end of file
diff --git a/config/config-client/pom.xml b/config/config-client/pom.xml
new file mode 100755
index 0000000..2e0a237
--- /dev/null
+++ b/config/config-client/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ config-client
+ Spring Cloud Sample Projects: Config Client
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+
\ No newline at end of file
diff --git a/config/config-client/src/main/java/io/twostepsfromjava/cloud/web/mall/Application.java b/config/config-client/src/main/java/io/twostepsfromjava/cloud/web/mall/Application.java
new file mode 100644
index 0000000..916fd94
--- /dev/null
+++ b/config/config-client/src/main/java/io/twostepsfromjava/cloud/web/mall/Application.java
@@ -0,0 +1,36 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+
+/**
+ * TwoStepsFromJava Cloud -- Config Client Project
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableDiscoveryClient
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/config/config-client/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ConfigController.java b/config/config-client/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ConfigController.java
new file mode 100644
index 0000000..c417c5b
--- /dev/null
+++ b/config/config-client/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ConfigController.java
@@ -0,0 +1,40 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.controller;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * Config Client Test Controller
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/cfg")
+public class ConfigController {
+ @Value("${foo}")
+ String foo;
+
+ @Value("${bar}")
+ String bar;
+
+ @RequestMapping(value = "/foo")
+ public String foo(){
+ return foo + "——" + bar;
+ }
+}
diff --git a/config/config-client/src/main/resources/application.properties b/config/config-client/src/main/resources/application.properties
new file mode 100644
index 0000000..1303c65
--- /dev/null
+++ b/config/config-client/src/main/resources/application.properties
@@ -0,0 +1,3 @@
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/config/config-client/src/main/resources/banner.txt b/config/config-client/src/main/resources/banner.txt
new file mode 100644
index 0000000..8860e63
--- /dev/null
+++ b/config/config-client/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- config client ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/config/config-client/src/main/resources/bootstrap.properties b/config/config-client/src/main/resources/bootstrap.properties
new file mode 100644
index 0000000..331a4e1
--- /dev/null
+++ b/config/config-client/src/main/resources/bootstrap.properties
@@ -0,0 +1,5 @@
+server.port=8080
+
+spring.application.name=mallWeb
+spring.cloud.config.profile=dev
+spring.cloud.config.uri= http://localhost:8280/
diff --git a/config/config-client/src/main/resources/logback.xml b/config/config-client/src/main/resources/logback.xml
new file mode 100644
index 0000000..d4b7206
--- /dev/null
+++ b/config/config-client/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+
+
+ logs/log-%d{yyyy-MM-dd}.%i.log
+
+
+ 64 MB
+
+
+
+
+
+ DEBUG
+
+
+ true
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
diff --git a/config/config-server/pom.xml b/config/config-server/pom.xml
new file mode 100755
index 0000000..dcf6dd6
--- /dev/null
+++ b/config/config-server/pom.xml
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ config-server
+ Spring Cloud Sample Projects: Config Server
+
+
+
+ org.springframework.cloud
+ spring-cloud-config-server
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/config/config-server/src/main/java/io/twostepsfromjava/cloud/service/hello/Application.java b/config/config-server/src/main/java/io/twostepsfromjava/cloud/service/hello/Application.java
new file mode 100644
index 0000000..87b9e88
--- /dev/null
+++ b/config/config-server/src/main/java/io/twostepsfromjava/cloud/service/hello/Application.java
@@ -0,0 +1,37 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.hello;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.config.server.EnableConfigServer;
+
+/**
+ * TwoStepsFromJava Cloud -- Config Server
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@SpringBootApplication
+@EnableConfigServer
+@EnableDiscoveryClient
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/config/config-server/src/main/resources/application.properties b/config/config-server/src/main/resources/application.properties
new file mode 100644
index 0000000..ad4e4cc
--- /dev/null
+++ b/config/config-server/src/main/resources/application.properties
@@ -0,0 +1,12 @@
+server.port=8280
+
+spring.application.name=config-server
+
+spring.cloud.config.server.git.uri=https://github.com/cd826/SpringcloudSamplesConfig
+spring.cloud.config.server.git.username=yourname
+spring.cloud.config.server.git.password=yourpass
+spring.cloud.config.server.git.basedir=tmp/
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/config/config-server/src/main/resources/banner.txt b/config/config-server/src/main/resources/banner.txt
new file mode 100644
index 0000000..123d812
--- /dev/null
+++ b/config/config-server/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Config Server ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/config/config-server/src/main/resources/logback.xml b/config/config-server/src/main/resources/logback.xml
new file mode 100644
index 0000000..d4b7206
--- /dev/null
+++ b/config/config-server/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+
+
+ logs/log-%d{yyyy-MM-dd}.%i.log
+
+
+ 64 MB
+
+
+
+
+
+ DEBUG
+
+
+ true
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
diff --git a/config/parent/pom.xml b/config/parent/pom.xml
new file mode 100644
index 0000000..84914e0
--- /dev/null
+++ b/config/parent/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.2.RELEASE
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ Spring Cloud Sample Projects: Parent Pom
+ pom
+
+
+ UTF-8
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ Dalston.SR1
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+ 1.8
+ 1.8
+
+
+
+
+
\ No newline at end of file
diff --git a/config/pom.xml b/config/pom.xml
new file mode 100755
index 0000000..fd13027
--- /dev/null
+++ b/config/pom.xml
@@ -0,0 +1,26 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ parent
+
+
+ twostepsfromjava-clouds
+ 1.0.0-SNAPSHOT
+ Spring Cloud Sample Projects
+ pom
+
+
+ parent
+ service-discovery
+
+ config-server
+ config-client
+
+
diff --git a/config/service-discovery/pom.xml b/config/service-discovery/pom.xml
new file mode 100755
index 0000000..c7040cc
--- /dev/null
+++ b/config/service-discovery/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ service-discovery
+ Spring Cloud Sample Projects: Eureka Server
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka-server
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/config/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java b/config/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
new file mode 100644
index 0000000..31a533d
--- /dev/null
+++ b/config/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
@@ -0,0 +1,35 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.discovery;
+
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+/**
+ * TwoStepsFromJava Cloud -- Service Discoery 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableEurekaServer
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(Application.class).web(true).run(args);
+ }
+
+}
diff --git a/config/service-discovery/src/main/resources/application.properties b/config/service-discovery/src/main/resources/application.properties
new file mode 100644
index 0000000..269e732
--- /dev/null
+++ b/config/service-discovery/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+server.port=8260
+
+eureka.instance.hostname=localhost
+eureka.client.register-with-eureka=false
+eureka.client.fetch-registry=false
+eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/config/service-discovery/src/main/resources/banner.txt b/config/service-discovery/src/main/resources/banner.txt
new file mode 100644
index 0000000..e12a88a
--- /dev/null
+++ b/config/service-discovery/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Discovery ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/config/service-discovery/src/main/resources/logback.xml b/config/service-discovery/src/main/resources/logback.xml
new file mode 100644
index 0000000..d4b7206
--- /dev/null
+++ b/config/service-discovery/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+
+
+ logs/log-%d{yyyy-MM-dd}.%i.log
+
+
+ 64 MB
+
+
+
+
+
+ DEBUG
+
+
+ true
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
diff --git a/eureka/service-discovery/pom.xml b/eureka/service-discovery/pom.xml
index 3f7810a..bd7dbc0 100755
--- a/eureka/service-discovery/pom.xml
+++ b/eureka/service-discovery/pom.xml
@@ -18,6 +18,11 @@
org.springframework.cloud
spring-cloud-starter-eureka-server
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
diff --git a/feign/mall-web/pom.xml b/feign/mall-web/pom.xml
index 52b0350..deaee9c 100755
--- a/feign/mall-web/pom.xml
+++ b/feign/mall-web/pom.xml
@@ -37,5 +37,14 @@
product-service-api
${project.version}
-
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
\ No newline at end of file
diff --git a/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java b/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
index e9d33a5..9e6f229 100644
--- a/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
+++ b/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
@@ -42,8 +42,15 @@ public List list() {
return this.productService.findAll();
}
- @RequestMapping(value = "/{itemCode}", method = RequestMethod.GET)
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.POST)
public Product detail(@PathVariable String itemCode) {
+ System.out.println("dddddddddd");
+ return this.productService.loadByItemCodeEx(itemCode, "OBgEDj", "restore");
+ }
+
+ @RequestMapping(value = "/t/{itemCode}", method = RequestMethod.POST)
+ public Product detailEx(@PathVariable String itemCode) {
+ System.out.println("dddddddddd");
return this.productService.loadByItemCode(itemCode);
}
}
diff --git a/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java b/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
index 805d4fa..95c5843 100644
--- a/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
+++ b/feign/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
@@ -18,6 +18,7 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@@ -37,4 +38,8 @@ public interface ProductService {
@RequestMapping(value = "/products/{itemCode}", method = RequestMethod.GET)
Product loadByItemCode(@PathVariable("itemCode") String itemCode);
+ @RequestMapping(value = "/products/{itemCode}/instruction/execute", method = RequestMethod.POST)
+ Product loadByItemCodeEx(@PathVariable("itemCode") String itemCode,
+ @RequestParam("user_id") String userId,
+ @RequestParam("instruction_code") String instructionCode);
}
diff --git a/feign/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/api/ProductEndpoint.java b/feign/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/api/ProductEndpoint.java
index b5da7c5..df3f690 100644
--- a/feign/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/api/ProductEndpoint.java
+++ b/feign/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/api/ProductEndpoint.java
@@ -48,6 +48,19 @@ public Product detail(@PathVariable String itemCode) {
return null;
}
+ @RequestMapping(value = "/item/{itemCode}/instruction/execute", method = RequestMethod.POST)
+ public Product detailEx(@PathVariable String itemCode,
+ @RequestParam(value = "user_id", required = false) String userId,
+ @RequestParam(value = "instruction_code") String instructionCode) {
+ System.out.println("userId = " + userId);
+ List products = this.buildProducts();
+ for (Product product : products) {
+ if (product.getItemCode().equalsIgnoreCase(itemCode))
+ return product;
+ }
+ return null;
+ }
+
protected List buildProducts() {
List products = new ArrayList<>();
products.add(new Product("item-1", "测试商品-1", "TwoStepsFromJava", 100));
diff --git a/hystrix-2/README.md b/hystrix-2/README.md
new file mode 100644
index 0000000..bbf8a8b
--- /dev/null
+++ b/hystrix-2/README.md
@@ -0,0 +1,6 @@
+# TwoStepsFromJava-Cloud-Feign
+
+Spring Cloud 示例项目:结合Ribbon和Feign实现声明式服务调用。
+
+
+Spring Cloud Release Trains: [Dalston.SR1](http://projects.spring.io/spring-cloud/)
\ No newline at end of file
diff --git a/hystrix-2/mall-web/pom.xml b/hystrix-2/mall-web/pom.xml
new file mode 100755
index 0000000..9e97fd5
--- /dev/null
+++ b/hystrix-2/mall-web/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ mall-web
+ Spring Cloud Sample Projects: Mall
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix-dashboard
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+ ${project.groupId}
+ product-service-api
+ ${project.version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/Application.java b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/Application.java
new file mode 100644
index 0000000..b7f8524
--- /dev/null
+++ b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/Application.java
@@ -0,0 +1,49 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * TwoStepsFromJava Cloud -- Mall Web Project
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableHystrixDashboard
+@EnableCircuitBreaker
+@EnableDiscoveryClient
+@SpringBootApplication
+public class Application {
+
+ @Bean
+ @LoadBalanced
+ RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
new file mode 100644
index 0000000..e9d33a5
--- /dev/null
+++ b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
@@ -0,0 +1,49 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.controller;
+
+import io.twostepsfromjava.cloud.product.dto.Product;
+import io.twostepsfromjava.cloud.web.mall.service.ProductService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.List;
+
+
+/**
+ * Product Controller
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/products")
+public class ProductController {
+ @Autowired
+ private ProductService productService;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public List list() {
+ return this.productService.findAll();
+ }
+
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.GET)
+ public Product detail(@PathVariable String itemCode) {
+ return this.productService.loadByItemCode(itemCode);
+ }
+}
diff --git a/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
new file mode 100644
index 0000000..4ddda9e
--- /dev/null
+++ b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
@@ -0,0 +1,37 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+import io.twostepsfromjava.cloud.product.dto.Product;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.util.List;
+
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public interface ProductService {
+
+ List findAll();
+
+ Product loadByItemCode(String itemCode);
+
+}
diff --git a/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/impl/ProductServiceImpl.java b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/impl/ProductServiceImpl.java
new file mode 100644
index 0000000..b254d16
--- /dev/null
+++ b/hystrix-2/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/impl/ProductServiceImpl.java
@@ -0,0 +1,59 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service.impl;
+
+import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
+import io.twostepsfromjava.cloud.product.dto.Product;
+import io.twostepsfromjava.cloud.web.mall.service.ProductService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@Service
+public class ProductServiceImpl implements ProductService {
+ @Autowired
+ private RestTemplate restTemplate;
+
+ @Override
+ @HystrixCommand(fallbackMethod = "findAllFallback")
+ public List findAll() {
+ return this.restTemplate.getForEntity("http://PRODUCT-SERVICE/products", List.class).getBody();
+ }
+
+ @Override
+ public Product loadByItemCode(String itemCode) {
+ return this.restTemplate.getForEntity("http://PRODUCT-SERVICE/products/" + itemCode, Product.class).getBody();
+ }
+
+ public List findAllFallback() {
+ List products = new ArrayList<>();
+ products.add(new Product("Failure-1", "固定商品-1", "Hystrix-Fallback", 100));
+ products.add(new Product("Failure-2", "固定商品-2", "Hystrix-Fallback", 100));
+ products.add(new Product("Failure-3", "固定商品-3", "Hystrix-Fallback", 100));
+ products.add(new Product("Failure-4", "固定商品-4", "Hystrix-Fallback", 100));
+ products.add(new Product("Failure-5", "固定商品-5", "Hystrix-Fallback", 100));
+ products.add(new Product("Failure-6", "固定商品-6", "Hystrix-Fallback", 100));
+ return products;
+ }
+}
diff --git a/hystrix-2/mall-web/src/main/resources/application.properties b/hystrix-2/mall-web/src/main/resources/application.properties
new file mode 100644
index 0000000..e0a190b
--- /dev/null
+++ b/hystrix-2/mall-web/src/main/resources/application.properties
@@ -0,0 +1,9 @@
+server.port=8080
+
+spring.application.name=MALL-WEB
+
+feign.hystrix.enabled=true
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/hystrix-2/mall-web/src/main/resources/banner.txt b/hystrix-2/mall-web/src/main/resources/banner.txt
new file mode 100644
index 0000000..2d4682f
--- /dev/null
+++ b/hystrix-2/mall-web/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Consumer ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/hystrix-2/mall-web/src/main/resources/logback.xml b/hystrix-2/mall-web/src/main/resources/logback.xml
new file mode 100644
index 0000000..d4b7206
--- /dev/null
+++ b/hystrix-2/mall-web/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+
+
+ logs/log-%d{yyyy-MM-dd}.%i.log
+
+
+ 64 MB
+
+
+
+
+
+ DEBUG
+
+
+ true
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
diff --git a/hystrix-2/parent/pom.xml b/hystrix-2/parent/pom.xml
new file mode 100644
index 0000000..84914e0
--- /dev/null
+++ b/hystrix-2/parent/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.2.RELEASE
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ Spring Cloud Sample Projects: Parent Pom
+ pom
+
+
+ UTF-8
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ Dalston.SR1
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+ 1.8
+ 1.8
+
+
+
+
+
\ No newline at end of file
diff --git a/hystrix-2/pom.xml b/hystrix-2/pom.xml
new file mode 100755
index 0000000..4b24942
--- /dev/null
+++ b/hystrix-2/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ parent
+
+
+ twostepsfromjava-clouds
+ 1.0.0-SNAPSHOT
+ Spring Cloud Sample Projects
+ pom
+
+
+ parent
+ service-discovery
+
+ product-service-api
+ product-service
+
+ mall-web
+
+ turbine-server
+
+
diff --git a/hystrix-2/product-service-api/pom.xml b/hystrix-2/product-service-api/pom.xml
new file mode 100755
index 0000000..8c8f494
--- /dev/null
+++ b/hystrix-2/product-service-api/pom.xml
@@ -0,0 +1,16 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ product-service-api
+ Spring Cloud Sample Projects: Product Service API
+
\ No newline at end of file
diff --git a/feign/product-service-api/src/main/java/io/twostepsfromjava/cloud/product/dto/Product.java b/hystrix-2/product-service-api/src/main/java/io/twostepsfromjava/cloud/product/dto/Product.java
similarity index 100%
rename from feign/product-service-api/src/main/java/io/twostepsfromjava/cloud/product/dto/Product.java
rename to hystrix-2/product-service-api/src/main/java/io/twostepsfromjava/cloud/product/dto/Product.java
diff --git a/hystrix-2/product-service/pom.xml b/hystrix-2/product-service/pom.xml
new file mode 100755
index 0000000..ad6aaf9
--- /dev/null
+++ b/hystrix-2/product-service/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ product-service
+ Spring Cloud Sample Projects: Product Service Server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+
+ ${project.groupId}
+ product-service-api
+ ${project.version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/hystrix-2/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/Application.java b/hystrix-2/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/Application.java
new file mode 100644
index 0000000..fd2772f
--- /dev/null
+++ b/hystrix-2/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/Application.java
@@ -0,0 +1,35 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.hello;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * TwoStepsFromJava Cloud -- Product Service 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableDiscoveryClient
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/hystrix-2/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/api/ProductEndpoint.java b/hystrix-2/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/api/ProductEndpoint.java
new file mode 100644
index 0000000..37667be
--- /dev/null
+++ b/hystrix-2/product-service/src/main/java/io/twostepsfromjava/cloud/service/hello/api/ProductEndpoint.java
@@ -0,0 +1,70 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.hello.api;
+
+import io.twostepsfromjava.cloud.product.dto.Product;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+
+/**
+ * Product API服务
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/products")
+public class ProductEndpoint {
+ protected Logger logger = LoggerFactory.getLogger(ProductEndpoint.class);
+
+ @RequestMapping(method = RequestMethod.GET)
+ public List list() {
+ try {
+ int sleepTime = new Random().nextInt(3000);
+ this.logger.debug("sleep time = {}ms", sleepTime);
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException ie) {
+ ie.printStackTrace();
+ }
+
+ return this.buildProducts();
+ }
+
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.GET)
+ public Product detail(@PathVariable String itemCode) {
+ List products = this.buildProducts();
+ for (Product product : products) {
+ if (product.getItemCode().equalsIgnoreCase(itemCode))
+ return product;
+ }
+ return null;
+ }
+
+ protected List buildProducts() {
+ List products = new ArrayList<>();
+ products.add(new Product("item-1", "测试商品-1", "TwoStepsFromJava", 100));
+ products.add(new Product("item-2", "测试商品-2", "TwoStepsFromJava", 200));
+ products.add(new Product("item-3", "测试商品-3", "TwoStepsFromJava", 300));
+ products.add(new Product("item-4", "测试商品-4", "TwoStepsFromJava", 400));
+ products.add(new Product("item-5", "测试商品-5", "TwoStepsFromJava", 500));
+ products.add(new Product("item-6", "测试商品-6", "TwoStepsFromJava", 600));
+ return products;
+ }
+}
diff --git a/hystrix-2/product-service/src/main/resources/application.properties b/hystrix-2/product-service/src/main/resources/application.properties
new file mode 100644
index 0000000..1d1bf34
--- /dev/null
+++ b/hystrix-2/product-service/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+server.port=2100
+
+spring.application.name=PRODUCT-SERVICE
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/hystrix-2/product-service/src/main/resources/banner.txt b/hystrix-2/product-service/src/main/resources/banner.txt
new file mode 100644
index 0000000..a692d74
--- /dev/null
+++ b/hystrix-2/product-service/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Product ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/hystrix-2/product-service/src/main/resources/logback.xml b/hystrix-2/product-service/src/main/resources/logback.xml
new file mode 100644
index 0000000..d4b7206
--- /dev/null
+++ b/hystrix-2/product-service/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+
+
+ logs/log-%d{yyyy-MM-dd}.%i.log
+
+
+ 64 MB
+
+
+
+
+
+ DEBUG
+
+
+ true
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
diff --git a/hystrix-2/service-discovery/pom.xml b/hystrix-2/service-discovery/pom.xml
new file mode 100755
index 0000000..c7040cc
--- /dev/null
+++ b/hystrix-2/service-discovery/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ service-discovery
+ Spring Cloud Sample Projects: Eureka Server
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka-server
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/hystrix-2/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java b/hystrix-2/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
new file mode 100644
index 0000000..31a533d
--- /dev/null
+++ b/hystrix-2/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
@@ -0,0 +1,35 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.discovery;
+
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+/**
+ * TwoStepsFromJava Cloud -- Service Discoery 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableEurekaServer
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(Application.class).web(true).run(args);
+ }
+
+}
diff --git a/hystrix-2/service-discovery/src/main/resources/application.properties b/hystrix-2/service-discovery/src/main/resources/application.properties
new file mode 100644
index 0000000..269e732
--- /dev/null
+++ b/hystrix-2/service-discovery/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+server.port=8260
+
+eureka.instance.hostname=localhost
+eureka.client.register-with-eureka=false
+eureka.client.fetch-registry=false
+eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/hystrix-2/service-discovery/src/main/resources/banner.txt b/hystrix-2/service-discovery/src/main/resources/banner.txt
new file mode 100644
index 0000000..e12a88a
--- /dev/null
+++ b/hystrix-2/service-discovery/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Discovery ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/hystrix-2/service-discovery/src/main/resources/logback.xml b/hystrix-2/service-discovery/src/main/resources/logback.xml
new file mode 100644
index 0000000..d4b7206
--- /dev/null
+++ b/hystrix-2/service-discovery/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+
+
+ logs/log-%d{yyyy-MM-dd}.%i.log
+
+
+ 64 MB
+
+
+
+
+
+ DEBUG
+
+
+ true
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
diff --git a/hystrix-2/turbine-server/pom.xml b/hystrix-2/turbine-server/pom.xml
new file mode 100755
index 0000000..ab2cd22
--- /dev/null
+++ b/hystrix-2/turbine-server/pom.xml
@@ -0,0 +1,36 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ turbine-server
+ Spring Cloud Sample Projects: Turbine Server
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-turbine
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/hystrix-2/turbine-server/src/main/java/io/twostepsfromjava/cloud/turbine/Application.java b/hystrix-2/turbine-server/src/main/java/io/twostepsfromjava/cloud/turbine/Application.java
new file mode 100644
index 0000000..02c472e
--- /dev/null
+++ b/hystrix-2/turbine-server/src/main/java/io/twostepsfromjava/cloud/turbine/Application.java
@@ -0,0 +1,37 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.turbine;
+
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.turbine.EnableTurbine;
+
+/**
+ * TwoStepsFromJava Cloud -- Turbine服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableDiscoveryClient
+@EnableTurbine
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(Application.class).web(true).run(args);
+ }
+
+}
diff --git a/hystrix-2/turbine-server/src/main/resources/application.properties b/hystrix-2/turbine-server/src/main/resources/application.properties
new file mode 100644
index 0000000..b4109a9
--- /dev/null
+++ b/hystrix-2/turbine-server/src/main/resources/application.properties
@@ -0,0 +1,12 @@
+server.port=8280
+management.port=8281
+
+spring.application.name=TURBINE
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+turbine.app-config=MALL-WEB
+turbine.cluster-name-expression="default"
+turbine.combine-host-port=true
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/hystrix-2/turbine-server/src/main/resources/banner.txt b/hystrix-2/turbine-server/src/main/resources/banner.txt
new file mode 100644
index 0000000..e12a88a
--- /dev/null
+++ b/hystrix-2/turbine-server/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Discovery ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/hystrix-2/turbine-server/src/main/resources/logback.xml b/hystrix-2/turbine-server/src/main/resources/logback.xml
new file mode 100644
index 0000000..d4b7206
--- /dev/null
+++ b/hystrix-2/turbine-server/src/main/resources/logback.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+
+
+ logs/log-%d{yyyy-MM-dd}.%i.log
+
+
+ 64 MB
+
+
+
+
+
+ DEBUG
+
+
+ true
+
+
+
+
+
+
+ [ %-5level] [%date{yyyy-MM-dd HH:mm:ss}] %logger{96} [%line] - %msg%n
+
+ UTF-8
+
+
+ DEBUG
+
+
+
+
+
+
+
+
+
diff --git a/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandHelloFailure.java b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandHelloFailure.java
new file mode 100644
index 0000000..484ec17
--- /dev/null
+++ b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandHelloFailure.java
@@ -0,0 +1,47 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+
+import com.netflix.hystrix.HystrixCommand;
+import com.netflix.hystrix.HystrixCommandGroupKey;
+import com.netflix.hystrix.HystrixCommandKey;
+import com.netflix.hystrix.HystrixRequestCache;
+import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategyDefault;
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+
+public class CommandHelloFailure extends HystrixCommand {
+ private String name;
+
+ public CommandHelloFailure(String name) {
+ super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")));
+ this.name = name;
+ }
+
+ @Override
+ protected String run() throws Exception {
+ return "Hello " + this.name + "!";
+ }
+
+ @Override
+ protected String getFallback() {
+ return "Hello Failure " + this.name + "!";
+ }
+}
diff --git a/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandThatFailsFast.java b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandThatFailsFast.java
new file mode 100644
index 0000000..573bef5
--- /dev/null
+++ b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandThatFailsFast.java
@@ -0,0 +1,48 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+
+import com.netflix.hystrix.HystrixCommand;
+import com.netflix.hystrix.HystrixCommandGroupKey;
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+
+public class CommandThatFailsFast extends HystrixCommand {
+ private final boolean throwException;
+
+ public CommandThatFailsFast(boolean throwException) {
+ super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
+ this.throwException = throwException;
+ }
+
+ @Override
+ protected String run() {
+ if (throwException) {
+ throw new RuntimeException("failure from CommandThatFailsFast");
+ } else {
+ return "success";
+ }
+ }
+
+ @Override
+ protected boolean shouldNotBeWrapped(Throwable underlying) {
+ return super.shouldNotBeWrapped(underlying);
+ }
+}
diff --git a/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandUsingRequestCache.java b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandUsingRequestCache.java
new file mode 100644
index 0000000..d157f11
--- /dev/null
+++ b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/CommandUsingRequestCache.java
@@ -0,0 +1,51 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+
+import com.netflix.hystrix.*;
+import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
+import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategyDefault;
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+
+public class CommandUsingRequestCache extends HystrixCommand {
+ private String name;
+
+ public CommandUsingRequestCache(String name) {
+ super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("HelloWorldGroup"))
+ .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld")));
+ this.name = name;
+ }
+
+ @Override
+ protected String run() throws Exception {
+ return this.name;
+ }
+
+ @Override
+ protected String getCacheKey() {
+ return this.name;
+ }
+
+ public void evictCache(String name) {
+ HystrixRequestCache.getInstance(HystrixCommandKey.Factory.asKey("HelloWorld"),
+ HystrixConcurrencyStrategyDefault.getInstance()).clear(name);
+ }
+}
diff --git a/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/HelloFailureService.java b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/HelloFailureService.java
new file mode 100644
index 0000000..48073ed
--- /dev/null
+++ b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/HelloFailureService.java
@@ -0,0 +1,35 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+
+public class HelloFailureService {
+
+ @HystrixCommand(groupKey = "ExampleGroup", fallbackMethod = "helloFallback")
+ public String hello(String name) {
+ return "Hello " + name + "!";
+ }
+
+ public String helloFallback(String name) {
+ return "Hello Failure " + name + "!";
+ }
+}
diff --git a/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ObservableCommandHelloFailure.java b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ObservableCommandHelloFailure.java
new file mode 100644
index 0000000..74e7f53
--- /dev/null
+++ b/hystrix/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ObservableCommandHelloFailure.java
@@ -0,0 +1,46 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+
+import com.netflix.hystrix.HystrixCommand;
+import com.netflix.hystrix.HystrixCommandGroupKey;
+import com.netflix.hystrix.HystrixObservableCommand;
+import rx.Observable;
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+
+public class ObservableCommandHelloFailure extends HystrixObservableCommand {
+ private String name;
+
+ public ObservableCommandHelloFailure(String name) {
+ super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")));
+ this.name = name;
+ }
+
+ @Override
+ protected Observable construct() {
+ return Observable.just("Hello " + this.name + "!");
+ }
+
+ @Override
+ protected Observable resumeWithFallback() {
+ return Observable.just("Hello Failure " + this.name + "!");
+ }
+}
diff --git a/stream/README.md b/stream/README.md
new file mode 100644
index 0000000..fc320dd
--- /dev/null
+++ b/stream/README.md
@@ -0,0 +1,6 @@
+# TwoStepsFromJava-Cloud-Stream
+
+Spring Cloud 示例项目:消息驱动式开发。
+
+
+Spring Cloud Release Trains: [Dalston.SR1](http://projects.spring.io/spring-cloud/)
\ No newline at end of file
diff --git a/stream/mall-web/pom.xml b/stream/mall-web/pom.xml
new file mode 100755
index 0000000..1c2e97e
--- /dev/null
+++ b/stream/mall-web/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ mall-web
+ MS Blog Projects(Stream): Mall Web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-ribbon
+
+
+ org.springframework.cloud
+ spring-cloud-starter-feign
+
+
+ org.springframework.cloud
+ spring-cloud-starter-hystrix
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-kafka
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/Application.java b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/Application.java
new file mode 100644
index 0000000..fcf6902
--- /dev/null
+++ b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/Application.java
@@ -0,0 +1,37 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.netflix.feign.EnableFeignClients;
+
+/**
+ * TwoStepsFromJava Cloud -- Mall Web Project
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableFeignClients
+@EnableDiscoveryClient
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
new file mode 100644
index 0000000..ed312d5
--- /dev/null
+++ b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/controller/ProductController.java
@@ -0,0 +1,48 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.controller;
+
+import io.twostepsfromjava.cloud.web.mall.dto.ProductDto;
+import io.twostepsfromjava.cloud.web.mall.service.ProductService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+
+/**
+ * Product Controller
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/products")
+public class ProductController {
+ @Autowired
+ private ProductService productService;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public List list() {
+ return this.productService.findAll();
+ }
+
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.GET)
+ public ProductDto detail(@PathVariable String itemCode) {
+ return this.productService.loadByItemCode(itemCode);
+ }
+}
diff --git a/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/dto/ProductDto.java b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/dto/ProductDto.java
new file mode 100644
index 0000000..d3da9c9
--- /dev/null
+++ b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/dto/ProductDto.java
@@ -0,0 +1,84 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.dto;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品信息DTO对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class ProductDto {
+ private static final long serialVersionUID = 1L;
+
+ // ========================================================================
+ // fields =================================================================
+ private String itemCode; // 商品货号
+ private String name; // 商品名称
+ private String bandName; // 商品品牌名称
+ private int price; // 商品价格(分)
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductDto() {
+ }
+
+ public ProductDto(String itemCode, String name, String bandName, int price) {
+ this.itemCode = itemCode;
+ this.name = name;
+ this.bandName = bandName;
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("itemCode", this.getItemCode())
+ .add("name", this.getName())
+ .add("bandName", this.getBandName())
+ .add("price", this.getPrice()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBandName() {
+ return bandName;
+ }
+ public void setBandName(String bandName) {
+ this.bandName = bandName;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+ public void setPrice(int price) {
+ this.price = price;
+ }
+}
diff --git a/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsg.java b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsg.java
new file mode 100644
index 0000000..51303a1
--- /dev/null
+++ b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsg.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.mq;
+
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品消息
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductMsg {
+ /** 消息类型:更新商品,值为: {@value} */
+ public static final String MA_UPDATE = "update";
+ /** 消息类型:删除商品,值为: {@value} */
+ public static final String MA_DELETE = "delete";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private String itemCode;
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductMsg() { }
+
+ public ProductMsg(String action, String itemCode) {
+ this.action = action;
+ this.itemCode = itemCode;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("itemCode", this.getItemCode()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+}
diff --git a/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsgListener.java b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsgListener.java
new file mode 100644
index 0000000..7c668e8
--- /dev/null
+++ b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/mq/ProductMsgListener.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.mq;
+
+
+import io.twostepsfromjava.cloud.web.mall.dto.ProductDto;
+import io.twostepsfromjava.cloud.web.mall.service.ProductService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.cloud.stream.annotation.StreamListener;
+import org.springframework.cloud.stream.messaging.Sink;
+
+
+/**
+ * 商品消息监听器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableBinding(Sink.class)
+public class ProductMsgListener {
+ protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ @Autowired
+ protected ProductService productService;
+
+ @StreamListener(Sink.INPUT)
+ public void onProductMsgSink(ProductMsg productMsg) {
+ if (ProductMsg.MA_UPDATE.equalsIgnoreCase(productMsg.getAction())) {
+ this.logger.debug("收到商品变更消息,商品货号: {}", productMsg.getItemCode());
+ // 重新获取该商品信息
+ ProductDto productDto = this.productService.loadByItemCode(productMsg.getItemCode());
+ if (null != productDto)
+ this.logger.debug("重新获取到的商品信息为:{}", productDto);
+ else
+ this.logger.debug("货号为:{} 的商品不存在", productMsg.getItemCode());
+ } else if (ProductMsg.MA_DELETE.equalsIgnoreCase(productMsg.getAction())) {
+ this.logger.debug("收到商品删除消息,所要删除商品货号为: {}", productMsg.getItemCode());
+ } else {
+ this.logger.debug("收到未知商品消息: {}", productMsg);
+ }
+ }
+}
diff --git a/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
new file mode 100644
index 0000000..b0c769a
--- /dev/null
+++ b/stream/mall-web/src/main/java/io/twostepsfromjava/cloud/web/mall/service/ProductService.java
@@ -0,0 +1,38 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.web.mall.service;
+
+import io.twostepsfromjava.cloud.web.mall.dto.ProductDto;
+import org.springframework.cloud.netflix.feign.FeignClient;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import java.util.List;
+
+
+/**
+ * Product Service
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@FeignClient("productservice")
+public interface ProductService {
+ @RequestMapping(value = "/products", method = RequestMethod.GET)
+ List findAll();
+
+ @RequestMapping(value = "/products/{itemCode}", method = RequestMethod.GET)
+ ProductDto loadByItemCode(@PathVariable("itemCode") String itemCode);
+}
diff --git a/stream/mall-web/src/main/resources/application.properties b/stream/mall-web/src/main/resources/application.properties
new file mode 100644
index 0000000..f76d718
--- /dev/null
+++ b/stream/mall-web/src/main/resources/application.properties
@@ -0,0 +1,18 @@
+server.port=8080
+
+spring.application.name=MALL-WEB
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
+logging.level.io.twostepsfromjava=DEBUG
+
+# =====================================================================================================================
+# == stream / kafka ==
+# =====================================================================================================================
+spring.cloud.stream.bindings.input.destination=twostepsfromjava-cloud-producttopic
+spring.cloud.stream.bindings.input.content-type=application/json
+spring.cloud.stream.bindings.input.group=mallWebGroup
+spring.cloud.stream.kafka.binder.brokers=localhost
+spring.cloud.stream.kafka.binder.defaultBrokerPort=9092
+spring.cloud.stream.kafka.binder.zkNodes=localhost
\ No newline at end of file
diff --git a/stream/mall-web/src/main/resources/banner.txt b/stream/mall-web/src/main/resources/banner.txt
new file mode 100644
index 0000000..2d4682f
--- /dev/null
+++ b/stream/mall-web/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Consumer ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/stream/parent/pom.xml b/stream/parent/pom.xml
new file mode 100644
index 0000000..118f600
--- /dev/null
+++ b/stream/parent/pom.xml
@@ -0,0 +1,56 @@
+
+
+ 4.0.0
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.2.RELEASE
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ MS Blog Projects(Stream): Parent Pom
+ pom
+
+
+ UTF-8
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ Dalston.SR3
+ pom
+ import
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.5.1
+
+ 1.8
+ 1.8
+
+
+
+
+
\ No newline at end of file
diff --git a/stream/pom.xml b/stream/pom.xml
new file mode 100755
index 0000000..0552fe8
--- /dev/null
+++ b/stream/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ parent
+
+
+ twostepsfromjava-clouds
+ 1.0.0-SNAPSHOT
+ MS Blog Projects -- Stream
+ pom
+
+
+ parent
+ service-discovery
+
+ product-service
+ user-service
+
+ mall-web
+
+
diff --git a/stream/product-service/pom.xml b/stream/product-service/pom.xml
new file mode 100755
index 0000000..3f0ce03
--- /dev/null
+++ b/stream/product-service/pom.xml
@@ -0,0 +1,40 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ product-service
+ MS Blog Projects(Stream): Product Service Server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+ org.springframework.cloud
+ spring-cloud-starter-stream-kafka
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/stream/product-service/src/main/java/io/twostepsfromjava/cloud/Application.java b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/Application.java
new file mode 100644
index 0000000..56b1480
--- /dev/null
+++ b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/Application.java
@@ -0,0 +1,38 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.cloud.stream.messaging.Source;
+
+/**
+ * TwoStepsFromJava Cloud -- ProductDto Service 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableDiscoveryClient
+@EnableBinding(Source.class)
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/api/ProductEndpoint.java b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/api/ProductEndpoint.java
new file mode 100644
index 0000000..be39d8d
--- /dev/null
+++ b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/api/ProductEndpoint.java
@@ -0,0 +1,59 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.api;
+
+import io.twostepsfromjava.cloud.product.dto.ProductDto;
+import io.twostepsfromjava.cloud.product.service.ProductService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+
+/**
+ * ProductDto API服务
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/products")
+public class ProductEndpoint {
+ protected Logger logger = LoggerFactory.getLogger(ProductEndpoint.class);
+
+ @Autowired
+ ProductService productService;
+
+ @RequestMapping(method = RequestMethod.GET)
+ public List list() {
+ return this.productService.findAll();
+ }
+
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.GET)
+ public ProductDto detail(@PathVariable String itemCode) {
+ return this.productService.findOne(itemCode);
+ }
+
+ // FIXME: 该端点仅仅是用来测试消息发送,并不包含任何业务逻辑处理
+ @RequestMapping(value = "/{itemCode}", method = RequestMethod.POST)
+ public ProductDto save(@PathVariable String itemCode) {
+ ProductDto productDto = this.productService.findOne(itemCode);
+ if (null != productDto) {
+ this.productService.save(productDto);
+ }
+ return productDto;
+ }
+}
diff --git a/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/dto/ProductDto.java b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/dto/ProductDto.java
new file mode 100644
index 0000000..500fe43
--- /dev/null
+++ b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/dto/ProductDto.java
@@ -0,0 +1,84 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.dto;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品信息DTO对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class ProductDto {
+ private static final long serialVersionUID = 1L;
+
+ // ========================================================================
+ // fields =================================================================
+ private String itemCode; // 商品货号
+ private String name; // 商品名称
+ private String bandName; // 商品品牌名称
+ private int price; // 商品价格(分)
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductDto() {
+ }
+
+ public ProductDto(String itemCode, String name, String bandName, int price) {
+ this.itemCode = itemCode;
+ this.name = name;
+ this.bandName = bandName;
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("itemCode", this.getItemCode())
+ .add("name", this.getName())
+ .add("bandName", this.getBandName())
+ .add("price", this.getPrice()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBandName() {
+ return bandName;
+ }
+ public void setBandName(String bandName) {
+ this.bandName = bandName;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+ public void setPrice(int price) {
+ this.price = price;
+ }
+}
diff --git a/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/entity/Product.java b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/entity/Product.java
new file mode 100644
index 0000000..ca56fce
--- /dev/null
+++ b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/entity/Product.java
@@ -0,0 +1,84 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.entity;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品信息实体对象
+ *
+ * @author CD826(CD826Dong@gamil.com)
+ * @since 1.0.0
+ */
+public class Product {
+ private static final long serialVersionUID = 1L;
+
+ // ========================================================================
+ // fields =================================================================
+ private String itemCode; // 商品货号
+ private String name; // 商品名称
+ private String bandName; // 商品品牌名称
+ private int price; // 商品价格(分)
+
+ // ========================================================================
+ // constructor ============================================================
+ public Product() {
+ }
+
+ public Product(String itemCode, String name, String bandName, int price) {
+ this.itemCode = itemCode;
+ this.name = name;
+ this.bandName = bandName;
+ this.price = price;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("itemCode", this.getItemCode())
+ .add("name", this.getName())
+ .add("bandName", this.getBandName())
+ .add("price", this.getPrice()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getBandName() {
+ return bandName;
+ }
+ public void setBandName(String bandName) {
+ this.bandName = bandName;
+ }
+
+ public int getPrice() {
+ return price;
+ }
+ public void setPrice(int price) {
+ this.price = price;
+ }
+}
diff --git a/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/mq/ProductMsg.java b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/mq/ProductMsg.java
new file mode 100644
index 0000000..4d18bf7
--- /dev/null
+++ b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/mq/ProductMsg.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.mq;
+
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * 商品消息
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+public class ProductMsg {
+ /** 消息类型:更新商品,值为: {@value} */
+ public static final String MA_UPDATE = "update";
+ /** 消息类型:删除商品,值为: {@value} */
+ public static final String MA_DELETE = "delete";
+
+ // ========================================================================
+ // fields =================================================================
+ private String action;
+ private String itemCode;
+
+ // ========================================================================
+ // constructor ============================================================
+ public ProductMsg() { }
+
+ public ProductMsg(String action, String itemCode) {
+ this.action = action;
+ this.itemCode = itemCode;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("action", this.getAction())
+ .add("itemCode", this.getItemCode()).toString();
+ }
+
+ // ==================================================================
+ // setter/getter ====================================================
+ public String getAction() {
+ return action;
+ }
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public String getItemCode() {
+ return itemCode;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+}
diff --git a/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/service/ProductService.java b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/service/ProductService.java
new file mode 100644
index 0000000..29a1826
--- /dev/null
+++ b/stream/product-service/src/main/java/io/twostepsfromjava/cloud/product/service/ProductService.java
@@ -0,0 +1,115 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.product.service;
+
+import io.twostepsfromjava.cloud.product.dto.ProductDto;
+import io.twostepsfromjava.cloud.product.mq.ProductMsg;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.stream.messaging.Source;
+import org.springframework.messaging.support.MessageBuilder;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * 商品服务
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@Service
+public class ProductService {
+ protected Logger logger = LoggerFactory.getLogger(ProductService.class);
+
+ private Source source;
+ private List productList;
+
+ @Autowired
+ public ProductService(Source source) {
+ this.source = source;
+ this.productList = this.buildProducts();
+ }
+
+ /**
+ * 获取商品列表
+ * @return
+ */
+ public List findAll() {
+ return this.productList;
+ }
+
+ /**
+ * 根据ItemCode获取
+ * @param itemCode
+ * @return
+ */
+ public ProductDto findOne(String itemCode) {
+ for (ProductDto productDto : this.productList) {
+ if (productDto.getItemCode().equalsIgnoreCase(itemCode))
+ return productDto;
+ }
+
+ return null;
+ }
+
+ /**
+ * 保存或更新商品信息
+ * @param productDto
+ * @return
+ */
+ public ProductDto save(ProductDto productDto) {
+ // TODO: 实现商品保存处理
+ for (ProductDto sourceProductDto : this.productList) {
+ if (sourceProductDto.getItemCode().equalsIgnoreCase(productDto.getItemCode())) {
+ sourceProductDto.setName(sourceProductDto.getName() + "-new");
+ sourceProductDto.setPrice(sourceProductDto.getPrice() + 100);
+ productDto = sourceProductDto;
+ break;
+ }
+ }
+
+ // 发送商品消息
+ this.sendMsg(ProductMsg.MA_UPDATE, productDto.getItemCode());
+
+ return productDto;
+ }
+
+ /**
+ * 具体消息发送的实现
+ * @param msgAction 消息类型
+ * @param itemCode 商品货号
+ */
+ protected void sendMsg(String msgAction, String itemCode) {
+ ProductMsg productMsg = new ProductMsg(msgAction, itemCode);
+ this.logger.debug("发送商品消息:{} ", productMsg);
+
+ // 发送消息
+ this.source.output().send(MessageBuilder.withPayload(productMsg).build());
+ }
+
+ protected List buildProducts() {
+ List products = new ArrayList<>();
+ products.add(new ProductDto("item-1", "测试商品-1", "TwoStepsFromJava", 100));
+ products.add(new ProductDto("item-2", "测试商品-2", "TwoStepsFromJava", 200));
+ products.add(new ProductDto("item-3", "测试商品-3", "TwoStepsFromJava", 300));
+ products.add(new ProductDto("item-4", "测试商品-4", "TwoStepsFromJava", 400));
+ products.add(new ProductDto("item-5", "测试商品-5", "TwoStepsFromJava", 500));
+ products.add(new ProductDto("item-6", "测试商品-6", "TwoStepsFromJava", 600));
+ return products;
+ }
+}
diff --git a/stream/product-service/src/main/resources/application.properties b/stream/product-service/src/main/resources/application.properties
new file mode 100644
index 0000000..55a76e8
--- /dev/null
+++ b/stream/product-service/src/main/resources/application.properties
@@ -0,0 +1,17 @@
+server.port=2100
+
+spring.application.name=productservice
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
+logging.level.io.twostepsfromjava=DEBUG
+
+# =====================================================================================================================
+# == stream / kafka ==
+# =====================================================================================================================
+spring.cloud.stream.bindings.output.destination=twostepsfromjava-cloud-producttopic
+spring.cloud.stream.bindings.output.content-type=application/json
+spring.cloud.stream.kafka.binder.brokers=localhost
+spring.cloud.stream.kafka.binder.defaultBrokerPort=9092
+spring.cloud.stream.kafka.binder.zkNodes=localhost
\ No newline at end of file
diff --git a/stream/product-service/src/main/resources/banner.txt b/stream/product-service/src/main/resources/banner.txt
new file mode 100644
index 0000000..a692d74
--- /dev/null
+++ b/stream/product-service/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Product ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/stream/service-discovery/pom.xml b/stream/service-discovery/pom.xml
new file mode 100755
index 0000000..56771c3
--- /dev/null
+++ b/stream/service-discovery/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ service-discovery
+ MS Blog Projects(Stream): Eureka Server
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka-server
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/stream/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java b/stream/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
new file mode 100644
index 0000000..31a533d
--- /dev/null
+++ b/stream/service-discovery/src/main/java/io/twostepsfromjava/cloud/service/discovery/Application.java
@@ -0,0 +1,35 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.discovery;
+
+
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
+
+/**
+ * TwoStepsFromJava Cloud -- Service Discoery 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableEurekaServer
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(Application.class).web(true).run(args);
+ }
+
+}
diff --git a/stream/service-discovery/src/main/resources/application.properties b/stream/service-discovery/src/main/resources/application.properties
new file mode 100644
index 0000000..269e732
--- /dev/null
+++ b/stream/service-discovery/src/main/resources/application.properties
@@ -0,0 +1,8 @@
+server.port=8260
+
+eureka.instance.hostname=localhost
+eureka.client.register-with-eureka=false
+eureka.client.fetch-registry=false
+eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/stream/service-discovery/src/main/resources/banner.txt b/stream/service-discovery/src/main/resources/banner.txt
new file mode 100644
index 0000000..e12a88a
--- /dev/null
+++ b/stream/service-discovery/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- Discovery ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file
diff --git a/stream/user-service/pom.xml b/stream/user-service/pom.xml
new file mode 100755
index 0000000..50e85ee
--- /dev/null
+++ b/stream/user-service/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+
+ twostepsfromjava.cloud
+ twostepsfromjava-cloud-parent
+ 1.0.0-SNAPSHOT
+ ../parent
+
+
+ user-service
+ MS Blog Projects(Stream): User Service Server
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+
+ ${project.groupId}
+ service-api
+ ${project.version}
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
\ No newline at end of file
diff --git a/stream/user-service/src/main/java/io/twostepsfromjava/cloud/service/user/Application.java b/stream/user-service/src/main/java/io/twostepsfromjava/cloud/service/user/Application.java
new file mode 100644
index 0000000..53bd46c
--- /dev/null
+++ b/stream/user-service/src/main/java/io/twostepsfromjava/cloud/service/user/Application.java
@@ -0,0 +1,35 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.user;
+
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * TwoStepsFromJava Cloud -- User Service 服务器
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@EnableDiscoveryClient
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/stream/user-service/src/main/java/io/twostepsfromjava/cloud/service/user/api/UserEndpoint.java b/stream/user-service/src/main/java/io/twostepsfromjava/cloud/service/user/api/UserEndpoint.java
new file mode 100644
index 0000000..b1bdf74
--- /dev/null
+++ b/stream/user-service/src/main/java/io/twostepsfromjava/cloud/service/user/api/UserEndpoint.java
@@ -0,0 +1,42 @@
+/***
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.twostepsfromjava.cloud.service.user.api;
+
+import io.twostepsfromjava.cloud.user.dto.User;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+
+/**
+ * User API服务
+ *
+ * @author CD826(CD826Dong@gmail.com)
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/users")
+public class UserEndpoint {
+ protected Logger logger = LoggerFactory.getLogger(UserEndpoint.class);
+
+ @Value("${server.port:2200}")
+ private int serverPort = 2200;
+
+ @RequestMapping(value = "/{loginName}", method = RequestMethod.GET)
+ public User detail(@PathVariable String loginName) {
+ String memos = "I come form " + this.serverPort;
+ return new User(loginName, loginName, "/avatar/default.png", memos);
+ }
+}
diff --git a/stream/user-service/src/main/resources/application.properties b/stream/user-service/src/main/resources/application.properties
new file mode 100644
index 0000000..f015575
--- /dev/null
+++ b/stream/user-service/src/main/resources/application.properties
@@ -0,0 +1,7 @@
+server.port=2200
+
+spring.application.name=USER-SERVICE
+
+eureka.client.service-url.defaultZone=http://localhost:8260/eureka
+
+logging.level.org.springframework=INFO
\ No newline at end of file
diff --git a/stream/user-service/src/main/resources/banner.txt b/stream/user-service/src/main/resources/banner.txt
new file mode 100644
index 0000000..6d6d6bb
--- /dev/null
+++ b/stream/user-service/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+=======================================================================================================================
+== ==
+== ==
+== _______ _____ ______ _ _____ _ ____ _ _ _____ ==
+== |__ __|/ ____|| ____| | | / ____|| | / __ \ | | | || __ \ ==
+== | | | (___ | |__ | | ______ | | | | | | | || | | || | | | ==
+== | | \___ \ | __|_ | ||______|| | | | | | | || | | || | | | ==
+== | | ____) || | | |__| | | |____ | |____| |__| || |__| || |__| | ==
+== |_| |_____/ |_| \____/ \_____||______|\____/ \____/ |_____/ -- User ==
+== ==
+== ==
+=======================================================================================================================
+:: twostepsfromjava.io :: v1.0.0.BUILD-SNAPSHOT BUILD-BY: CD826
\ No newline at end of file