From bd7cc53b50f7c9092b63404db74a490495667e55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com> Date: Thu, 17 Jan 2019 17:58:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20spring=20cloud=20=E7=94=A8?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pictures/zipkin-detail.png | Bin 0 -> 52810 bytes pictures/zipkin.png | Bin 0 -> 47872 bytes .../spring-cloud-sleuth-zipkin/README.md | 8 ++ .../spring-cloud-sleuth-zipkin/common/pom.xml | 22 +++++ .../heibaiying/common/CommonApplication.java | 14 +++ .../com/heibaiying/common/bean/Product.java | 33 +++++++ .../heibaiying/common/feign/ProductFeign.java | 27 ++++++ .../common/CommonApplicationTests.java | 17 ++++ .../consumer/pom.xml | 55 ++++++++++++ .../consumer/ConsumerApplication.java | 18 ++++ .../consumer/config/FeignConfig.java | 20 +++++ .../consumer/controller/SellController.java | 48 +++++++++++ .../consumer/feign/CProductFeign.java | 15 ++++ .../feign/impl/CProductFeignImpl.java | 31 +++++++ .../src/main/resources/application.yml | 18 ++++ .../src/main/resources/templates/product.ftl | 15 ++++ .../src/main/resources/templates/products.ftl | 24 ++++++ .../consumer/ConsumerApplicationTests.java | 17 ++++ .../spring-cloud-sleuth-zipkin/eureka/pom.xml | 31 +++++++ .../heibaiying/eureka/EurekaApplication.java | 16 ++++ .../eureka/src/main/resources/application.yml | 12 +++ .../eureka/EurekaApplicationTests.java | 17 ++++ .../spring-cloud-sleuth-zipkin/pom.xml | 64 ++++++++++++++ .../producer/pom.xml | 48 +++++++++++ .../producer/ProducerApplication.java | 16 ++++ .../controller/ProducerController.java | 35 ++++++++ .../producer/service/IProductService.java | 13 +++ .../producer/service/impl/ProductService.java | 44 ++++++++++ .../src/main/resources/application.yml | 13 +++ .../producer/ProducerApplicationTests.java | 17 ++++ .../spring-cloud-sleuth-zipkin/zuul/pom.xml | 74 ++++++++++++++++ .../com/heibaiying/zuul/ZuulApplication.java | 18 ++++ .../config/CustomZuulFallbackProvider.java | 81 ++++++++++++++++++ .../zuul/controller/LoginController.java | 26 ++++++ .../zuul/filter/CustomZuulFilter.java | 71 +++++++++++++++ .../zuul/src/main/resources/application.yml | 25 ++++++ .../src/main/resources/templates/index.ftl | 12 +++ .../heibaiying/zuul/ZuulApplicationTests.java | 17 ++++ spring-cloud/spring-cloud-stream/pom.xml | 72 ++++++++++++++++ .../stream/SpringCloudStreamApplication.java | 14 +++ .../heibaiying/stream/bean/Programmer.java | 23 +++++ .../stream/controller/MessageController.java | 78 +++++++++++++++++ .../com/heibaiying/stream/stream/Custom.java | 22 +++++ .../stream/stream/StreamReceived.java | 62 ++++++++++++++ .../src/main/resources/application.yml | 6 ++ .../SpringCloudStreamApplicationTests.java | 17 ++++ 46 files changed, 1326 insertions(+) create mode 100644 pictures/zipkin-detail.png create mode 100644 pictures/zipkin.png create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/README.md create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/common/pom.xml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/CommonApplication.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/bean/Product.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/common/src/test/java/com/heibaiying/common/CommonApplicationTests.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/pom.xml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/ConsumerApplication.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/config/FeignConfig.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/controller/SellController.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/CProductFeign.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/application.yml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/product.ftl create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/products.ftl create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/test/java/com/heibaiying/consumer/ConsumerApplicationTests.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/eureka/pom.xml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/java/com/heibaiying/eureka/EurekaApplication.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/resources/application.yml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/test/java/com/heibaiying/eureka/EurekaApplicationTests.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/pom.xml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/producer/pom.xml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/ProducerApplication.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/controller/ProducerController.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/IProductService.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/impl/ProductService.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/resources/application.yml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/producer/src/test/java/com/heibaiying/producer/ProducerApplicationTests.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/pom.xml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/ZuulApplication.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/config/CustomZuulFallbackProvider.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/controller/LoginController.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/filter/CustomZuulFilter.java create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/application.yml create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/templates/index.ftl create mode 100644 spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/test/java/com/heibaiying/zuul/ZuulApplicationTests.java create mode 100644 spring-cloud/spring-cloud-stream/pom.xml create mode 100644 spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/SpringCloudStreamApplication.java create mode 100644 spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/bean/Programmer.java create mode 100644 spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/controller/MessageController.java create mode 100644 spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/Custom.java create mode 100644 spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/StreamReceived.java create mode 100644 spring-cloud/spring-cloud-stream/src/main/resources/application.yml create mode 100644 spring-cloud/spring-cloud-stream/src/test/java/com/heibaiying/stream/SpringCloudStreamApplicationTests.java diff --git a/pictures/zipkin-detail.png b/pictures/zipkin-detail.png new file mode 100644 index 0000000000000000000000000000000000000000..61a92598fe6dde04bbe53949010d5ca670ecd5fd GIT binary patch literal 52810 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

