├── .gitignore ├── README.md ├── section-01 ├── README.md └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── TakeOutOrder.java │ │ │ ├── TakeOutOrderRepository.java │ │ │ ├── WaiterServiceApplication.java │ │ │ └── WaiterServiceController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-02 ├── README.md └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-03 ├── README.md └── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── customerservice │ │ │ ├── CustomerServiceApplication.java │ │ │ ├── SimpleOrderRunner.java │ │ │ └── model │ │ │ ├── Order.java │ │ │ └── Payment.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── takeout │ └── customerservice │ └── CustomerServiceApplicationTests.java ├── section-04 ├── README.md ├── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── customerservice │ │ │ │ ├── CustomerServiceApplication.java │ │ │ │ ├── SimpleOrderRunner.java │ │ │ │ └── model │ │ │ │ └── TakeOutOrder.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── customerservice │ │ └── CustomerServiceApplicationTests.java └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-05 ├── README.md ├── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── customerservice │ │ │ │ ├── CustomerServiceApplication.java │ │ │ │ ├── SimpleOrderRunner.java │ │ │ │ └── model │ │ │ │ ├── Order.java │ │ │ │ └── Payment.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── bootstrap.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── customerservice │ │ └── CustomerServiceApplicationTests.java ├── eureka-server │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── eurekaserver │ │ │ │ └── EurekaServerApplication.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── eurekaserver │ │ └── EurekaServerApplicationTests.java └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ ├── application.properties │ │ └── bootstrap.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-06 ├── README.md ├── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── customerservice │ │ │ │ ├── CustomerServiceApplication.java │ │ │ │ ├── SimpleOrderRunner.java │ │ │ │ └── model │ │ │ │ ├── Order.java │ │ │ │ └── Payment.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── bootstrap.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── customerservice │ │ └── CustomerServiceApplicationTests.java └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ ├── application.properties │ │ └── bootstrap.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-07 ├── README.md ├── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── customerservice │ │ │ │ ├── CustomerServiceApplication.java │ │ │ │ ├── SimpleOrderRunner.java │ │ │ │ ├── TakeOutService.java │ │ │ │ └── model │ │ │ │ ├── Order.java │ │ │ │ └── Payment.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── bootstrap.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── customerservice │ │ └── CustomerServiceApplicationTests.java └── hystrix-dashboard │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── hystrixdashboard │ │ │ └── HystrixDashboardApplication.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── takeout │ └── hystrixdashboard │ └── HystrixDashboardApplicationTests.java ├── section-08 ├── README.md └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── Waiter.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ ├── application.properties │ │ └── bootstrap.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-09 ├── README.md ├── chef-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── chefservice │ │ │ │ ├── ChefServiceApplication.java │ │ │ │ ├── TakeOutOrder.java │ │ │ │ └── TakeOutStream.java │ │ └── resources │ │ │ └── application.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── chefservice │ │ └── ChefServiceApplicationTests.java ├── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── customerservice │ │ │ │ ├── CustomerServiceApplication.java │ │ │ │ ├── SimpleOrderRunner.java │ │ │ │ ├── TakeOutStream.java │ │ │ │ └── model │ │ │ │ ├── Payment.java │ │ │ │ └── TakeOutOrder.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── bootstrap.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── customerservice │ │ └── CustomerServiceApplicationTests.java └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── TakeOutStream.java │ │ │ ├── Waiter.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ ├── application.properties │ │ └── bootstrap.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-10 ├── README.md ├── chef-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── chefservice │ │ │ │ ├── ChefServiceApplication.java │ │ │ │ ├── TakeOutOrder.java │ │ │ │ └── TakeOutStream.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── bootstrap.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── chefservice │ │ └── ChefServiceApplicationTests.java ├── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── takeout │ │ │ │ └── customerservice │ │ │ │ ├── CustomerServiceApplication.java │ │ │ │ ├── TakeOutStream.java │ │ │ │ └── model │ │ │ │ ├── Payment.java │ │ │ │ └── TakeOutOrder.java │ │ └── resources │ │ │ ├── application.properties │ │ │ └── bootstrap.properties │ │ └── test │ │ └── java │ │ └── takeout │ │ └── customerservice │ │ └── CustomerServiceApplicationTests.java └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── TakeOutStream.java │ │ │ ├── Waiter.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ ├── application.properties │ │ └── bootstrap.properties │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java ├── section-11 ├── README.md ├── chef-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── docker │ │ │ └── Dockerfile │ │ ├── java │ │ │ └── takeout │ │ │ │ └── chefservice │ │ │ │ ├── ChefServiceApplication.java │ │ │ │ ├── TakeOutOrder.java │ │ │ │ └── TakeOutStream.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── bootstrap.yml │ │ └── test │ │ └── java │ │ └── takeout │ │ └── chefservice │ │ └── ChefServiceApplicationTests.java ├── customer-service │ ├── .gitignore │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── docker │ │ │ └── Dockerfile │ │ ├── java │ │ │ └── takeout │ │ │ │ └── customerservice │ │ │ │ ├── CustomerServiceApplication.java │ │ │ │ ├── TakeOutStream.java │ │ │ │ └── model │ │ │ │ ├── Payment.java │ │ │ │ └── TakeOutOrder.java │ │ └── resources │ │ │ ├── application.yml │ │ │ └── bootstrap.yml │ │ └── test │ │ └── java │ │ └── takeout │ │ └── customerservice │ │ └── CustomerServiceApplicationTests.java ├── docker-compose.yml └── waiter-service │ ├── .gitignore │ ├── pom.xml │ └── src │ ├── main │ ├── docker │ │ └── Dockerfile │ ├── java │ │ └── takeout │ │ │ └── waiterservice │ │ │ ├── DataInitializerRunner.java │ │ │ ├── TakeOutStream.java │ │ │ ├── Waiter.java │ │ │ ├── WaiterServiceApplication.java │ │ │ ├── controller │ │ │ ├── ExceptionControllerAdvice.java │ │ │ ├── OrderController.java │ │ │ └── PaymentController.java │ │ │ ├── model │ │ │ ├── Payment.java │ │ │ └── TakeOutOrder.java │ │ │ ├── repository │ │ │ ├── PaymentRepository.java │ │ │ └── TakeOutOrderRepository.java │ │ │ └── service │ │ │ ├── OrderService.java │ │ │ └── PaymentService.java │ └── resources │ │ ├── application.yml │ │ └── bootstrap.yml │ └── test │ └── java │ └── takeout │ └── waiterservice │ └── WaiterServiceApplicationTests.java └── section-12 ├── README.md ├── customer-service ├── .gitignore ├── pom.xml └── src │ ├── main │ ├── docker │ │ └── Dockerfile │ ├── java │ │ └── takeout │ │ │ └── customerservice │ │ │ ├── CustomerServiceApplication.java │ │ │ └── model │ │ │ ├── Order.java │ │ │ └── Payment.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── takeout │ └── customerservice │ └── CustomerServiceApplicationTests.java ├── docker-compose.yml ├── istio ├── istio-destination.yml ├── istio-vs-all-v1.yml ├── istio-vs-waiter-abort.yml ├── istio-vs-waiter-delay.yml ├── istio-vs-waiter-percent.yml └── istio-vs-waiter-v2.yml ├── takeout-aliyun.yml ├── takeout-minikube.yml └── waiter-service ├── .gitignore ├── pom.xml └── src ├── main ├── docker │ └── Dockerfile ├── java │ └── takeout │ │ └── waiterservice │ │ ├── WaiterServiceApplication.java │ │ ├── controller │ │ ├── ExceptionControllerAdvice.java │ │ ├── OrderController.java │ │ └── PaymentController.java │ │ ├── model │ │ ├── Payment.java │ │ └── TakeOutOrder.java │ │ ├── repository │ │ ├── PaymentRepository.java │ │ └── TakeOutOrderRepository.java │ │ └── service │ │ ├── OrderService.java │ │ └── PaymentService.java └── resources │ └── application.properties └── test └── java └── takeout └── waiterservice └── WaiterServiceApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | dependency-reduced-pom.xml 8 | buildNumber.properties 9 | .mvn/timing.properties 10 | 11 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 12 | !/.mvn/wrapper/maven-wrapper.jar 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 微服务架构与实战 2 | 3 | QConShanghai 2018深度培训第二天演示代码。 4 | 大会官方页面:[微服务架构与实践](https://2018.qconshanghai.com/training/953) 5 | 6 | ## 代码说明 7 | 8 | * Section 01 - 一个最基本的微服务 9 | * Section 02 - 重构了Section 01的服务,丰富了服务内容 10 | * Section 03 - 为Section 02的服务编写了一个基于RestTemplate的客户端 11 | * Section 04 - 用Spring Data REST重构了Section 02和Section03的代码 12 | * Section 05 - 使用Spring Cloud Netflix,通过Eureka实现服务注册与发现 13 | * Section 06 - 使用Zookeeper代替Section 05的Eureka实现服务注册与发现 14 | * Section 07 - 演示Hystrix断路器 15 | * Section 08 - 使用Zookeeper作为配置中心,加载集中配置 16 | * Section 09 - 增加RabbitMQ,使用Spring Cloud Stream,新增了chef-service 17 | * Section 10 - 演示了Spring Cloud Sleuth的使用,基于OpenZipkin实现服务追踪 18 | * Section 11 - 将Section 10的所有服务打包成Docker镜像,并提供DockerCompose配置 19 | * Section 12 - 基于Section 06重构代码,去除Spring Cloud依赖,演示在阿里云k8s上运行代码,同时也演示了Istio相关的一些功能 20 | 21 | -------------------------------------------------------------------------------- /section-01/README.md: -------------------------------------------------------------------------------- 1 | # Section 01 2 | 3 | 最简单的一个微服务,包含如下元素: 4 | 5 | 1. 一个Model 6 | 2. 对应的JpaRepository接口 7 | 3. 一个初始化数据的Runner 8 | 4. 一个REST服务 9 | 10 | 其中使用了Spring Boot,通过Lombok简化了模型类的编写。 11 | -------------------------------------------------------------------------------- /section-01/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-01/waiter-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | takeout 7 | waiter-service 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | waiter-service 12 | a simple microservice demo 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-actuator 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-data-jpa 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-web 39 | 40 | 41 | 42 | com.h2database 43 | h2 44 | runtime 45 | 46 | 47 | org.projectlombok 48 | lombok 49 | true 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-maven-plugin 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /section-01/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.Date; 9 | 10 | @Component 11 | public class DataInitializerRunner implements ApplicationRunner { 12 | @Autowired 13 | private TakeOutOrderRepository orderRepository; 14 | 15 | @Override 16 | public void run(ApplicationArguments args) throws Exception { 17 | TakeOutOrder order = TakeOutOrder.builder() 18 | .customer("Tony") 19 | .waiter("Steve") 20 | .items("Hamburger") 21 | .createTime(new Date()) 22 | .modifyTime(new Date()).build(); 23 | orderRepository.save(order); 24 | 25 | order = TakeOutOrder.builder() 26 | .customer("Tony") 27 | .waiter("Bruce") 28 | .items("Sandwich") 29 | .createTime(new Date()) 30 | .modifyTime(new Date()).build(); 31 | orderRepository.save(order); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /section-01/waiter-service/src/main/java/takeout/waiterservice/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import java.util.Date; 14 | 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Builder 19 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 20 | @Entity 21 | public class TakeOutOrder { 22 | @Id 23 | @GeneratedValue 24 | private Long id; 25 | private String items; 26 | private String customer; 27 | private String waiter; 28 | @Column(updatable = false) 29 | private Date createTime; 30 | private Date modifyTime; 31 | } 32 | -------------------------------------------------------------------------------- /section-01/waiter-service/src/main/java/takeout/waiterservice/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | 5 | public interface TakeOutOrderRepository extends JpaRepository { 6 | } 7 | -------------------------------------------------------------------------------- /section-01/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class WaiterServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(WaiterServiceApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /section-01/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.PathVariable; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import java.util.List; 9 | 10 | @RestController 11 | public class WaiterServiceController { 12 | @Autowired 13 | private TakeOutOrderRepository orderRepository; 14 | 15 | @RequestMapping("/orders/{id}") 16 | public TakeOutOrder getOrder(@PathVariable("id") Long id) { 17 | return id == null ? null : orderRepository.getOne(id); 18 | } 19 | 20 | @RequestMapping("/orders") 21 | public List getAllOrder() { 22 | return orderRepository.findAll(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /section-01/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | management.endpoints.web.exposure.include=* 2 | spring.output.ansi.enabled=ALWAYS -------------------------------------------------------------------------------- /section-01/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-02/README.md: -------------------------------------------------------------------------------- 1 | # Section 02 2 | 3 | 相对Section 01,主要有以下变化: 4 | 5 | 1. 重构服务,调整包结构,按功能划分 6 | 2. 增加支付相关接口 7 | 3. 演示了Spring MVC的一些功能 8 | -------------------------------------------------------------------------------- /section-02/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-02/waiter-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | takeout 7 | waiter-service 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | waiter-service 12 | a simple microservice demo 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-actuator 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-data-jpa 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-web 39 | 40 | 41 | 42 | com.h2database 43 | h2 44 | runtime 45 | 46 | 47 | org.projectlombok 48 | lombok 49 | true 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-starter-test 54 | test 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-maven-plugin 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | @Override 18 | public void run(ApplicationArguments args) throws Exception { 19 | TakeOutOrder order = TakeOutOrder.builder() 20 | .customer("Steve") 21 | .waiter("Tony") 22 | .items("Hamburger") 23 | .price(1000L) 24 | .state("I") 25 | .createTime(new Date()) 26 | .modifyTime(new Date()).build(); 27 | orderRepository.save(order); 28 | 29 | order = TakeOutOrder.builder() 30 | .customer("Bruce") 31 | .waiter("Tony") 32 | .items("Sandwich") 33 | .price(1000L) 34 | .state("I") 35 | .createTime(new Date()) 36 | .modifyTime(new Date()).build(); 37 | orderRepository.save(order); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class WaiterServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(WaiterServiceApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private Long price; 32 | private String state; 33 | @Column(updatable = false) 34 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 35 | private Date createTime; 36 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 37 | private Date modifyTime; 38 | } 39 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import takeout.waiterservice.model.TakeOutOrder; 6 | import takeout.waiterservice.repository.TakeOutOrderRepository; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | @Service 13 | public class OrderService { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | public List getAllOrders() { 18 | return orderRepository.findAll(); 19 | } 20 | 21 | public TakeOutOrder getOrder(Long id) { 22 | return id == null ? null : orderRepository.findById(id) 23 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")); 24 | } 25 | 26 | public void deleteOrder(Long id) { 27 | orderRepository.delete( 28 | orderRepository.findById(id) 29 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")) 30 | ); 31 | } 32 | 33 | public TakeOutOrder createOrder(TakeOutOrder order) { 34 | if (order != null) { 35 | order.setId(null); 36 | order.setWaiter("Tony"); 37 | order.setState("I"); 38 | order.setCreateTime(new Date()); 39 | order.setModifyTime(new Date()); 40 | orderRepository.save(order); 41 | } 42 | return order; 43 | } 44 | 45 | public void payOrder(Long id) { 46 | TakeOutOrder order = orderRepository.getOne(id); 47 | order.setState("P"); 48 | order.setModifyTime(new Date()); 49 | orderRepository.save(order); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/java/takeout/waiterservice/service/PaymentService.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import takeout.waiterservice.model.Payment; 6 | import takeout.waiterservice.model.TakeOutOrder; 7 | import takeout.waiterservice.repository.PaymentRepository; 8 | 9 | import javax.persistence.EntityNotFoundException; 10 | import javax.transaction.Transactional; 11 | import java.util.Date; 12 | import java.util.Optional; 13 | 14 | @Service 15 | @Transactional 16 | public class PaymentService { 17 | @Autowired 18 | private OrderService orderService; 19 | @Autowired 20 | private PaymentRepository paymentRepository; 21 | 22 | public Payment getPayment(Long orderId) { 23 | return paymentRepository.findByOrderId(orderId) 24 | .orElseThrow(() -> new EntityNotFoundException("Order " + orderId + " has NO payment!")); 25 | } 26 | 27 | public Payment createPayment(Long orderId) { 28 | Optional savedPayment = paymentRepository.findByOrderId(orderId); 29 | if (savedPayment.isPresent()) { 30 | return savedPayment.get(); 31 | } 32 | 33 | TakeOutOrder order = orderService.getOrder(orderId); 34 | if (order == null) { 35 | throw new EntityNotFoundException("Order " + orderId + " is NOT Found!"); 36 | } 37 | Payment payment = Payment.builder() 38 | .orderId(orderId) 39 | .price(order.getPrice()) 40 | .state("I") 41 | .createTime(new Date()) 42 | .modifyTime(new Date()).build(); 43 | return paymentRepository.save(payment); 44 | } 45 | 46 | public Payment updatePayment(Long orderId, Payment payment) { 47 | Payment savedPayment = paymentRepository.findByOrderId(orderId) 48 | .orElseThrow(() -> new EntityNotFoundException("Order " + orderId + " has NO payment!")); 49 | 50 | if ("S".equalsIgnoreCase(payment.getState())) { 51 | orderService.payOrder(orderId); 52 | } 53 | savedPayment.setState(payment.getState()); 54 | savedPayment.setModifyTime(new Date()); 55 | return paymentRepository.save(savedPayment); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /section-02/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS -------------------------------------------------------------------------------- /section-02/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-03/README.md: -------------------------------------------------------------------------------- 1 | # Section 03 2 | 3 | 为waiter-service的REST服务编写了一个客户端,主要演示如下功能: 4 | 5 | 1. Spring RestTemplate的基本用法 6 | 2. 各种HTTP Method的调用方法 7 | -------------------------------------------------------------------------------- /section-03/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-03/customer-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | takeout 7 | customer-service 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | customer-service 12 | a simple microservice demo 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.projectlombok 35 | lombok 36 | true 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-test 41 | test 42 | 43 | 44 | 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-maven-plugin 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /section-03/customer-service/src/main/java/takeout/customerservice/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.web.client.RestTemplate; 7 | 8 | @SpringBootApplication 9 | public class CustomerServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(CustomerServiceApplication.class, args); 13 | } 14 | 15 | @Bean 16 | public RestTemplate restTemplate() { 17 | return new RestTemplate(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-03/customer-service/src/main/java/takeout/customerservice/model/Order.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class Order { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private Long price; 18 | private String state; 19 | } 20 | -------------------------------------------------------------------------------- /section-03/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-03/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha 2 | waiter.url=http://127.0.0.1:8080 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | -------------------------------------------------------------------------------- /section-03/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-04/README.md: -------------------------------------------------------------------------------- 1 | # Section 04 2 | 3 | 用Spring Data REST重构了Section 02和Section 03的代码: 4 | 5 | 1. 以HATEOS的方式暴露了TakeOutOrder资源 6 | 2. 客户端通过REL自动发现URI资源并发起调用 7 | 8 | -------------------------------------------------------------------------------- /section-04/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-04/customer-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | takeout 7 | customer-service 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | customer-service 12 | a simple microservice demo 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-data-rest 35 | 36 | 37 | 38 | org.projectlombok 39 | lombok 40 | true 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | test 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-maven-plugin 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /section-04/customer-service/src/main/java/takeout/customerservice/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import com.fasterxml.jackson.databind.DeserializationFeature; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.hateoas.hal.Jackson2HalModule; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 11 | import org.springframework.web.client.RestTemplate; 12 | 13 | import java.util.Arrays; 14 | 15 | @SpringBootApplication 16 | public class CustomerServiceApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(CustomerServiceApplication.class, args); 20 | } 21 | 22 | @Bean 23 | public RestTemplate restTemplate() { 24 | ObjectMapper mapper = new ObjectMapper(); 25 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 26 | mapper.registerModule(new Jackson2HalModule()); 27 | 28 | MappingJackson2HttpMessageConverter converter = 29 | new MappingJackson2HttpMessageConverter(); 30 | converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json")); 31 | converter.setObjectMapper(mapper); 32 | 33 | return new RestTemplate(Arrays.asList(converter)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-04/customer-service/src/main/java/takeout/customerservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class TakeOutOrder { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private Long price; 18 | private String state; 19 | } 20 | -------------------------------------------------------------------------------- /section-04/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha 2 | waiter.url=http://127.0.0.1:8080 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | -------------------------------------------------------------------------------- /section-04/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-04/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | @Override 18 | public void run(ApplicationArguments args) throws Exception { 19 | TakeOutOrder order = TakeOutOrder.builder() 20 | .customer("Steve") 21 | .waiter("Tony") 22 | .items("Hamburger") 23 | .price(1000L) 24 | .state("I") 25 | .createTime(new Date()) 26 | .modifyTime(new Date()).build(); 27 | orderRepository.save(order); 28 | 29 | order = TakeOutOrder.builder() 30 | .customer("Bruce") 31 | .waiter("Tony") 32 | .items("Sandwich") 33 | .price(1000L) 34 | .state("I") 35 | .createTime(new Date()) 36 | .modifyTime(new Date()).build(); 37 | orderRepository.save(order); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class WaiterServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(WaiterServiceApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private Long price; 32 | private String state; 33 | @Column(updatable = false) 34 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 35 | private Date createTime; 36 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 37 | private Date modifyTime; 38 | } 39 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.repository.query.Param; 5 | import org.springframework.data.rest.core.annotation.RepositoryRestResource; 6 | import takeout.waiterservice.model.Payment; 7 | 8 | import java.util.Optional; 9 | 10 | @RepositoryRestResource 11 | public interface PaymentRepository extends JpaRepository { 12 | Optional findByOrderId(@Param("orderId") Long orderId); 13 | } 14 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.repository.query.Param; 5 | import takeout.waiterservice.model.TakeOutOrder; 6 | 7 | import java.util.List; 8 | 9 | public interface TakeOutOrderRepository extends JpaRepository { 10 | List findByCustomerOrderById(@Param("customer") String customer); 11 | } 12 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/java/takeout/waiterservice/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import takeout.waiterservice.model.TakeOutOrder; 6 | import takeout.waiterservice.repository.TakeOutOrderRepository; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | @Service 13 | public class OrderService { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | public List getAllOrders() { 18 | return orderRepository.findAll(); 19 | } 20 | 21 | public TakeOutOrder getOrder(Long id) { 22 | return id == null ? null : orderRepository.findById(id) 23 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")); 24 | } 25 | 26 | public void deleteOrder(Long id) { 27 | orderRepository.delete( 28 | orderRepository.findById(id) 29 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")) 30 | ); 31 | } 32 | 33 | public TakeOutOrder createOrder(TakeOutOrder order) { 34 | if (order != null) { 35 | order.setId(null); 36 | order.setWaiter("Tony"); 37 | order.setState("I"); 38 | order.setCreateTime(new Date()); 39 | order.setModifyTime(new Date()); 40 | orderRepository.save(order); 41 | } 42 | return order; 43 | } 44 | 45 | public void payOrder(Long id) { 46 | TakeOutOrder order = orderRepository.getOne(id); 47 | order.setState("P"); 48 | order.setModifyTime(new Date()); 49 | orderRepository.save(order); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /section-04/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS -------------------------------------------------------------------------------- /section-04/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-05/README.md: -------------------------------------------------------------------------------- 1 | # Section 05 2 | 3 | 用Spring Cloud Netflix重构Section 02和Section 03的代码: 4 | 5 | 1. 使用Eureka作为服务注册中心 6 | 2. customer-service使用注册中心获取waiter-service的地址 7 | 8 | 9 | -------------------------------------------------------------------------------- /section-05/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-05/customer-service/src/main/java/takeout/customerservice/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | @SpringBootApplication 11 | @EnableDiscoveryClient 12 | public class CustomerServiceApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(CustomerServiceApplication.class, args); 16 | } 17 | 18 | @Bean 19 | @LoadBalanced 20 | public RestTemplate restTemplate() { 21 | return new RestTemplate(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /section-05/customer-service/src/main/java/takeout/customerservice/model/Order.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class Order { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private Long price; 18 | private String state; 19 | } 20 | -------------------------------------------------------------------------------- /section-05/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-05/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha 2 | waiter.url=http://waiter-service 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | -------------------------------------------------------------------------------- /section-05/customer-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=customer-service -------------------------------------------------------------------------------- /section-05/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-05/eureka-server/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-05/eureka-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | takeout 7 | eureka-server 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | eureka-server 12 | a simple eureka server 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | Finchley.SR1 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-starter-netflix-eureka-server 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.cloud 45 | spring-cloud-dependencies 46 | ${spring-cloud.version} 47 | pom 48 | import 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-maven-plugin 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /section-05/eureka-server/src/main/java/takeout/eurekaserver/EurekaServerApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.eurekaserver; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | @SpringBootApplication 8 | @EnableEurekaServer 9 | public class EurekaServerApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(EurekaServerApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /section-05/eureka-server/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8761 2 | 3 | eureka.client.register-with-eureka=false 4 | eureka.client.fetch-registry=false 5 | -------------------------------------------------------------------------------- /section-05/eureka-server/src/test/java/takeout/eurekaserver/EurekaServerApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.eurekaserver; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class EurekaServerApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-05/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | @Override 18 | public void run(ApplicationArguments args) throws Exception { 19 | TakeOutOrder order = TakeOutOrder.builder() 20 | .customer("Steve") 21 | .waiter("Tony") 22 | .items("Hamburger") 23 | .price(1000L) 24 | .state("I") 25 | .createTime(new Date()) 26 | .modifyTime(new Date()).build(); 27 | orderRepository.save(order); 28 | 29 | order = TakeOutOrder.builder() 30 | .customer("Bruce") 31 | .waiter("Tony") 32 | .items("Sandwich") 33 | .price(1000L) 34 | .state("I") 35 | .createTime(new Date()) 36 | .modifyTime(new Date()).build(); 37 | orderRepository.save(order); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | @SpringBootApplication 8 | @EnableDiscoveryClient 9 | public class WaiterServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(WaiterServiceApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private Long price; 32 | private String state; 33 | @Column(updatable = false) 34 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 35 | private Date createTime; 36 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 37 | private Date modifyTime; 38 | } 39 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/java/takeout/waiterservice/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import takeout.waiterservice.model.TakeOutOrder; 6 | import takeout.waiterservice.repository.TakeOutOrderRepository; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | @Service 13 | public class OrderService { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | public List getAllOrders() { 18 | return orderRepository.findAll(); 19 | } 20 | 21 | public TakeOutOrder getOrder(Long id) { 22 | return id == null ? null : orderRepository.findById(id) 23 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")); 24 | } 25 | 26 | public void deleteOrder(Long id) { 27 | orderRepository.delete( 28 | orderRepository.findById(id) 29 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")) 30 | ); 31 | } 32 | 33 | public TakeOutOrder createOrder(TakeOutOrder order) { 34 | if (order != null) { 35 | order.setId(null); 36 | order.setWaiter("Tony"); 37 | order.setState("I"); 38 | order.setCreateTime(new Date()); 39 | order.setModifyTime(new Date()); 40 | orderRepository.save(order); 41 | } 42 | return order; 43 | } 44 | 45 | public void payOrder(Long id) { 46 | TakeOutOrder order = orderRepository.getOne(id); 47 | order.setState("P"); 48 | order.setModifyTime(new Date()); 49 | orderRepository.save(order); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS -------------------------------------------------------------------------------- /section-05/waiter-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=waiter-service -------------------------------------------------------------------------------- /section-05/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-06/README.md: -------------------------------------------------------------------------------- 1 | # Section 06 2 | 3 | 用Zookeeper作为服务注册中心,重构Section 05的代码。 4 | 5 | 使用Docker在本地启动一个Zookeeper: 6 | 7 | ``` 8 | docker pull zookeeper:3.5 9 | docker run --name zookeeper -p 2181:2181 -d zookeeper:3.5 10 | ``` 11 | -------------------------------------------------------------------------------- /section-06/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-06/customer-service/src/main/java/takeout/customerservice/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | @SpringBootApplication 11 | @EnableDiscoveryClient 12 | public class CustomerServiceApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(CustomerServiceApplication.class, args); 16 | } 17 | 18 | @Bean 19 | @LoadBalanced 20 | public RestTemplate restTemplate() { 21 | return new RestTemplate(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /section-06/customer-service/src/main/java/takeout/customerservice/model/Order.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class Order { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private Long price; 18 | private String state; 19 | } 20 | -------------------------------------------------------------------------------- /section-06/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-06/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha 2 | waiter.url=http://waiter-service 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | -------------------------------------------------------------------------------- /section-06/customer-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=customer-service -------------------------------------------------------------------------------- /section-06/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-06/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | @Override 18 | public void run(ApplicationArguments args) throws Exception { 19 | TakeOutOrder order = TakeOutOrder.builder() 20 | .customer("Steve") 21 | .waiter("Tony") 22 | .items("Hamburger") 23 | .price(1000L) 24 | .state("I") 25 | .createTime(new Date()) 26 | .modifyTime(new Date()).build(); 27 | orderRepository.save(order); 28 | 29 | order = TakeOutOrder.builder() 30 | .customer("Bruce") 31 | .waiter("Tony") 32 | .items("Sandwich") 33 | .price(1000L) 34 | .state("I") 35 | .createTime(new Date()) 36 | .modifyTime(new Date()).build(); 37 | orderRepository.save(order); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | @SpringBootApplication 8 | @EnableDiscoveryClient 9 | public class WaiterServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(WaiterServiceApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private Long price; 32 | private String state; 33 | @Column(updatable = false) 34 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 35 | private Date createTime; 36 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 37 | private Date modifyTime; 38 | } 39 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/java/takeout/waiterservice/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import takeout.waiterservice.model.TakeOutOrder; 6 | import takeout.waiterservice.repository.TakeOutOrderRepository; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Date; 10 | import java.util.List; 11 | 12 | @Service 13 | public class OrderService { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | 17 | public List getAllOrders() { 18 | return orderRepository.findAll(); 19 | } 20 | 21 | public TakeOutOrder getOrder(Long id) { 22 | return id == null ? null : orderRepository.findById(id) 23 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")); 24 | } 25 | 26 | public void deleteOrder(Long id) { 27 | orderRepository.delete( 28 | orderRepository.findById(id) 29 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")) 30 | ); 31 | } 32 | 33 | public TakeOutOrder createOrder(TakeOutOrder order) { 34 | if (order != null) { 35 | order.setId(null); 36 | order.setWaiter("Tony"); 37 | order.setState("I"); 38 | order.setCreateTime(new Date()); 39 | order.setModifyTime(new Date()); 40 | orderRepository.save(order); 41 | } 42 | return order; 43 | } 44 | 45 | public void payOrder(Long id) { 46 | TakeOutOrder order = orderRepository.getOne(id); 47 | order.setState("P"); 48 | order.setModifyTime(new Date()); 49 | orderRepository.save(order); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS -------------------------------------------------------------------------------- /section-06/waiter-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=waiter-service -------------------------------------------------------------------------------- /section-06/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-07/README.md: -------------------------------------------------------------------------------- 1 | # Section 07 2 | 3 | 在Section 06的基础上,增加Hystrix作为断路器。 4 | 5 | * 复用Section 06的waiter-service 6 | * 修改customer-service,增加Hystrix支持 7 | * 新建一个HystrixDashboard 8 | 9 | -------------------------------------------------------------------------------- /section-07/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-07/customer-service/src/main/java/takeout/customerservice/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.web.client.RestTemplate; 10 | 11 | @SpringBootApplication 12 | @EnableDiscoveryClient 13 | @EnableCircuitBreaker 14 | public class CustomerServiceApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(CustomerServiceApplication.class, args); 18 | } 19 | 20 | @Bean 21 | @LoadBalanced 22 | public RestTemplate restTemplate() { 23 | return new RestTemplate(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /section-07/customer-service/src/main/java/takeout/customerservice/SimpleOrderRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.boot.ApplicationArguments; 7 | import org.springframework.boot.ApplicationRunner; 8 | import org.springframework.core.ParameterizedTypeReference; 9 | import org.springframework.http.HttpMethod; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.client.RestTemplate; 13 | import org.springframework.web.util.UriComponentsBuilder; 14 | import takeout.customerservice.model.Order; 15 | import takeout.customerservice.model.Payment; 16 | 17 | import java.net.URI; 18 | import java.util.List; 19 | 20 | @Component 21 | @Slf4j 22 | public class SimpleOrderRunner implements ApplicationRunner { 23 | @Autowired 24 | private TakeOutService takeOutService; 25 | 26 | @Override 27 | public void run(ApplicationArguments args) throws Exception { 28 | for (int i = 0; i < 100; i++) { 29 | if (takeOutService.askHowLongToWait() >=0) { 30 | break; 31 | } 32 | Thread.sleep(5000); 33 | } 34 | Long orderId = takeOutService.makeAnOrder(); 35 | takeOutService.payTheOrder(orderId); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /section-07/customer-service/src/main/java/takeout/customerservice/model/Order.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class Order { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private Long price; 18 | private String state; 19 | } 20 | -------------------------------------------------------------------------------- /section-07/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-07/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha 2 | waiter.url=http://waiter-service 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | 7 | management.endpoints.web.exposure.include=health,hystrix.stream 8 | -------------------------------------------------------------------------------- /section-07/customer-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=customer-service -------------------------------------------------------------------------------- /section-07/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-07/hystrix-dashboard/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-07/hystrix-dashboard/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | takeout 7 | hystrix-dashboard 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | hystrix-dashboard 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.5.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | Finchley.SR1 26 | 27 | 28 | 29 | 30 | org.springframework.cloud 31 | spring-cloud-starter-netflix-hystrix-dashboard 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.cloud 45 | spring-cloud-dependencies 46 | ${spring-cloud.version} 47 | pom 48 | import 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | org.springframework.boot 57 | spring-boot-maven-plugin 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /section-07/hystrix-dashboard/src/main/java/takeout/hystrixdashboard/HystrixDashboardApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.hystrixdashboard; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 6 | 7 | @SpringBootApplication 8 | @EnableHystrixDashboard 9 | public class HystrixDashboardApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(HystrixDashboardApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /section-07/hystrix-dashboard/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=6080 -------------------------------------------------------------------------------- /section-07/hystrix-dashboard/src/test/java/takeout/hystrixdashboard/HystrixDashboardApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.hystrixdashboard; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class HystrixDashboardApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-08/README.md: -------------------------------------------------------------------------------- 1 | # Section 08 2 | 3 | 在Section 06的基础上,使用Spring Cloud Config添加了配置中心功能,配置中心使用的是Zookeeper存储。 4 | 5 | 6 | -------------------------------------------------------------------------------- /section-08/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | @Autowired 17 | private Waiter waiter; 18 | 19 | @Override 20 | public void run(ApplicationArguments args) throws Exception { 21 | TakeOutOrder order = TakeOutOrder.builder() 22 | .customer("Steve") 23 | .waiter(waiter.getWaiterName()) 24 | .items("Hamburger") 25 | .price(1000L) 26 | .state("I") 27 | .createTime(new Date()) 28 | .modifyTime(new Date()).build(); 29 | orderRepository.save(order); 30 | 31 | order = TakeOutOrder.builder() 32 | .customer("Bruce") 33 | .waiter(waiter.getWaiterName()) 34 | .items("Sandwich") 35 | .price(1000L) 36 | .state("I") 37 | .createTime(new Date()) 38 | .modifyTime(new Date()).build(); 39 | orderRepository.save(order); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/Waiter.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.cloud.context.config.annotation.RefreshScope; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | @RefreshScope 10 | @Data 11 | public class Waiter { 12 | @Value("${prefix.name}") 13 | private String prefix; 14 | @Value("${random.int}") 15 | private int number; 16 | 17 | public String getWaiterName() { 18 | return prefix + "-" + number; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | @SpringBootApplication 8 | @EnableDiscoveryClient 9 | public class WaiterServiceApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(WaiterServiceApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private Long price; 32 | private String state; 33 | @Column(updatable = false) 34 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 35 | private Date createTime; 36 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 37 | private Date modifyTime; 38 | } 39 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/java/takeout/waiterservice/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | import takeout.waiterservice.Waiter; 6 | import takeout.waiterservice.model.TakeOutOrder; 7 | import takeout.waiterservice.repository.TakeOutOrderRepository; 8 | 9 | import javax.persistence.EntityNotFoundException; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | @Service 14 | public class OrderService { 15 | @Autowired 16 | private TakeOutOrderRepository orderRepository; 17 | @Autowired 18 | private Waiter waiter; 19 | 20 | public List getAllOrders() { 21 | return orderRepository.findAll(); 22 | } 23 | 24 | public TakeOutOrder getOrder(Long id) { 25 | return id == null ? null : orderRepository.findById(id) 26 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")); 27 | } 28 | 29 | public void deleteOrder(Long id) { 30 | orderRepository.delete( 31 | orderRepository.findById(id) 32 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")) 33 | ); 34 | } 35 | 36 | public TakeOutOrder createOrder(TakeOutOrder order) { 37 | if (order != null) { 38 | order.setId(null); 39 | order.setWaiter(waiter.getWaiterName()); 40 | order.setState("I"); 41 | order.setCreateTime(new Date()); 42 | order.setModifyTime(new Date()); 43 | orderRepository.save(order); 44 | } 45 | return order; 46 | } 47 | 48 | public void payOrder(Long id) { 49 | TakeOutOrder order = orderRepository.getOne(id); 50 | order.setState("P"); 51 | order.setModifyTime(new Date()); 52 | orderRepository.save(order); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS 2 | management.endpoints.web.exposure.include=health,refresh 3 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=waiter-service 2 | 3 | spring.cloud.zookeeper.config.enabled=true 4 | spring.cloud.zookeeper.connect-string=localhost:2181 5 | -------------------------------------------------------------------------------- /section-08/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-09/README.md: -------------------------------------------------------------------------------- 1 | # Section 09 2 | 3 | 基于Spring Cloud Stream接入了RabbitMQ,实现了完整的下单、付款、制作、取餐的过程。 4 | 5 | 需要在本地启动一个RabbitMQ: 6 | 7 | ``` 8 | docker run -d --hostname my-rabbit --name some-rabbit -p 9888:15672 -p 5672:5672 rabbitmq:3.6-management 9 | ``` -------------------------------------------------------------------------------- /section-09/chef-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-09/chef-service/src/main/java/takeout/chefservice/ChefServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.stream.annotation.EnableBinding; 8 | import org.springframework.cloud.stream.annotation.StreamListener; 9 | //import org.springframework.integration.annotation.Transformer; 10 | import org.springframework.messaging.handler.annotation.SendTo; 11 | 12 | @SpringBootApplication 13 | @EnableBinding(TakeOutStream.class) 14 | @Slf4j 15 | public class ChefServiceApplication { 16 | @Value("${chef.name}-${random.int}") 17 | private String chef; 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(ChefServiceApplication.class, args); 21 | } 22 | 23 | @StreamListener("orderRequests") 24 | @SendTo("finishedOrders") 25 | // @Transformer(inputChannel = "orderRequests", outputChannel = "finishedOrders") 26 | public TakeOutOrder processOrder(TakeOutOrder request) { 27 | log.info("Receiving Order: {}", request); 28 | log.info("Cocking order {}...", request.getId()); 29 | try { 30 | Thread.sleep(100); 31 | } catch (InterruptedException e) { 32 | } 33 | request.setChef(chef); 34 | request.setState("C"); 35 | return request; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /section-09/chef-service/src/main/java/takeout/chefservice/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class TakeOutOrder { 7 | private Long id; 8 | private String items; 9 | private String chef; 10 | private String state; 11 | } 12 | -------------------------------------------------------------------------------- /section-09/chef-service/src/main/java/takeout/chefservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Output 10 | MessageChannel finishedOrders(); 11 | @Input 12 | SubscribableChannel orderRequests(); 13 | } 14 | -------------------------------------------------------------------------------- /section-09/chef-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9080 2 | spring.output.ansi.enabled=ALWAYS 3 | 4 | chef.name=Peter 5 | 6 | spring.rabbitmq.host=localhost 7 | spring.rabbitmq.port=5672 8 | spring.rabbitmq.username=guest 9 | spring.rabbitmq.password=guest 10 | 11 | spring.cloud.stream.bindinds.default.binder=rabbit 12 | spring.cloud.stream.binders.rabbit.type=rabbit 13 | 14 | spring.cloud.stream.bindings.orderRequests.group=chef-service -------------------------------------------------------------------------------- /section-09/chef-service/src/test/java/takeout/chefservice/ChefServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ChefServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-09/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-09/customer-service/src/main/java/takeout/customerservice/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.cloud.stream.annotation.EnableBinding; 9 | import org.springframework.cloud.stream.annotation.StreamListener; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.web.client.RestTemplate; 12 | import takeout.customerservice.model.TakeOutOrder; 13 | 14 | @SpringBootApplication 15 | @EnableDiscoveryClient 16 | @EnableBinding(TakeOutStream.class) 17 | @Slf4j 18 | public class CustomerServiceApplication { 19 | public static void main(String[] args) { 20 | SpringApplication.run(CustomerServiceApplication.class, args); 21 | } 22 | 23 | @Bean 24 | @LoadBalanced 25 | public RestTemplate restTemplate() { 26 | return new RestTemplate(); 27 | } 28 | 29 | @StreamListener(target = "takeoutFood", condition = "headers['customer']=='${customer.name}'") 30 | public void takeoutFood(TakeOutOrder takeOutOrder) { 31 | log.info("I've taken the food {}", takeOutOrder); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /section-09/customer-service/src/main/java/takeout/customerservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Input 10 | SubscribableChannel takeoutFood(); 11 | } 12 | -------------------------------------------------------------------------------- /section-09/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-09/customer-service/src/main/java/takeout/customerservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class TakeOutOrder { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private String chef; 18 | private Long price; 19 | private String state; 20 | } 21 | -------------------------------------------------------------------------------- /section-09/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha-${server.port} 2 | waiter.url=http://waiter-service 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | 7 | spring.rabbitmq.host=localhost 8 | spring.rabbitmq.port=5672 9 | spring.rabbitmq.username=guest 10 | spring.rabbitmq.password=guest 11 | 12 | spring.cloud.stream.bindinds.default.binder=rabbit 13 | spring.cloud.stream.binders.rabbit.type=rabbit 14 | 15 | spring.cloud.stream.bindings.takeoutFood.group=customer-service 16 | -------------------------------------------------------------------------------- /section-09/customer-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=customer-service -------------------------------------------------------------------------------- /section-09/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-09/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | @Autowired 17 | private Waiter waiter; 18 | 19 | @Override 20 | public void run(ApplicationArguments args) throws Exception { 21 | TakeOutOrder order = TakeOutOrder.builder() 22 | .customer("Steve") 23 | .waiter(waiter.getWaiterName()) 24 | .items("Hamburger") 25 | .price(1000L) 26 | .state("I") 27 | .createTime(new Date()) 28 | .modifyTime(new Date()).build(); 29 | orderRepository.save(order); 30 | 31 | order = TakeOutOrder.builder() 32 | .customer("Bruce") 33 | .waiter(waiter.getWaiterName()) 34 | .items("Sandwich") 35 | .price(1000L) 36 | .state("I") 37 | .createTime(new Date()) 38 | .modifyTime(new Date()).build(); 39 | orderRepository.save(order); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Input 10 | SubscribableChannel finishedOrders(); 11 | @Output 12 | MessageChannel orderRequests(); 13 | @Output 14 | MessageChannel takeoutFood(); 15 | } 16 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/Waiter.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.cloud.context.config.annotation.RefreshScope; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | @RefreshScope 10 | @Data 11 | public class Waiter { 12 | @Value("${prefix.name}") 13 | private String prefix; 14 | @Value("${random.int}") 15 | private int number; 16 | 17 | public String getWaiterName() { 18 | return prefix + "-" + number; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.stream.annotation.EnableBinding; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient 10 | @EnableBinding(TakeOutStream.class) 11 | public class WaiterServiceApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(WaiterServiceApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private String chef; 32 | private Long price; 33 | private String state; 34 | @Column(updatable = false) 35 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 36 | private Date createTime; 37 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 38 | private Date modifyTime; 39 | } 40 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS 2 | management.endpoints.web.exposure.include=health,refresh 3 | 4 | spring.rabbitmq.host=localhost 5 | spring.rabbitmq.port=5672 6 | spring.rabbitmq.username=guest 7 | spring.rabbitmq.password=guest 8 | 9 | spring.cloud.stream.bindinds.default.binder=rabbit 10 | spring.cloud.stream.binders.rabbit.type=rabbit 11 | 12 | spring.cloud.stream.bindings.finishedOrders.group=waiter-service -------------------------------------------------------------------------------- /section-09/waiter-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=waiter-service 2 | 3 | spring.cloud.zookeeper.config.enabled=true 4 | spring.cloud.zookeeper.connect-string=localhost:2181 5 | -------------------------------------------------------------------------------- /section-09/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-10/README.md: -------------------------------------------------------------------------------- 1 | # Section 10 2 | 3 | 基于Section 09的代码,使用Spring Cloud Sleuth基于OpenZipkin实现了服务追踪,使用Web方式提交信息。 4 | 5 | * customer-service稍作修改,使用POST请求来触发后续操作 6 | * 所有服务接入spring-cloud-starter-zipkin 7 | * 在本地9411端口启动一个OpenZipkin 8 | 9 | ``` 10 | docker run -d --name zipkin -p 9411:9411 openzipkin/zipkin 11 | ``` -------------------------------------------------------------------------------- /section-10/chef-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-10/chef-service/src/main/java/takeout/chefservice/ChefServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.stream.annotation.EnableBinding; 8 | import org.springframework.cloud.stream.annotation.StreamListener; 9 | //import org.springframework.integration.annotation.Transformer; 10 | import org.springframework.messaging.handler.annotation.SendTo; 11 | 12 | @SpringBootApplication 13 | @EnableBinding(TakeOutStream.class) 14 | @Slf4j 15 | public class ChefServiceApplication { 16 | @Value("${chef.name}-${random.int}") 17 | private String chef; 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(ChefServiceApplication.class, args); 21 | } 22 | 23 | @StreamListener("orderRequests") 24 | @SendTo("finishedOrders") 25 | // @Transformer(inputChannel = "orderRequests", outputChannel = "finishedOrders") 26 | public TakeOutOrder processOrder(TakeOutOrder request) { 27 | log.info("Receiving Order: {}", request); 28 | log.info("Cocking order {}...", request.getId()); 29 | try { 30 | Thread.sleep(100); 31 | } catch (InterruptedException e) { 32 | } 33 | request.setChef(chef); 34 | request.setState("C"); 35 | return request; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /section-10/chef-service/src/main/java/takeout/chefservice/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class TakeOutOrder { 7 | private Long id; 8 | private String items; 9 | private String chef; 10 | private String state; 11 | } 12 | -------------------------------------------------------------------------------- /section-10/chef-service/src/main/java/takeout/chefservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Output 10 | MessageChannel finishedOrders(); 11 | @Input 12 | SubscribableChannel orderRequests(); 13 | } 14 | -------------------------------------------------------------------------------- /section-10/chef-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=9080 2 | spring.output.ansi.enabled=ALWAYS 3 | 4 | chef.name=Peter 5 | 6 | spring.rabbitmq.host=localhost 7 | spring.rabbitmq.port=5672 8 | spring.rabbitmq.username=guest 9 | spring.rabbitmq.password=guest 10 | 11 | spring.cloud.stream.bindinds.default.binder=rabbit 12 | spring.cloud.stream.binders.rabbit.type=rabbit 13 | 14 | spring.cloud.stream.bindings.orderRequests.group=chef-service 15 | 16 | spring.sleuth.sampler.probability=1.0 17 | spring.zipkin.baseUrl=http://localhost:9411 18 | spring.zipkin.sender.type=web -------------------------------------------------------------------------------- /section-10/chef-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=chef-service 2 | 3 | spring.cloud.zookeeper.config.enabled=true 4 | spring.cloud.zookeeper.connect-string=localhost:2181 5 | -------------------------------------------------------------------------------- /section-10/chef-service/src/test/java/takeout/chefservice/ChefServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ChefServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-10/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-10/customer-service/src/main/java/takeout/customerservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Input 10 | SubscribableChannel takeoutFood(); 11 | } 12 | -------------------------------------------------------------------------------- /section-10/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-10/customer-service/src/main/java/takeout/customerservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class TakeOutOrder { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private String chef; 18 | private Long price; 19 | private String state; 20 | } 21 | -------------------------------------------------------------------------------- /section-10/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha-${server.port} 2 | waiter.url=http://waiter-service 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | 7 | spring.rabbitmq.host=localhost 8 | spring.rabbitmq.port=5672 9 | spring.rabbitmq.username=guest 10 | spring.rabbitmq.password=guest 11 | 12 | spring.cloud.stream.bindinds.default.binder=rabbit 13 | spring.cloud.stream.binders.rabbit.type=rabbit 14 | 15 | spring.cloud.stream.bindings.takeoutFood.group=customer-service 16 | 17 | spring.sleuth.sampler.probability=1.0 18 | spring.zipkin.baseUrl=http://localhost:9411 19 | spring.zipkin.sender.type: web -------------------------------------------------------------------------------- /section-10/customer-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=customer-service 2 | 3 | spring.cloud.zookeeper.config.enabled=true 4 | spring.cloud.zookeeper.connect-string=localhost:2181 5 | -------------------------------------------------------------------------------- /section-10/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-10/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | @Autowired 17 | private Waiter waiter; 18 | 19 | @Override 20 | public void run(ApplicationArguments args) throws Exception { 21 | TakeOutOrder order = TakeOutOrder.builder() 22 | .customer("Steve") 23 | .waiter(waiter.getWaiterName()) 24 | .items("Hamburger") 25 | .price(1000L) 26 | .state("I") 27 | .createTime(new Date()) 28 | .modifyTime(new Date()).build(); 29 | orderRepository.save(order); 30 | 31 | order = TakeOutOrder.builder() 32 | .customer("Bruce") 33 | .waiter(waiter.getWaiterName()) 34 | .items("Sandwich") 35 | .price(1000L) 36 | .state("I") 37 | .createTime(new Date()) 38 | .modifyTime(new Date()).build(); 39 | orderRepository.save(order); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Input 10 | SubscribableChannel finishedOrders(); 11 | @Output 12 | MessageChannel orderRequests(); 13 | @Output 14 | MessageChannel takeoutFood(); 15 | } 16 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/Waiter.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.cloud.context.config.annotation.RefreshScope; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | @RefreshScope 10 | @Data 11 | public class Waiter { 12 | @Value("${prefix.name}") 13 | private String prefix; 14 | @Value("${random.int}") 15 | private int number; 16 | 17 | public String getWaiterName() { 18 | return prefix + "-" + number; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.stream.annotation.EnableBinding; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient 10 | @EnableBinding(TakeOutStream.class) 11 | public class WaiterServiceApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(WaiterServiceApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private String chef; 32 | private Long price; 33 | private String state; 34 | @Column(updatable = false) 35 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 36 | private Date createTime; 37 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 38 | private Date modifyTime; 39 | } 40 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS 2 | management.endpoints.web.exposure.include=health,refresh 3 | 4 | spring.rabbitmq.host=localhost 5 | spring.rabbitmq.port=5672 6 | spring.rabbitmq.username=guest 7 | spring.rabbitmq.password=guest 8 | 9 | spring.cloud.stream.bindinds.default.binder=rabbit 10 | spring.cloud.stream.binders.rabbit.type=rabbit 11 | 12 | spring.cloud.stream.bindings.finishedOrders.group=waiter-service 13 | 14 | spring.sleuth.sampler.percentage=1.0 15 | spring.zipkin.baseUrl=http://localhost:9411 16 | spring.zipkin.sender.type: web -------------------------------------------------------------------------------- /section-10/waiter-service/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | spring.application.name=waiter-service 2 | 3 | spring.cloud.zookeeper.config.enabled=true 4 | spring.cloud.zookeeper.connect-string=localhost:2181 5 | -------------------------------------------------------------------------------- /section-10/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-11/README.md: -------------------------------------------------------------------------------- 1 | # Section 11 2 | 3 | 容器化整个服务 4 | 5 | * 增加Dockerfile,将服务打包为Docker镜像 6 | * 修改程序配置,适应容器环境 7 | * 增加docker-compose.yml,演示Docker Compose 8 | 9 | 执行命令打包: 10 | ``` 11 | mvn clean package docker:build -Dmaven.test.skip 12 | ``` 13 | 14 | 通过docker命令启动: 15 | ``` 16 | docker run -d --name rabbit -p 5672:5672 rabbitmq:3.6-management 17 | docker run -d --name zipkin -p 9411:9411 openzipkin/zipkin 18 | docker run -d --name zookeeper -p 2181:2181 zookeeper:3.5 19 | 20 | docker run --link rabbit:rabbit --link zookeeper:zookeeper --link zipkin:zipkin --name waiter-service takeout/waiter-service 21 | docker run --link rabbit:rabbit --link zookeeper:zookeeper --link zipkin:zipkin --name chef-service takeout/chef-service 22 | docker run --link rabbit:rabbit --link zookeeper:zookeeper --link zipkin:zipkin -p 8080:8080 --name customer-service takeout/customer-service 23 | ``` 24 | 25 | 通过docker-compose启动: 26 | ``` 27 | docker-compose -f docker-compose.yml up -d 28 | docker-compose scale chef-service=3 29 | docker-compose logs --tail 10 --follow customer-service 30 | ``` -------------------------------------------------------------------------------- /section-11/chef-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-11/chef-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java:8 2 | EXPOSE 8080 3 | ADD chef-service-0.0.1-SNAPSHOT.jar chef-service.jar 4 | ENTRYPOINT ["java", "-jar","/chef-service.jar"] -------------------------------------------------------------------------------- /section-11/chef-service/src/main/java/takeout/chefservice/ChefServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.cloud.stream.annotation.EnableBinding; 8 | import org.springframework.cloud.stream.annotation.StreamListener; 9 | //import org.springframework.integration.annotation.Transformer; 10 | import org.springframework.messaging.handler.annotation.SendTo; 11 | 12 | @SpringBootApplication 13 | @EnableBinding(TakeOutStream.class) 14 | @Slf4j 15 | public class ChefServiceApplication { 16 | @Value("${chef.name}-${random.int}") 17 | private String chef; 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(ChefServiceApplication.class, args); 21 | } 22 | 23 | @StreamListener("orderRequests") 24 | @SendTo("finishedOrders") 25 | // @Transformer(inputChannel = "orderRequests", outputChannel = "finishedOrders") 26 | public TakeOutOrder processOrder(TakeOutOrder request) { 27 | log.info("Receiving Order: {}", request); 28 | log.info("Cocking order {}...", request.getId()); 29 | try { 30 | Thread.sleep(100); 31 | } catch (InterruptedException e) { 32 | } 33 | request.setChef(chef); 34 | request.setState("C"); 35 | return request; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /section-11/chef-service/src/main/java/takeout/chefservice/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import lombok.Data; 4 | 5 | @Data 6 | public class TakeOutOrder { 7 | private Long id; 8 | private String items; 9 | private String chef; 10 | private String state; 11 | } 12 | -------------------------------------------------------------------------------- /section-11/chef-service/src/main/java/takeout/chefservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Output 10 | MessageChannel finishedOrders(); 11 | @Input 12 | SubscribableChannel orderRequests(); 13 | } 14 | -------------------------------------------------------------------------------- /section-11/chef-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | chef.name: Peter 2 | 3 | server.port: 8080 4 | 5 | spring: 6 | output.ansi.enabled: ALWAYS 7 | 8 | rabbitmq: 9 | host: rabbit 10 | port: 5672 11 | username: guest 12 | password: guest 13 | 14 | cloud: 15 | stream: 16 | bindings: 17 | default.binder: rabbit 18 | orderRequests.group: chef-service 19 | binders.rabbit.type: rabbit 20 | zookeeper.discovery.preferIpAddress: true 21 | inetutils: 22 | ignoredInterfaces: 23 | - docker0 24 | - veth.* 25 | 26 | sleth.sampler.probability: 1.0 27 | 28 | zipkin: 29 | baseUrl: http://zipkin:9411 30 | sender.type: web 31 | -------------------------------------------------------------------------------- /section-11/chef-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application.name: chef-service 3 | 4 | cloud.zookeeper: 5 | config.enabled: true 6 | connect-string: zookeeper:2181 7 | -------------------------------------------------------------------------------- /section-11/chef-service/src/test/java/takeout/chefservice/ChefServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.chefservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ChefServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-11/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-11/customer-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java:8 2 | EXPOSE 8080 3 | ADD customer-service-0.0.1-SNAPSHOT.jar customer-service.jar 4 | ENTRYPOINT ["java", "-jar","/customer-service.jar"] -------------------------------------------------------------------------------- /section-11/customer-service/src/main/java/takeout/customerservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Input 10 | SubscribableChannel takeoutFood(); 11 | } 12 | -------------------------------------------------------------------------------- /section-11/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-11/customer-service/src/main/java/takeout/customerservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class TakeOutOrder { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private String chef; 18 | private Long price; 19 | private String state; 20 | } 21 | -------------------------------------------------------------------------------- /section-11/customer-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | customer.name: Natasha-${server.port} 2 | 3 | waiter.url: http://waiter-service 4 | 5 | server.port: 8080 6 | 7 | spring: 8 | output.ansi.enabled: ALWAYS 9 | 10 | rabbitmq: 11 | host: rabbit 12 | port: 5672 13 | username: guest 14 | password: guest 15 | 16 | cloud: 17 | stream: 18 | bindings: 19 | default.binder: rabbit 20 | takeoutFood.group: customer-service 21 | binders.rabbit.type: rabbit 22 | zookeeper.discovery.preferIpAddress: true 23 | inetutils: 24 | ignoredInterfaces: 25 | - docker0 26 | - veth.* 27 | 28 | sleth.sampler.probability: 1.0 29 | 30 | zipkin: 31 | baseUrl: http://zipkin:9411 32 | sender.type: web 33 | -------------------------------------------------------------------------------- /section-11/customer-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application.name: customer-service 3 | 4 | cloud.zookeeper: 5 | config.enabled: true 6 | connect-string: zookeeper:2181 7 | -------------------------------------------------------------------------------- /section-11/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-11/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | zookeeper: 5 | image: zookeeper:3.5 6 | expose: 7 | - "2181" 8 | 9 | rabbit: 10 | image: rabbitmq:3.6-management 11 | expose: 12 | - "5671-5672" 13 | ports: 14 | - "9888:15672" 15 | 16 | zipkin: 17 | image: openzipkin/zipkin 18 | expose: 19 | - "9411" 20 | ports: 21 | - "9411:9411" 22 | 23 | chef-service: 24 | image: takeout/chef-service 25 | restart: always 26 | depends_on: 27 | - zookeeper 28 | - rabbit 29 | - zipkin 30 | links: 31 | - zookeeper 32 | - rabbit 33 | - zipkin 34 | 35 | customer-service: 36 | image: takeout/customer-service 37 | expose: 38 | - "8080" 39 | ports: 40 | - "8080:8080" 41 | depends_on: 42 | - waiter-service 43 | - chef-service 44 | links: 45 | - zookeeper 46 | - rabbit 47 | - zipkin 48 | 49 | waiter-service: 50 | image: takeout/waiter-service 51 | restart: always 52 | expose: 53 | - "8080" 54 | depends_on: 55 | - zookeeper 56 | - rabbit 57 | - zipkin 58 | links: 59 | - zookeeper 60 | - rabbit 61 | - zipkin 62 | -------------------------------------------------------------------------------- /section-11/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java:8 2 | EXPOSE 8080 3 | ADD waiter-service-0.0.1-SNAPSHOT.jar waiter-service.jar 4 | ENTRYPOINT ["java", "-jar","/waiter-service.jar"] -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/DataInitializerRunner.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.ApplicationArguments; 5 | import org.springframework.boot.ApplicationRunner; 6 | import org.springframework.stereotype.Component; 7 | import takeout.waiterservice.model.TakeOutOrder; 8 | import takeout.waiterservice.repository.TakeOutOrderRepository; 9 | 10 | import java.util.Date; 11 | 12 | @Component 13 | public class DataInitializerRunner implements ApplicationRunner { 14 | @Autowired 15 | private TakeOutOrderRepository orderRepository; 16 | @Autowired 17 | private Waiter waiter; 18 | 19 | @Override 20 | public void run(ApplicationArguments args) throws Exception { 21 | TakeOutOrder order = TakeOutOrder.builder() 22 | .customer("Steve") 23 | .waiter(waiter.getWaiterName()) 24 | .items("Hamburger") 25 | .price(1000L) 26 | .state("I") 27 | .createTime(new Date()) 28 | .modifyTime(new Date()).build(); 29 | orderRepository.save(order); 30 | 31 | order = TakeOutOrder.builder() 32 | .customer("Bruce") 33 | .waiter(waiter.getWaiterName()) 34 | .items("Sandwich") 35 | .price(1000L) 36 | .state("I") 37 | .createTime(new Date()) 38 | .modifyTime(new Date()).build(); 39 | orderRepository.save(order); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/TakeOutStream.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.cloud.stream.annotation.Output; 5 | import org.springframework.messaging.MessageChannel; 6 | import org.springframework.messaging.SubscribableChannel; 7 | 8 | public interface TakeOutStream { 9 | @Input 10 | SubscribableChannel finishedOrders(); 11 | @Output 12 | MessageChannel orderRequests(); 13 | @Output 14 | MessageChannel takeoutFood(); 15 | } 16 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/Waiter.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import lombok.Data; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.cloud.context.config.annotation.RefreshScope; 6 | import org.springframework.stereotype.Component; 7 | 8 | @Component 9 | @RefreshScope 10 | @Data 11 | public class Waiter { 12 | @Value("${prefix.name}") 13 | private String prefix; 14 | @Value("${random.int}") 15 | private int number; 16 | 17 | public String getWaiterName() { 18 | return prefix + "-" + number; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.stream.annotation.EnableBinding; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient 10 | @EnableBinding(TakeOutStream.class) 11 | public class WaiterServiceApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(WaiterServiceApplication.class, args); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private String chef; 32 | private Long price; 33 | private String state; 34 | @Column(updatable = false) 35 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 36 | private Date createTime; 37 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 38 | private Date modifyTime; 39 | } 40 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | prefix.name: Jarvis 2 | 3 | server.port: 8080 4 | 5 | management.endpoints.web.exposure.include: 6 | - health 7 | - refresh 8 | 9 | spring: 10 | output.ansi.enabled: ALWAYS 11 | 12 | rabbitmq: 13 | host: rabbit 14 | port: 5672 15 | username: guest 16 | password: guest 17 | 18 | cloud: 19 | stream: 20 | bindings: 21 | default.binder: rabbit 22 | finishedOrders.group: waiter-service 23 | binders.rabbit.type: rabbit 24 | zookeeper.discovery.preferIpAddress: true 25 | inetutils: 26 | ignoredInterfaces: 27 | - docker0 28 | - veth.* 29 | 30 | sleth.sampler.probability: 1.0 31 | 32 | zipkin: 33 | baseUrl: http://zipkin:9411 34 | sender.type: web 35 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application.name: waiter-service 3 | 4 | cloud.zookeeper: 5 | config.enabled: true 6 | connect-string: zookeeper:2181 7 | -------------------------------------------------------------------------------- /section-11/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-12/README.md: -------------------------------------------------------------------------------- 1 | # Section 12 2 | 3 | 在Kubernetes上运行一个简单的TakeOut示例。 4 | 5 | * 基于Section 06修改代码,去除Spring Cloud相关内容,简化部分代码 6 | * 修改程序配置,适应k8s容器环境 7 | * 修改Docker打包相关配置,将镜像上传至阿里云的私有镜像 8 | * 增加用于本地minikube和阿里云k8s的部署文件 9 | 10 | 执行命令打包: 11 | ``` 12 | mvn clean package docker:build -Dmaven.test.skip 13 | ``` 14 | 15 | 在minikube中执行部署命令: 16 | ``` 17 | kubectl create -f takeout-minikube.yml 18 | ``` 19 | 20 | 部署到阿里云(需要事先在k8s上配置私有镜像的secret): 21 | ``` 22 | kubectl create -f takeout-aliyun.yml 23 | ``` 24 | 25 | 在阿里云上如果部署了Istio,先设置自动注入SideCar: 26 | 27 | ``` 28 | kubectl label namespace default istio-injection=enabled 29 | ``` 30 | 31 | 在`istio`目录中有一些Istio的演示,先运行`kubectl create -f istio-destination.yml`创建Destination,随后再运行其他的Yaml。 32 | 33 | 可以用下面的命令开启Grafana,观察服务的调用情况: 34 | ``` 35 | kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 3000:3000 & 36 | ``` 37 | -------------------------------------------------------------------------------- /section-12/customer-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-12/customer-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java:8 2 | EXPOSE 7080 3 | ADD customer-service-0.0.1-SNAPSHOT.jar customer-service.jar 4 | ENTRYPOINT ["java", "-jar","/customer-service.jar"] -------------------------------------------------------------------------------- /section-12/customer-service/src/main/java/takeout/customerservice/CustomerServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.core.ParameterizedTypeReference; 10 | import org.springframework.http.HttpMethod; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.PostMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | import org.springframework.web.client.RestTemplate; 15 | import org.springframework.web.util.UriComponentsBuilder; 16 | import takeout.customerservice.model.Order; 17 | import takeout.customerservice.model.Payment; 18 | 19 | import java.net.URI; 20 | import java.util.List; 21 | 22 | @SpringBootApplication 23 | @RestController 24 | @Slf4j 25 | public class CustomerServiceApplication { 26 | @Autowired 27 | private RestTemplate restTemplate; 28 | @Value("${waiter.url}") 29 | private String waiterUrl; 30 | @Value("${customer.name}-${random.int}") 31 | private String customer; 32 | 33 | public static void main(String[] args) { 34 | SpringApplication.run(CustomerServiceApplication.class, args); 35 | } 36 | 37 | @Bean 38 | public RestTemplate restTemplate() { 39 | return new RestTemplate(); 40 | } 41 | 42 | @PostMapping("/orders") 43 | public Order createNewOrder() { 44 | URI uri = UriComponentsBuilder.fromHttpUrl(waiterUrl + "/orders").build().toUri(); 45 | Order rawOrder = Order.builder().customer(customer).items("Coffee").price(2000L).build(); 46 | 47 | List orders = restTemplate.exchange(uri, HttpMethod.GET, null, 48 | new ParameterizedTypeReference>() {}).getBody(); 49 | log.info("There are {} orders ahead.", orders.size()); 50 | 51 | Order order = restTemplate.postForObject(uri, rawOrder, Order.class); 52 | log.info("Order created: {}", order); 53 | 54 | return order; 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /section-12/customer-service/src/main/java/takeout/customerservice/model/Order.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | @Builder 12 | public class Order { 13 | private Long id; 14 | private String items; 15 | private String customer; 16 | private String waiter; 17 | private Long price; 18 | private String state; 19 | } 20 | -------------------------------------------------------------------------------- /section-12/customer-service/src/main/java/takeout/customerservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | @Data 9 | @AllArgsConstructor 10 | @NoArgsConstructor 11 | @Builder 12 | public class Payment { 13 | private Long id; 14 | private Long orderId; 15 | private Long price; 16 | private String state; 17 | } 18 | -------------------------------------------------------------------------------- /section-12/customer-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | customer.name=Natasha 2 | waiter.url=http://${WAITER_SERVICE_HOST}:${WAITER_SERVICE_PORT} 3 | 4 | server.port=7080 5 | spring.output.ansi.enabled=ALWAYS 6 | -------------------------------------------------------------------------------- /section-12/customer-service/src/test/java/takeout/customerservice/CustomerServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.customerservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class CustomerServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /section-12/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | customer-service: 5 | image: registry.cn-huhehaote.aliyuncs.com/digitalsonic/customer-service 6 | environment: 7 | - WAITER_URL=http://waiter-service:8080 8 | expose: 9 | - "7080" 10 | ports: 11 | - "7080:7080" 12 | depends_on: 13 | - waiter-service 14 | links: 15 | - waiter-service 16 | 17 | waiter-service: 18 | image: registry.cn-huhehaote.aliyuncs.com/digitalsonic/waiter-service 19 | expose: 20 | - "8080" 21 | -------------------------------------------------------------------------------- /section-12/istio/istio-destination.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: DestinationRule 3 | metadata: 4 | name: customer 5 | spec: 6 | host: customer 7 | subsets: 8 | - name: v1 9 | labels: 10 | version: v1 11 | --- 12 | apiVersion: networking.istio.io/v1alpha3 13 | kind: DestinationRule 14 | metadata: 15 | name: waiter 16 | spec: 17 | host: waiter 18 | subsets: 19 | - name: v1 20 | labels: 21 | version: v1 22 | - name: v2 23 | labels: 24 | version: v2 25 | -------------------------------------------------------------------------------- /section-12/istio/istio-vs-all-v1.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: customer 5 | spec: 6 | hosts: 7 | - customer 8 | http: 9 | - route: 10 | - destination: 11 | host: customer 12 | --- 13 | apiVersion: networking.istio.io/v1alpha3 14 | kind: VirtualService 15 | metadata: 16 | name: waiter 17 | spec: 18 | hosts: 19 | - waiter 20 | http: 21 | - route: 22 | - destination: 23 | host: waiter 24 | subset: v1 25 | -------------------------------------------------------------------------------- /section-12/istio/istio-vs-waiter-abort.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: customer 5 | spec: 6 | hosts: 7 | - customer 8 | http: 9 | - route: 10 | - destination: 11 | host: customer 12 | --- 13 | apiVersion: networking.istio.io/v1alpha3 14 | kind: VirtualService 15 | metadata: 16 | name: waiter 17 | spec: 18 | hosts: 19 | - waiter 20 | http: 21 | - route: 22 | - destination: 23 | host: waiter 24 | subset: v1 25 | weight: 50 26 | - destination: 27 | host: waiter 28 | subset: v2 29 | weight: 50 30 | fault: 31 | abort: 32 | percent: 10 33 | httpStatus: 500 -------------------------------------------------------------------------------- /section-12/istio/istio-vs-waiter-delay.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: customer 5 | spec: 6 | hosts: 7 | - customer 8 | http: 9 | - route: 10 | - destination: 11 | host: customer 12 | --- 13 | apiVersion: networking.istio.io/v1alpha3 14 | kind: VirtualService 15 | metadata: 16 | name: waiter 17 | spec: 18 | hosts: 19 | - waiter 20 | http: 21 | - route: 22 | - destination: 23 | host: waiter 24 | subset: v1 25 | weight: 50 26 | - destination: 27 | host: waiter 28 | subset: v2 29 | weight: 50 30 | fault: 31 | delay: 32 | percent: 10 33 | fixedDelay: 5s -------------------------------------------------------------------------------- /section-12/istio/istio-vs-waiter-percent.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: customer 5 | spec: 6 | hosts: 7 | - customer 8 | http: 9 | - route: 10 | - destination: 11 | host: customer 12 | --- 13 | apiVersion: networking.istio.io/v1alpha3 14 | kind: VirtualService 15 | metadata: 16 | name: waiter 17 | spec: 18 | hosts: 19 | - waiter 20 | http: 21 | - route: 22 | - destination: 23 | host: waiter 24 | subset: v1 25 | weight: 10 26 | - destination: 27 | host: waiter 28 | subset: v2 29 | weight: 90 30 | -------------------------------------------------------------------------------- /section-12/istio/istio-vs-waiter-v2.yml: -------------------------------------------------------------------------------- 1 | apiVersion: networking.istio.io/v1alpha3 2 | kind: VirtualService 3 | metadata: 4 | name: customer 5 | spec: 6 | hosts: 7 | - customer 8 | http: 9 | - route: 10 | - destination: 11 | host: customer 12 | --- 13 | apiVersion: networking.istio.io/v1alpha3 14 | kind: VirtualService 15 | metadata: 16 | name: waiter 17 | spec: 18 | hosts: 19 | - waiter 20 | http: 21 | - route: 22 | - destination: 23 | host: waiter 24 | subset: v2 25 | -------------------------------------------------------------------------------- /section-12/takeout-aliyun.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: waiter 5 | spec: 6 | selector: 7 | app: waiter-service 8 | ports: 9 | - name: http 10 | port: 8080 11 | --- 12 | apiVersion: extensions/v1beta1 13 | kind: Deployment 14 | metadata: 15 | name: waiter-service-v1 16 | spec: 17 | replicas: 1 18 | template: 19 | metadata: 20 | labels: 21 | app: waiter-service 22 | version: v1 23 | spec: 24 | containers: 25 | - name: waiter-service 26 | image: registry-vpc.cn-huhehaote.aliyuncs.com/digitalsonic/waiter-service 27 | imagePullPolicy: IfNotPresent 28 | ports: 29 | - containerPort: 8080 30 | env: 31 | - name: WAITER_NAME 32 | value: "Mark I" 33 | imagePullSecrets: 34 | - name: digitalsonic 35 | --- 36 | apiVersion: extensions/v1beta1 37 | kind: Deployment 38 | metadata: 39 | name: waiter-service-v2 40 | spec: 41 | replicas: 1 42 | template: 43 | metadata: 44 | labels: 45 | app: waiter-service 46 | version: v2 47 | spec: 48 | containers: 49 | - name: waiter-service 50 | image: registry-vpc.cn-huhehaote.aliyuncs.com/digitalsonic/waiter-service 51 | imagePullPolicy: IfNotPresent 52 | ports: 53 | - containerPort: 8080 54 | env: 55 | - name: WAITER_NAME 56 | value: "Mark II" 57 | imagePullSecrets: 58 | - name: digitalsonic 59 | --- 60 | apiVersion: v1 61 | kind: Service 62 | metadata: 63 | name: customer 64 | spec: 65 | selector: 66 | app: customer-service 67 | ports: 68 | - name: http 69 | port: 7080 70 | --- 71 | apiVersion: extensions/v1beta1 72 | kind: Deployment 73 | metadata: 74 | name: customer-service 75 | spec: 76 | replicas: 1 77 | template: 78 | metadata: 79 | labels: 80 | app: customer-service 81 | version: v1 82 | spec: 83 | containers: 84 | - name: customer-service 85 | image: registry-vpc.cn-huhehaote.aliyuncs.com/digitalsonic/customer-service 86 | imagePullPolicy: IfNotPresent 87 | ports: 88 | - containerPort: 7080 89 | imagePullSecrets: 90 | - name: digitalsonic 91 | 92 | -------------------------------------------------------------------------------- /section-12/takeout-minikube.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: waiter 5 | spec: 6 | selector: 7 | app: waiter-service 8 | ports: 9 | - name: http 10 | port: 8080 11 | --- 12 | apiVersion: extensions/v1beta1 13 | kind: Deployment 14 | metadata: 15 | name: waiter-service-v1 16 | spec: 17 | replicas: 1 18 | template: 19 | metadata: 20 | labels: 21 | app: waiter-service 22 | version: v1 23 | spec: 24 | containers: 25 | - name: waiter-service 26 | image: registry.cn-huhehaote.aliyuncs.com/digitalsonic/waiter-service 27 | imagePullPolicy: IfNotPresent 28 | ports: 29 | - containerPort: 8080 30 | env: 31 | - name: WAITER_NAME 32 | value: "Mark I" 33 | --- 34 | apiVersion: extensions/v1beta1 35 | kind: Deployment 36 | metadata: 37 | name: waiter-service-v2 38 | spec: 39 | replicas: 1 40 | template: 41 | metadata: 42 | labels: 43 | app: waiter-service 44 | version: v2 45 | spec: 46 | containers: 47 | - name: waiter-service 48 | image: registry.cn-huhehaote.aliyuncs.com/digitalsonic/waiter-service 49 | imagePullPolicy: IfNotPresent 50 | ports: 51 | - containerPort: 8080 52 | env: 53 | - name: WAITER_NAME 54 | value: "Mark II" 55 | --- 56 | apiVersion: v1 57 | kind: Service 58 | metadata: 59 | name: customer 60 | spec: 61 | selector: 62 | app: customer-service 63 | type: NodePort 64 | ports: 65 | - name: http 66 | port: 7080 67 | --- 68 | apiVersion: extensions/v1beta1 69 | kind: Deployment 70 | metadata: 71 | name: customer-service 72 | spec: 73 | replicas: 1 74 | template: 75 | metadata: 76 | labels: 77 | app: customer-service 78 | version: v1 79 | spec: 80 | containers: 81 | - name: customer-service 82 | image: registry.cn-huhehaote.aliyuncs.com/digitalsonic/customer-service 83 | imagePullPolicy: IfNotPresent 84 | ports: 85 | - containerPort: 7080 86 | -------------------------------------------------------------------------------- /section-12/waiter-service/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM java:8 2 | EXPOSE 8080 3 | ADD waiter-service-0.0.1-SNAPSHOT.jar waiter-service.jar 4 | ENTRYPOINT ["java", "-jar","/waiter-service.jar"] -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/WaiterServiceApplication.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class WaiterServiceApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(WaiterServiceApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/controller/ExceptionControllerAdvice.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseStatus; 7 | 8 | import javax.persistence.EntityNotFoundException; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | 12 | @ControllerAdvice 13 | public class ExceptionControllerAdvice { 14 | @ExceptionHandler(EntityNotFoundException.class) 15 | @ResponseStatus(HttpStatus.NOT_FOUND) 16 | public Map entityNotFound(EntityNotFoundException e) { 17 | return Collections.singletonMap("message", e.getMessage()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.DeleteMapping; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseStatus; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import takeout.waiterservice.model.TakeOutOrder; 14 | import takeout.waiterservice.service.OrderService; 15 | 16 | import java.util.List; 17 | 18 | @RestController 19 | @RequestMapping("/orders") 20 | public class OrderController { 21 | @Autowired 22 | private OrderService orderService; 23 | 24 | @GetMapping("/{id}") 25 | public TakeOutOrder getOrder(@PathVariable Long id) { 26 | return orderService.getOrder(id); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public List deleteOrder(@PathVariable Long id) { 31 | orderService.deleteOrder(id); 32 | return orderService.getAllOrders(); 33 | } 34 | 35 | @PostMapping 36 | @ResponseStatus(HttpStatus.CREATED) 37 | public TakeOutOrder createOrder(@RequestBody TakeOutOrder order) { 38 | return orderService.createOrder(order); 39 | } 40 | 41 | @GetMapping 42 | public List getAllOrder() { 43 | return orderService.getAllOrders(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/controller/PaymentController.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | import takeout.waiterservice.model.Payment; 12 | import takeout.waiterservice.service.PaymentService; 13 | 14 | @RestController 15 | @RequestMapping("/orders/{id}/payment") 16 | public class PaymentController { 17 | @Autowired 18 | private PaymentService paymentService; 19 | 20 | @RequestMapping(method = RequestMethod.POST) 21 | @ResponseStatus(HttpStatus.CREATED) 22 | public Payment createPayment(@PathVariable Long id) { 23 | return paymentService.createPayment(id); 24 | } 25 | 26 | @RequestMapping(method = RequestMethod.GET) 27 | public Payment getPayment(@PathVariable Long id) { 28 | return paymentService.getPayment(id); 29 | } 30 | 31 | @RequestMapping(method = RequestMethod.PUT) 32 | public Payment updatePayment(@PathVariable Long id, @RequestBody Payment payment) { 33 | return paymentService.updatePayment(id, payment); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/model/Payment.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.GeneratedValue; 12 | import javax.persistence.Id; 13 | import javax.xml.bind.annotation.XmlRootElement; 14 | import java.util.Date; 15 | 16 | @Entity 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | @Builder 21 | @XmlRootElement 22 | public class Payment { 23 | @Id 24 | @GeneratedValue 25 | private Long id; 26 | @Column(updatable = false) 27 | private Long orderId; 28 | private Long price; 29 | private String state; 30 | @Column(updatable = false) 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private Date createTime; 33 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 34 | private Date modifyTime; 35 | } 36 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/model/TakeOutOrder.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFormat; 4 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | import javax.persistence.Column; 11 | import javax.persistence.Entity; 12 | import javax.persistence.GeneratedValue; 13 | import javax.persistence.Id; 14 | import javax.xml.bind.annotation.XmlRootElement; 15 | import java.util.Date; 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Builder 21 | @JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "fieldHandler"}) 22 | @Entity 23 | @XmlRootElement 24 | public class TakeOutOrder { 25 | @Id 26 | @GeneratedValue 27 | private Long id; 28 | private String items; 29 | private String customer; 30 | private String waiter; 31 | private Long price; 32 | private String state; 33 | @Column(updatable = false) 34 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 35 | private Date createTime; 36 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 37 | private Date modifyTime; 38 | } 39 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/repository/PaymentRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.Payment; 5 | 6 | import java.util.Optional; 7 | 8 | public interface PaymentRepository extends JpaRepository { 9 | Optional findByOrderId(Long orderId); 10 | } 11 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/repository/TakeOutOrderRepository.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import takeout.waiterservice.model.TakeOutOrder; 5 | 6 | import java.util.List; 7 | 8 | public interface TakeOutOrderRepository extends JpaRepository { 9 | List findByCustomerOrderById(String customer); 10 | } 11 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/java/takeout/waiterservice/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.stereotype.Service; 6 | import takeout.waiterservice.model.TakeOutOrder; 7 | import takeout.waiterservice.repository.TakeOutOrderRepository; 8 | 9 | import javax.persistence.EntityNotFoundException; 10 | import java.util.Date; 11 | import java.util.List; 12 | 13 | @Service 14 | public class OrderService { 15 | @Autowired 16 | private TakeOutOrderRepository orderRepository; 17 | @Value("${waiter.name}-${random.int}") 18 | private String waiterName; 19 | 20 | public List getAllOrders() { 21 | return orderRepository.findAll(); 22 | } 23 | 24 | public TakeOutOrder getOrder(Long id) { 25 | return id == null ? null : orderRepository.findById(id) 26 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")); 27 | } 28 | 29 | public void deleteOrder(Long id) { 30 | orderRepository.delete( 31 | orderRepository.findById(id) 32 | .orElseThrow(() -> new EntityNotFoundException("Order " + id + " is NOT found.")) 33 | ); 34 | } 35 | 36 | public TakeOutOrder createOrder(TakeOutOrder order) { 37 | if (order != null) { 38 | order.setId(null); 39 | order.setWaiter(waiterName); 40 | order.setState("I"); 41 | order.setCreateTime(new Date()); 42 | order.setModifyTime(new Date()); 43 | orderRepository.save(order); 44 | } 45 | return order; 46 | } 47 | 48 | public void payOrder(Long id) { 49 | TakeOutOrder order = orderRepository.getOne(id); 50 | order.setState("P"); 51 | order.setModifyTime(new Date()); 52 | orderRepository.save(order); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /section-12/waiter-service/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.output.ansi.enabled=ALWAYS 2 | waiter.name=Tony -------------------------------------------------------------------------------- /section-12/waiter-service/src/test/java/takeout/waiterservice/WaiterServiceApplicationTests.java: -------------------------------------------------------------------------------- 1 | package takeout.waiterservice; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class WaiterServiceApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------