=64moR|OAqzr$l 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 r_yTF&VtVY`T>okv#x}67Y9Sn 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

&9&tDd5O}Mcn`{f+n3588M(}+5z;#e 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 + + 4.0.0 + + + com.heibaiying.sleuth.zipkin + spring-cloud-sleuth-zipkin + 0.0.1-SNAPSHOT + + + common + + + + org.springframework.boot + spring-boot-starter-web + + + + + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/CommonApplication.java b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/CommonApplication.java new file mode 100644 index 0000000..3675fb8 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/CommonApplication.java @@ -0,0 +1,14 @@ +package com.heibaiying.common; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class CommonApplication { + + public static void main(String[] args) { + SpringApplication.run(CommonApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/bean/Product.java b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/bean/Product.java new file mode 100644 index 0000000..75c3f5b --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/bean/Product.java @@ -0,0 +1,33 @@ +package com.heibaiying.common.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +/** + * @author : heibaiying + * @description : 产品实体类 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Product implements Serializable { + + // 产品序列号 + private long id; + + // 产品名称 + private String name; + + // 是否贵重品 + private Boolean isPrecious; + + //生产日期 + private Date dateInProduced; + + //产品价格 + private float price; +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java new file mode 100644 index 0000000..ddcb2e3 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java @@ -0,0 +1,27 @@ +package com.heibaiying.common.feign; + +import com.heibaiying.common.bean.Product; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author : heibaiying + * @description : 声明式接口调用 + */ +public interface ProductFeign { + + @GetMapping("products") + List productList(); + + /** + * 这是需要强调的是使用feign时候@PathVariable一定要用value指明参数, + * 不然会抛出.IllegalStateException: PathVariable annotation was empty on param 异常 + */ + @GetMapping("product/{id}") + Product productDetail(@PathVariable(value = "id") int id); + + + @PostMapping("product") + void save(@RequestBody Product product); +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/common/src/test/java/com/heibaiying/common/CommonApplicationTests.java b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/test/java/com/heibaiying/common/CommonApplicationTests.java new file mode 100644 index 0000000..b02d448 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/common/src/test/java/com/heibaiying/common/CommonApplicationTests.java @@ -0,0 +1,17 @@ +package com.heibaiying.common; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class CommonApplicationTests { + + @Test + public void contextLoads() { + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/pom.xml b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/pom.xml new file mode 100644 index 0000000..966f514 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + + + com.heibaiying.sleuth.zipkin + spring-cloud-sleuth-zipkin + 0.0.1-SNAPSHOT + + + consumer + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + org.springframework.boot + spring-boot-starter-freemarker + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + com.heibaiying.sleuth.zipkin + common + 0.0.1-SNAPSHOT + compile + + + + org.springframework.cloud + spring-cloud-starter-zipkin + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/ConsumerApplication.java b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/ConsumerApplication.java new file mode 100644 index 0000000..8116bec --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/ConsumerApplication.java @@ -0,0 +1,18 @@ +package com.heibaiying.consumer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; + +@SpringBootApplication +@EnableDiscoveryClient +@EnableFeignClients +public class ConsumerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConsumerApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/config/FeignConfig.java b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/config/FeignConfig.java new file mode 100644 index 0000000..e0ba1cc --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/config/FeignConfig.java @@ -0,0 +1,20 @@ +package com.heibaiying.consumer.config; + +import feign.Retryer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import static java.util.concurrent.TimeUnit.SECONDS; + +/** + * @author : heibaiying + * @description : feign 配置 + */ +@Configuration +public class FeignConfig { + + @Bean + public Retryer retryer(){ + //重试间隔为 100ms,最大重试时间为 1s, 重试次数为 5 次 + return new Retryer.Default(100,SECONDS.toMillis(1),5); + } +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/controller/SellController.java b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/controller/SellController.java new file mode 100644 index 0000000..88cf933 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/controller/SellController.java @@ -0,0 +1,48 @@ +package com.heibaiying.consumer.controller; + + +import com.heibaiying.common.bean.Product; +import com.heibaiying.consumer.feign.CProductFeign; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author : heibaiying + */ +@Controller +@RequestMapping("sell") +public class SellController { + + @Autowired + private CProductFeign cproductFeign; + + @GetMapping("products") + public String productList(Model model) { + List products = cproductFeign.productList(); + model.addAttribute("products", products); + return "products"; + } + + + @GetMapping("product/{id}") + public String productDetail(@PathVariable int id, Model model) { + Product product = cproductFeign.productDetail(id); + model.addAttribute("product", product); + return "product"; + } + + + @PostMapping("product") + public String save(@RequestParam String productName) { + long id = Math.round(Math.random() * 100); + Product product = new Product(id, productName, false, new Date(), 88); + cproductFeign.save(product); + return "redirect:products"; + } +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/CProductFeign.java b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/CProductFeign.java new file mode 100644 index 0000000..9dcbff5 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/CProductFeign.java @@ -0,0 +1,15 @@ +package com.heibaiying.consumer.feign; + +import com.heibaiying.common.feign.ProductFeign; +import com.heibaiying.consumer.config.FeignConfig; +import com.heibaiying.consumer.feign.impl.CProductFeignImpl; +import org.springframework.cloud.openfeign.FeignClient; + +/** + * @author : heibaiying + * @description : 声明式接口调用 + */ +@FeignClient(value = "producer",configuration = FeignConfig.class,fallback = CProductFeignImpl.class) +public interface CProductFeign extends ProductFeign { + +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java new file mode 100644 index 0000000..8196a8e --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java @@ -0,0 +1,31 @@ +package com.heibaiying.consumer.feign.impl; + +import com.heibaiying.common.bean.Product; +import com.heibaiying.consumer.feign.CProductFeign; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author : heibaiying + * @description : 定义发生错误时候的熔断处理。除了继承自CProductFeign,还需要用@Component声明为spring的组件 + */ +@Component +public class CProductFeignImpl implements CProductFeign { + + @Override + public List productList() { + return new ArrayList<>(); + } + + @Override + public Product productDetail(int id) { + return null; + } + + @Override + public void save(Product product) { + + } +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/application.yml b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/application.yml new file mode 100644 index 0000000..c7d0fdc --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/application.yml @@ -0,0 +1,18 @@ +server: + port: 8080 +# 指定服务命名 +spring: + application: + name: consumer + # 指定zipkin地址 默认就是http://localhost:9411/ + zipkin: + base-url: http://localhost:9411/ +# 指定注册中心地址 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ +feign: + hystrix: + # 如果为true,则OpenFign客户端将使用Hystrix断路器进行封装 默认为false + enabled: true \ No newline at end of file diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/product.ftl b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/product.ftl new file mode 100644 index 0000000..729f516 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/product.ftl @@ -0,0 +1,15 @@ + + + + 产品详情 + + +

+ + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/products.ftl b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/products.ftl new file mode 100644 index 0000000..c83dc5d --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/main/resources/templates/products.ftl @@ -0,0 +1,24 @@ + + + + 产品列表 + + +

产品列表:点击查看详情

+
+ + +
+
+ + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/test/java/com/heibaiying/consumer/ConsumerApplicationTests.java b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/test/java/com/heibaiying/consumer/ConsumerApplicationTests.java new file mode 100644 index 0000000..82f5399 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/consumer/src/test/java/com/heibaiying/consumer/ConsumerApplicationTests.java @@ -0,0 +1,17 @@ +package com.heibaiying.consumer; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ConsumerApplicationTests { + + @Test + public void contextLoads() { + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/eureka/pom.xml b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/pom.xml new file mode 100644 index 0000000..e126c96 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + + com.heibaiying.sleuth.zipkin + spring-cloud-sleuth-zipkin + 0.0.1-SNAPSHOT + + + eureka + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-server + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/java/com/heibaiying/eureka/EurekaApplication.java b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/java/com/heibaiying/eureka/EurekaApplication.java new file mode 100644 index 0000000..bd54938 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/java/com/heibaiying/eureka/EurekaApplication.java @@ -0,0 +1,16 @@ +package com.heibaiying.eureka; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; + +@SpringBootApplication +@EnableEurekaServer +public class EurekaApplication { + + public static void main(String[] args) { + SpringApplication.run(EurekaApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/resources/application.yml b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/resources/application.yml new file mode 100644 index 0000000..817356d --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/main/resources/application.yml @@ -0,0 +1,12 @@ +server: + port: 8010 +eureka: + instance: + hostname: localhost + client: + # 设置为false,代表不向注册中心注册自己 + register-with-eureka: false + # 注册中心主要用于维护服务,并不需要检索服务,所以设置为false + fetch-registry: false + serviceUrl: + defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ \ No newline at end of file diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/test/java/com/heibaiying/eureka/EurekaApplicationTests.java b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/test/java/com/heibaiying/eureka/EurekaApplicationTests.java new file mode 100644 index 0000000..b3e2d73 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/eureka/src/test/java/com/heibaiying/eureka/EurekaApplicationTests.java @@ -0,0 +1,17 @@ +package com.heibaiying.eureka; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class EurekaApplicationTests { + + @Test + public void contextLoads() { + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/pom.xml b/spring-cloud/spring-cloud-sleuth-zipkin/pom.xml new file mode 100644 index 0000000..961a97c --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/pom.xml @@ -0,0 +1,64 @@ + + + 4.0.0 + pom + + + org.springframework.boot + spring-boot-starter-parent + 2.1.2.RELEASE + + + + com.heibaiying.sleuth.zipkin + spring-cloud-sleuth-zipkin + 0.0.1-SNAPSHOT + spring-cloud-zuul + zuul project for Spring Boot + + + eureka + common + consumer + producer + + + + 1.8 + Finchley.SR2 + + + + + org.springframework.boot + spring-boot-starter + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/producer/pom.xml b/spring-cloud/spring-cloud-sleuth-zipkin/producer/pom.xml new file mode 100644 index 0000000..eda5f83 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/producer/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + + com.heibaiying.sleuth.zipkin + spring-cloud-sleuth-zipkin + 0.0.1-SNAPSHOT + + + producer + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + com.heibaiying.sleuth.zipkin + common + 0.0.1-SNAPSHOT + compile + + + + org.springframework.cloud + spring-cloud-starter-zipkin + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/ProducerApplication.java b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/ProducerApplication.java new file mode 100644 index 0000000..cb8e8fc --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/ProducerApplication.java @@ -0,0 +1,16 @@ +package com.heibaiying.producer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class ProducerApplication { + + public static void main(String[] args) { + SpringApplication.run(ProducerApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/controller/ProducerController.java b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/controller/ProducerController.java new file mode 100644 index 0000000..7827491 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/controller/ProducerController.java @@ -0,0 +1,35 @@ +package com.heibaiying.producer.controller; + + +import com.heibaiying.common.bean.Product; +import com.heibaiying.common.feign.ProductFeign; +import com.heibaiying.producer.service.IProductService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * @author : heibaiying + */ +@RestController +public class ProducerController implements ProductFeign { + + @Autowired + private IProductService productService; + + @GetMapping("products") + public List productList() { + return productService.queryAllProducts(); + } + + @GetMapping("product/{id}") + public Product productDetail(@PathVariable int id) { + return productService.queryProductById(id); + } + + @PostMapping("product") + public void save(@RequestBody Product product) { + productService.saveProduct(product); + } +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/IProductService.java b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/IProductService.java new file mode 100644 index 0000000..0a55013 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/IProductService.java @@ -0,0 +1,13 @@ +package com.heibaiying.producer.service; + +import com.heibaiying.common.bean.Product; + +import java.util.List; +public interface IProductService { + + Product queryProductById(int id) ; + + List queryAllProducts(); + + void saveProduct(Product product); +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/impl/ProductService.java b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/impl/ProductService.java new file mode 100644 index 0000000..caef1cf --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/java/com/heibaiying/producer/service/impl/ProductService.java @@ -0,0 +1,44 @@ +package com.heibaiying.producer.service.impl; + +import com.heibaiying.common.bean.Product; +import com.heibaiying.producer.service.IProductService; +import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author : heibaiying + * @description : 产品提供接口实现类 + */ +@Service +public class ProductService implements IProductService, ApplicationListener { + + private static List productList = new ArrayList<>(); + + public Product queryProductById(int id) { + return productList.stream().filter(p->p.getId()==id).collect(Collectors.toList()).get(0); + } + + + public List queryAllProducts() { + return productList; + } + + @Override + public void saveProduct(Product product) { + productList.add(product); + } + + @Override + public void onApplicationEvent(WebServerInitializedEvent event) { + int port = event.getWebServer().getPort(); + for (long i = 0; i < 20; i++) { + productList.add(new Product(i, port + "产品" + i, i / 2 == 0, new Date(), 66.66f * i)); + } + } +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/resources/application.yml b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/resources/application.yml new file mode 100644 index 0000000..3471fdb --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/main/resources/application.yml @@ -0,0 +1,13 @@ +server: + port: 8020 +# 指定服务命名 +spring: + application: + name: producer + zipkin: + base-url: http://localhost:9411/ +# 指定注册中心地址 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/test/java/com/heibaiying/producer/ProducerApplicationTests.java b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/test/java/com/heibaiying/producer/ProducerApplicationTests.java new file mode 100644 index 0000000..54cac2d --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/producer/src/test/java/com/heibaiying/producer/ProducerApplicationTests.java @@ -0,0 +1,17 @@ +package com.heibaiying.producer; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ProducerApplicationTests { + + @Test + public void contextLoads() { + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/pom.xml b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/pom.xml new file mode 100644 index 0000000..32177ba --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + + + org.springframework.boot + spring-boot-starter-parent + 2.0.8.RELEASE + + + + zuul + + + 1.8 + Finchley.SR2 + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-freemarker + + + org.springframework.boot + spring-boot-starter-test + test + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + org.springframework.cloud + spring-cloud-starter-netflix-zuul + + + + org.springframework.cloud + spring-cloud-starter-zipkin + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/ZuulApplication.java b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/ZuulApplication.java new file mode 100644 index 0000000..ba19b9d --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/ZuulApplication.java @@ -0,0 +1,18 @@ +package com.heibaiying.zuul; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.netflix.zuul.EnableZuulProxy; + +@SpringBootApplication +@EnableZuulProxy +@EnableDiscoveryClient +public class ZuulApplication { + + public static void main(String[] args) { + SpringApplication.run(ZuulApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/config/CustomZuulFallbackProvider.java b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/config/CustomZuulFallbackProvider.java new file mode 100644 index 0000000..0955398 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/config/CustomZuulFallbackProvider.java @@ -0,0 +1,81 @@ +package com.heibaiying.zuul.config; + +import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author : heibaiying + * @description : zuul 的熔断器 + */ +@Component +public class CustomZuulFallbackProvider implements FallbackProvider { + + /* + * 定义熔断将用于哪些路由的服务 + */ + @Override + public String getRoute() { + return "consumer"; + } + + @Override + public ClientHttpResponse fallbackResponse(String route, Throwable cause) { + return new ClientHttpResponse() { + + /** + * 返回响应的HTTP状态代码 + */ + @Override + public HttpStatus getStatusCode() throws IOException { + return HttpStatus.SERVICE_UNAVAILABLE; + } + + /** + * 返回HTTP状态代码 + */ + @Override + public int getRawStatusCode() throws IOException { + return HttpStatus.SERVICE_UNAVAILABLE.value(); + } + + /** + * 返回响应的HTTP状态文本 + */ + @Override + public String getStatusText() throws IOException { + return HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase(); + } + + @Override + public void close() { + + } + + /** + * 将消息正文作为输入流返回 + */ + @Override + public InputStream getBody() throws IOException { + return new ByteArrayInputStream("商城崩溃了,请稍后重试!".getBytes()); + } + + /** + * 将消息正文作为输入流返回 + */ + @Override + public HttpHeaders getHeaders() { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); + return httpHeaders; + } + }; + } +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/controller/LoginController.java b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/controller/LoginController.java new file mode 100644 index 0000000..0c5d75d --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/controller/LoginController.java @@ -0,0 +1,26 @@ +package com.heibaiying.zuul.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +import javax.servlet.http.HttpSession; +import java.util.Random; + +/** + * @author : heibaiying + * @description : 登录 + */ +@Controller +public class LoginController { + + @RequestMapping("index") + public String login(){ + return "index"; + } + + @RequestMapping("login") + public String login(String username,HttpSession session){ + session.setAttribute("code",username+String.valueOf(new Random().nextInt(10*1000))); + return "redirect:/consumer/sell/products"; + } +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/filter/CustomZuulFilter.java b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/filter/CustomZuulFilter.java new file mode 100644 index 0000000..70c9036 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/java/com/heibaiying/zuul/filter/CustomZuulFilter.java @@ -0,0 +1,71 @@ +package com.heibaiying.zuul.filter; + +import com.netflix.zuul.ZuulFilter; +import com.netflix.zuul.context.RequestContext; +import com.netflix.zuul.exception.ZuulException; +import org.omg.CORBA.Request; +import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author : heibaiying + * @description : 自定义filter过滤器 + */ + +@Component +public class CustomZuulFilter extends ZuulFilter { + + /** + * 返回过滤器的类型 + */ + @Override + public String filterType() { + return FilterConstants.PRE_TYPE; + } + + /** + * 返回过滤器的优先级顺序 + */ + @Override + public int filterOrder() { + return 0; + } + + /** + * 从此方法返回“true”意味着应该调用下面的 run()方法 + */ + @Override + public boolean shouldFilter() { + return true; + } + + /** + * ZuulFilter的核心校验方法 + */ + @Override + public Object run() throws ZuulException { + RequestContext currentContext = RequestContext.getCurrentContext(); + HttpServletRequest request = currentContext.getRequest(); + String code = (String)request.getSession().getAttribute("code"); + if (StringUtils.isEmpty(code)){ + // 设置值为false 不将请求转发到对应的服务上 + currentContext.setSendZuulResponse(false); + // 设置返回的状态码 + currentContext.setResponseStatusCode(HttpStatus.NON_AUTHORITATIVE_INFORMATION.value()); + HttpServletResponse response = currentContext.getResponse(); + try { + // 跳转到登录页面 + response.sendRedirect("/index"); + } catch (IOException e) { + e.printStackTrace(); + } + } + return null; + } +} diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/application.yml b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/application.yml new file mode 100644 index 0000000..239f795 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/application.yml @@ -0,0 +1,25 @@ +server: + port: 8090 +# 指定服务命名 +spring: + application: + name: zuul + zipkin: + base-url: http://localhost:9411/ +# 指定注册中心地址 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ +# 网关的路由 +zuul: + routes: + xxxx: #这个地方的值是可以任意的字符串 + path: /producer/** + serviceId: producer + consumer: + path: /consumer/** + serviceId: consumer + # 指定前缀 + # prefix: /v1 + diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/templates/index.ftl b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/templates/index.ftl new file mode 100644 index 0000000..a6e2308 --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/main/resources/templates/index.ftl @@ -0,0 +1,12 @@ + + + + Title + + +
+ + +
+ + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/test/java/com/heibaiying/zuul/ZuulApplicationTests.java b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/test/java/com/heibaiying/zuul/ZuulApplicationTests.java new file mode 100644 index 0000000..488c93a --- /dev/null +++ b/spring-cloud/spring-cloud-sleuth-zipkin/zuul/src/test/java/com/heibaiying/zuul/ZuulApplicationTests.java @@ -0,0 +1,17 @@ +package com.heibaiying.zuul; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class ZuulApplicationTests { + + @Test + public void contextLoads() { + } + +} + diff --git a/spring-cloud/spring-cloud-stream/pom.xml b/spring-cloud/spring-cloud-stream/pom.xml new file mode 100644 index 0000000..01f606d --- /dev/null +++ b/spring-cloud/spring-cloud-stream/pom.xml @@ -0,0 +1,72 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.0.8.RELEASE + + + com.heibaiying.stream + spring-cloud-stream + 0.0.1-SNAPSHOT + spring-cloud-stream + spring cloud stream project for Spring Boot + + + 1.8 + Finchley.SR2 + + + + + + org.springframework.boot + spring-boot-starter-amqp + + + org.springframework.cloud + spring-cloud-starter-stream-rabbit + + + org.springframework.boot + spring-boot-starter-web + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/SpringCloudStreamApplication.java b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/SpringCloudStreamApplication.java new file mode 100644 index 0000000..7addbf5 --- /dev/null +++ b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/SpringCloudStreamApplication.java @@ -0,0 +1,14 @@ +package com.heibaiying.stream; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringCloudStreamApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringCloudStreamApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/bean/Programmer.java b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/bean/Programmer.java new file mode 100644 index 0000000..a098dc9 --- /dev/null +++ b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/bean/Programmer.java @@ -0,0 +1,23 @@ +package com.heibaiying.stream.bean; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Programmer implements Serializable { + + private String name; + + private int age; + + private float salary; + + private Date birthday; +} diff --git a/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/controller/MessageController.java b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/controller/MessageController.java new file mode 100644 index 0000000..e7207da --- /dev/null +++ b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/controller/MessageController.java @@ -0,0 +1,78 @@ +package com.heibaiying.stream.controller; + +import com.heibaiying.stream.bean.Programmer; +import com.heibaiying.stream.stream.Custom; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHeaders; +import org.springframework.messaging.support.MessageBuilder; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * @author : heibaiying + * @description : 发送测试消息 + */ +@RestController +public class MessageController { + + @Autowired + private Custom custom; + + /*** + * 发送简单消息 + */ + @RequestMapping("sendSimpleMessage") + public void sendSimpleMessage() { + custom.input().send(MessageBuilder.withPayload("hell spring cloud stream").build()); + } + + + /*** + * 发送消息体为对象的消息 + * + */ + @RequestMapping("sendObject") + public void sendObject() { + Programmer programmer=new Programmer("pro",12,212.2f,new Date()); + custom.input().send(MessageBuilder.withPayload(programmer).build()); + } + + /** + * 发送带有消息头的消息 + */ + @RequestMapping("sendWithHeads") + public void sendWithHeads() { + Programmer programmer=new Programmer("pro",12,212.2f,new Date()); + Map map=new HashMap<>(); + map.put("code","868686"); + MessageHeaders messageHeaders=new MessageHeaders(map); + Message message= MessageBuilder.createMessage(programmer,messageHeaders); + custom.input().send(message); + } + + /** + * 条件消息 可以看做是消息路由键的一种实现 + */ + @RequestMapping("sendWithKey") + public void sendWithKey() { + // 创建消息头key 为 01 的消息 + Programmer programmer=new Programmer("key01",12,212.2f,new Date()); + Map map=new HashMap<>(); + map.put("key","01"); + MessageHeaders messageHeaders=new MessageHeaders(map); + Message message= MessageBuilder.createMessage(programmer,messageHeaders); + custom.input().send(message); + + // 创建消息头key 为 02 的消息 + programmer.setName("key02"); + map.put("key","02"); + MessageHeaders messageHeaders02=new MessageHeaders(map); + Message message02= MessageBuilder.createMessage(programmer,messageHeaders02); + custom.input().send(message02); + } +} diff --git a/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/Custom.java b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/Custom.java new file mode 100644 index 0000000..edf972e --- /dev/null +++ b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/Custom.java @@ -0,0 +1,22 @@ +package com.heibaiying.stream.stream; + +import org.springframework.cloud.stream.annotation.Input; +import org.springframework.cloud.stream.annotation.Output; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.SubscribableChannel; + +/** + * @author : heibaiying + */ +public interface Custom { + + String INPUT = "input"; + String OUTPUT = "output"; + + @Input(Custom.INPUT) + SubscribableChannel input(); + + @Output(Custom.OUTPUT) + MessageChannel output(); + +} diff --git a/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/StreamReceived.java b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/StreamReceived.java new file mode 100644 index 0000000..55f100d --- /dev/null +++ b/spring-cloud/spring-cloud-stream/src/main/java/com/heibaiying/stream/stream/StreamReceived.java @@ -0,0 +1,62 @@ +package com.heibaiying.stream.stream; + +import com.heibaiying.stream.bean.Programmer; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cloud.stream.annotation.EnableBinding; +import org.springframework.cloud.stream.annotation.StreamListener; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.messaging.handler.annotation.Headers; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.stereotype.Component; + +import java.util.Map; + +/** + * @author : heibaiying + * @description :消息的监听 + */ + +@Component +@EnableBinding(Custom.class) +@Slf4j +public class StreamReceived { + + @StreamListener(value = Custom.INPUT) + public void simple(Object payload) { + log.info("收到简单消息: {}", payload); + } + + @StreamListener(value = Custom.INPUT) + public void object(Programmer programmer) { + log.info("收到对象消息: {}", programmer); + } + + /** + * 用 @Header 监听时候需要注意,指定名称的属性必须在消息头中存在 不然就会抛出异常 MessageHandlingException: Missing header 'XXXX' for method parameter type [class java.lang.String] + */ + @StreamListener(value = Custom.INPUT) + public void heads(@Payload Programmer programmer, @Headers Map map, @Header(name = "code") String code) { + log.info("收到对象消息: {}", programmer); + map.forEach((key, value) -> { + log.info("消息头{}的值为{}", key, value); + }); + log.info("绑定指定消息头: code = {}", code); + } + + + /** + * 监听消息头key = 01 的消息 + */ + @StreamListener(target = Custom.INPUT, condition = "headers['key']=='01'") + public void key01(@Payload Programmer programmer) { + log.info("key01 监听器接收到消息: {}", programmer.getName()); + } + + /** + * 监听消息头key = 02 的消息 + */ + @StreamListener(target = Custom.INPUT, condition = "headers['key']=='01'") + public void key02(@Payload Programmer programmer) { + log.info("key02 监听器接收到消息: {}", programmer.getName()); + } +} diff --git a/spring-cloud/spring-cloud-stream/src/main/resources/application.yml b/spring-cloud/spring-cloud-stream/src/main/resources/application.yml new file mode 100644 index 0000000..37bb938 --- /dev/null +++ b/spring-cloud/spring-cloud-stream/src/main/resources/application.yml @@ -0,0 +1,6 @@ +spring: + rabbitmq: + host: localhost + port: 5672 + username: guest + password: guest \ No newline at end of file diff --git a/spring-cloud/spring-cloud-stream/src/test/java/com/heibaiying/stream/SpringCloudStreamApplicationTests.java b/spring-cloud/spring-cloud-stream/src/test/java/com/heibaiying/stream/SpringCloudStreamApplicationTests.java new file mode 100644 index 0000000..2efa878 --- /dev/null +++ b/spring-cloud/spring-cloud-stream/src/test/java/com/heibaiying/stream/SpringCloudStreamApplicationTests.java @@ -0,0 +1,17 @@ +package com.heibaiying.stream; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class SpringCloudStreamApplicationTests { + + @Test + public void contextLoads() { + } + +} +