├── reactive-spring-css ├── customer-service │ ├── src │ │ ├── test │ │ │ └── resources │ │ │ │ └── application.properties │ │ └── main │ │ │ ├── resources │ │ │ ├── bootstrap.yml │ │ │ └── application.yml │ │ │ └── java │ │ │ └── com │ │ │ └── springcss │ │ │ └── customer │ │ │ ├── event │ │ │ ├── AccountChangedChannel.java │ │ │ └── ReactiveAccountChangedSink.java │ │ │ ├── repository │ │ │ ├── CustomerTicketRepository.java │ │ │ └── redis │ │ │ │ ├── AccountRedisRepository.java │ │ │ │ └── AccountRedisRepositoryImpl.java │ │ │ ├── InitDatabase.java │ │ │ ├── client │ │ │ ├── ReactiveOrderClient.java │ │ │ ├── AccountMapper.java │ │ │ ├── OrderMapper.java │ │ │ └── ReactiveAccountClient.java │ │ │ ├── CustomerApplication.java │ │ │ ├── controller │ │ │ └── CustomerController.java │ │ │ ├── domain │ │ │ └── CustomerTicket.java │ │ │ └── service │ │ │ └── CustomerTicketService.java │ └── pom.xml ├── order-service │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ ├── bootstrap.yml │ │ │ └── application.yml │ │ │ └── java │ │ │ └── com │ │ │ └── springcss │ │ │ └── order │ │ │ ├── OrderApplication.java │ │ │ ├── repository │ │ │ └── ReactiveOrderRepository.java │ │ │ ├── service │ │ │ ├── OrderService.java │ │ │ └── StubOrderService.java │ │ │ ├── controller │ │ │ ├── OrderHandler.java │ │ │ ├── OrderRouter.java │ │ │ ├── OrderController.java │ │ │ └── StubOrderController.java │ │ │ ├── InitDatabase.java │ │ │ └── domain │ │ │ └── Order.java │ └── pom.xml ├── account-service │ ├── src │ │ ├── main │ │ │ ├── resources │ │ │ │ ├── bootstrap.yml │ │ │ │ └── application.yml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── springcss │ │ │ │ └── account │ │ │ │ ├── AccountApplication.java │ │ │ │ ├── repository │ │ │ │ └── ReactiveAccountRepository.java │ │ │ │ ├── InitDatabase.java │ │ │ │ ├── domain │ │ │ │ └── Account.java │ │ │ │ ├── controller │ │ │ │ └── AccountController.java │ │ │ │ ├── event │ │ │ │ └── ReactiveAccountChangedSource.java │ │ │ │ └── service │ │ │ │ └── AccountService.java │ │ └── test │ │ │ └── java │ │ │ └── com │ │ │ └── springcss │ │ │ └── account │ │ │ ├── ApplicationContextTests.java │ │ │ ├── ReactorTests.java │ │ │ ├── AccountServiceTest.java │ │ │ ├── EmbeddedAccountRepositoryTest.java │ │ │ ├── LiveAccountRepositoryTest.java │ │ │ └── AccountControllerTest.java │ └── pom.xml ├── message │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── com │ │ │ └── springcss │ │ │ └── message │ │ │ ├── AccountChannels.java │ │ │ ├── AccountChangedEvent.java │ │ │ └── AccountMessage.java │ └── pom.xml └── pom.xml └── r2dbc-demo ├── src └── main │ ├── resources │ ├── application.yml │ └── account_ddl.sql │ └── java │ └── com │ └── springcss │ └── r2dbc │ └── demo │ ├── R2dbcApplication.java │ ├── repository │ └── ReactiveAccountRepository.java │ ├── domain │ └── Account.java │ └── controller │ └── AccountController.java └── pom.xml /reactive-spring-css/customer-service/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | #springcss.order.point = 10 -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: orderservice 4 | profiles: 5 | active: 6 | default -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: accountservice 4 | profiles: 5 | active: 6 | default -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: customerservice 4 | profiles: 5 | active: 6 | default -------------------------------------------------------------------------------- /r2dbc-demo/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | 2 | spring: 3 | r2dbc: 4 | url: r2dbcs:mysql://119.3.52.175:3306/r2dbcs_account 5 | username: root 6 | password: 1qazxsw2#edc 7 | -------------------------------------------------------------------------------- /reactive-spring-css/message/src/main/java/com/springcss/message/AccountChannels.java: -------------------------------------------------------------------------------- 1 | package com.springcss.message; 2 | 3 | public class AccountChannels { 4 | 5 | public static final String SPRINGCSS_ACCOUNT_TOPIC = "springcss.account.topic"; 6 | 7 | public static final String SPRINGCSS_ACCOUNT_QUEUE = "springcss.account.queue"; 8 | } 9 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | 4 | logging: 5 | level: 6 | com.netflix: WARN 7 | org.springframework.web: WARN 8 | com.springcss: INFO 9 | 10 | 11 | management: 12 | endpoints: 13 | web: 14 | exposure: 15 | include: "*" 16 | endpoint: 17 | health: 18 | show-details: always 19 | 20 | -------------------------------------------------------------------------------- /r2dbc-demo/src/main/java/com/springcss/r2dbc/demo/R2dbcApplication.java: -------------------------------------------------------------------------------- 1 | package com.springcss.r2dbc.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class R2dbcApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(R2dbcApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/OrderApplication.java: -------------------------------------------------------------------------------- 1 | package com.springcss.order; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class OrderApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(OrderApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /r2dbc-demo/src/main/resources/account_ddl.sql: -------------------------------------------------------------------------------- 1 | 2 | USE `r2dbcs_account`; 3 | 4 | DROP TABLE IF EXISTS `ACCOUNT`; 5 | CREATE TABLE `ACCOUNT`( 6 | `ID` bigint(20) NOT NULL AUTO_INCREMENT, 7 | `ACCOUNT_CODE` varchar(100) NOT NULL, 8 | `ACCOUNT_NAME` varchar(100) NOT NULL, 9 | PRIMARY KEY (`ID`) 10 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 11 | 12 | INSERT INTO `account` VALUES ('1', 'account1', 'name1'); 13 | INSERT INTO `account` VALUES ('2', 'account2', 'name2'); -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/repository/ReactiveOrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.springcss.order.repository; 2 | 3 | import org.springframework.data.mongodb.repository.ReactiveMongoRepository; 4 | 5 | import com.springcss.order.domain.Order; 6 | 7 | import reactor.core.publisher.Mono; 8 | 9 | public interface ReactiveOrderRepository extends ReactiveMongoRepository { 10 | 11 | Mono getOrderByOrderNumber(String orderNumber); 12 | } 13 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/event/AccountChangedChannel.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.event; 2 | 3 | import org.springframework.cloud.stream.annotation.Input; 4 | import org.springframework.messaging.SubscribableChannel; 5 | 6 | public interface AccountChangedChannel { 7 | 8 | String ACCOUNT_CHANGED = "accountChangedChannel"; 9 | 10 | @Input(AccountChangedChannel.ACCOUNT_CHANGED) 11 | SubscribableChannel accountChangedChannel(); 12 | } 13 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/repository/CustomerTicketRepository.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.mongodb.repository.ReactiveMongoRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import com.springcss.customer.domain.CustomerTicket; 9 | 10 | @Repository 11 | public interface CustomerTicketRepository extends ReactiveMongoRepository { 12 | 13 | List getCustomerTicketByOrderNumber(String orderNumber); 14 | } 15 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/repository/redis/AccountRedisRepository.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.repository.redis; 2 | 3 | 4 | import com.springcss.customer.client.AccountMapper; 5 | 6 | import reactor.core.publisher.Mono; 7 | 8 | public interface AccountRedisRepository { 9 | Mono saveAccount(AccountMapper account); 10 | 11 | Mono updateAccount(AccountMapper account); 12 | 13 | Mono deleteAccount(String accountId); 14 | 15 | Mono findAccountById(String accountId); 16 | } 17 | 18 | 19 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/java/com/springcss/account/AccountApplication.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.stream.annotation.EnableBinding; 6 | import org.springframework.cloud.stream.messaging.Source; 7 | 8 | @SpringBootApplication 9 | @EnableBinding(Source.class) 10 | public class AccountApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(AccountApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/InitDatabase.java: -------------------------------------------------------------------------------- 1 | 2 | package com.springcss.customer; 3 | 4 | import org.springframework.boot.CommandLineRunner; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.data.mongodb.core.MongoOperations; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.springcss.customer.domain.CustomerTicket; 10 | 11 | @Component 12 | public class InitDatabase { 13 | @Bean 14 | CommandLineRunner init(MongoOperations operations) { 15 | return args -> { 16 | operations.dropCollection(CustomerTicket.class); 17 | }; 18 | } 19 | } -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.springcss.order.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Service; 5 | 6 | import com.springcss.order.domain.Order; 7 | import com.springcss.order.repository.ReactiveOrderRepository; 8 | 9 | import reactor.core.publisher.Mono; 10 | 11 | @Service 12 | public class OrderService { 13 | 14 | @Autowired 15 | private ReactiveOrderRepository orderRepository; 16 | 17 | public Mono getOrderByOrderNumber(String orderNumber) { 18 | return orderRepository.getOrderByOrderNumber(orderNumber); 19 | } 20 | } 21 | 22 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/java/com/springcss/account/repository/ReactiveAccountRepository.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account.repository; 2 | 3 | import org.springframework.data.mongodb.repository.ReactiveMongoRepository; 4 | import org.springframework.data.repository.query.ReactiveQueryByExampleExecutor; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.springcss.account.domain.Account; 8 | 9 | import reactor.core.publisher.Mono; 10 | 11 | @Repository 12 | public interface ReactiveAccountRepository extends 13 | ReactiveMongoRepository, ReactiveQueryByExampleExecutor { 14 | 15 | Mono findAccountByAccountName(String accountName); 16 | } 17 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/test/java/com/springcss/account/ApplicationContextTests.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | @SpringBootTest 12 | @RunWith(SpringRunner.class) 13 | public class ApplicationContextTests { 14 | 15 | @Autowired 16 | private ApplicationContext applicationContext; 17 | 18 | @Test 19 | public void testContextLoads() throws Throwable { 20 | Assert.assertNotNull(this.applicationContext); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /r2dbc-demo/src/main/java/com/springcss/r2dbc/demo/repository/ReactiveAccountRepository.java: -------------------------------------------------------------------------------- 1 | package com.springcss.r2dbc.demo.repository; 2 | 3 | import org.springframework.data.r2dbc.repository.Query; 4 | import org.springframework.data.r2dbc.repository.R2dbcRepository; 5 | import org.springframework.data.repository.reactive.ReactiveCrudRepository; 6 | 7 | import com.springcss.r2dbc.demo.domain.Account; 8 | 9 | import reactor.core.publisher.Mono; 10 | 11 | public interface ReactiveAccountRepository extends R2dbcRepository { 12 | 13 | @Query("insert into ACCOUNT (ACCOUNT_CODE, ACCOUNT_NAME) values (:accountCode,:accountName)") 14 | Mono addAccount(String accountCode, String accountName); 15 | 16 | @Query("SELECT * FROM account WHERE id =:id") 17 | Mono getAccountById(Long id); 18 | } 19 | -------------------------------------------------------------------------------- /reactive-spring-css/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.springcss 6 | 0.0.1-SNAPSHOT 7 | reactive-springcss-parent-pom 8 | pom 9 | 10 | reactive-springcss-parent-pom 11 | 12 | 13 | org.springframework.boot 14 | spring-boot-starter-parent 15 | 2.1.13.RELEASE 16 | 17 | 18 | 19 | customer-service 20 | account-service 21 | order-service 22 | message 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8083 3 | 4 | 5 | spring: 6 | cloud: 7 | stream: 8 | bindings: 9 | default: 10 | content-type: application/json 11 | binder: rabbitmq 12 | accountChangedChannel: 13 | destination: account-destination 14 | group: customerGroup 15 | # consumer: 16 | # partitioned: true 17 | # instanceIndex: 1 18 | # instanceCount: 2 19 | binders: 20 | rabbitmq: 21 | type: rabbit 22 | environment: 23 | spring: 24 | rabbitmq: 25 | host: 127.0.0.1 26 | port: 5672 27 | username: guest 28 | password: guest 29 | virtual-host: / 30 | 31 | logging: 32 | level: 33 | com.netflix: WARN 34 | org.springframework.web: WARN 35 | com.springcss: INFO 36 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/controller/OrderHandler.java: -------------------------------------------------------------------------------- 1 | package com.springcss.order.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.web.reactive.function.server.ServerRequest; 6 | import org.springframework.web.reactive.function.server.ServerResponse; 7 | 8 | import com.springcss.order.domain.Order; 9 | import com.springcss.order.service.OrderService; 10 | 11 | import reactor.core.publisher.Mono; 12 | 13 | @Configuration 14 | public class OrderHandler { 15 | 16 | @Autowired 17 | private OrderService orderService; 18 | 19 | public Mono getOrderByOrderNumber(ServerRequest request) { 20 | String orderNumber = request.pathVariable("orderNumber"); 21 | 22 | return ServerResponse.ok().body(this.orderService.getOrderByOrderNumber(orderNumber), Order.class); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/InitDatabase.java: -------------------------------------------------------------------------------- 1 | 2 | package com.springcss.order; 3 | 4 | import java.util.UUID; 5 | 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.data.mongodb.core.MongoOperations; 9 | import org.springframework.stereotype.Component; 10 | 11 | import com.springcss.order.domain.Order; 12 | 13 | @Component 14 | public class InitDatabase { 15 | @Bean 16 | CommandLineRunner init(MongoOperations operations) { 17 | return args -> { 18 | operations.dropCollection(Order.class); 19 | 20 | operations.insert(new Order("O_" + UUID.randomUUID().toString(), "Order001", "deliveryAddress1", "")); 21 | operations.insert(new Order("O_" + UUID.randomUUID().toString(), "Order002", "deliveryAddress2", "")); 22 | 23 | operations.findAll(Order.class).forEach( 24 | order -> { 25 | System.out.println(order.getId() 26 | );} 27 | ); 28 | }; 29 | } 30 | } -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/java/com/springcss/account/InitDatabase.java: -------------------------------------------------------------------------------- 1 | 2 | package com.springcss.account; 3 | 4 | import java.util.UUID; 5 | 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.data.mongodb.core.MongoOperations; 9 | import org.springframework.stereotype.Component; 10 | 11 | import com.springcss.account.domain.Account; 12 | 13 | @Component 14 | public class InitDatabase { 15 | @Bean 16 | CommandLineRunner init(MongoOperations operations) { 17 | return args -> { 18 | operations.dropCollection(Account.class); 19 | 20 | operations.insert(new Account("A_" + UUID.randomUUID().toString(),"account1", "jianxiang1")); 21 | operations.insert(new Account("A_" + UUID.randomUUID().toString(),"account2", "jianxiang")); 22 | 23 | operations.findAll(Account.class).forEach( 24 | account -> { 25 | System.out.println(account.getId() 26 | );} 27 | ); 28 | }; 29 | } 30 | } -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/controller/OrderRouter.java: -------------------------------------------------------------------------------- 1 | package com.springcss.order.controller; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.http.MediaType; 6 | import org.springframework.web.reactive.function.server.RequestPredicates; 7 | import org.springframework.web.reactive.function.server.RouterFunction; 8 | import org.springframework.web.reactive.function.server.RouterFunctions; 9 | import org.springframework.web.reactive.function.server.ServerResponse; 10 | 11 | @Configuration 12 | public class OrderRouter { 13 | 14 | @Bean 15 | public RouterFunction routeOrder(OrderHandler orderHandler) { 16 | 17 | return RouterFunctions.route( 18 | RequestPredicates.GET("/orders/{orderNumber}") 19 | .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), 20 | orderHandler::getOrderByOrderNumber); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /reactive-spring-css/message/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.springcss 8 | message 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | message 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.13.RELEASE 18 | 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-test 25 | test 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/client/ReactiveOrderClient.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.client; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.reactive.function.client.WebClient; 7 | 8 | import reactor.core.publisher.Mono; 9 | 10 | @Component 11 | public class ReactiveOrderClient { 12 | 13 | private static final Logger logger = LoggerFactory.getLogger(ReactiveOrderClient.class); 14 | 15 | public Mono getOrderByOrderNumber(String orderNumber) { 16 | logger.debug("Get order from remote: {}", orderNumber); 17 | 18 | Mono orderMono = WebClient.create() 19 | .get() 20 | .uri("localhost:8081/orders/{orderNumber}", orderNumber) 21 | .retrieve() 22 | .bodyToMono(OrderMapper.class).log("getOrderFromRemote"); 23 | 24 | return orderMono; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | //package com.springcss.order.controller; 2 | // 3 | //import org.springframework.beans.factory.annotation.Autowired; 4 | //import org.springframework.web.bind.annotation.GetMapping; 5 | //import org.springframework.web.bind.annotation.PathVariable; 6 | //import org.springframework.web.bind.annotation.RequestMapping; 7 | //import org.springframework.web.bind.annotation.RestController; 8 | // 9 | //import com.springcss.order.domain.Order; 10 | //import com.springcss.order.service.OrderService; 11 | // 12 | //import reactor.core.publisher.Mono; 13 | // 14 | //@RestController 15 | //@RequestMapping(value="orders") 16 | //public class OrderController { 17 | // 18 | // @Autowired 19 | // private OrderService orderService; 20 | // 21 | // @GetMapping(value = "/{orderNumber}") 22 | // public Mono getOrderByOrderNumber(@PathVariable String orderNumber) { 23 | // 24 | // Mono order = orderService.getOrderByOrderNumber(orderNumber); 25 | // 26 | // return order; 27 | // } 28 | //} 29 | -------------------------------------------------------------------------------- /r2dbc-demo/src/main/java/com/springcss/r2dbc/demo/domain/Account.java: -------------------------------------------------------------------------------- 1 | package com.springcss.r2dbc.demo.domain; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.relational.core.mapping.Table; 5 | 6 | @Table("account") 7 | public class Account { 8 | @Id 9 | private Long id; 10 | private String accountCode; 11 | private String accountName; 12 | 13 | public Account() { 14 | super(); 15 | } 16 | 17 | public Account(Long id, String accountCode, String accountName) { 18 | super(); 19 | this.id = id; 20 | this.accountCode = accountCode; 21 | this.accountName = accountName; 22 | } 23 | 24 | public Long getId() { 25 | return id; 26 | } 27 | public void setId(Long id) { 28 | this.id = id; 29 | } 30 | public String getAccountCode() { 31 | return accountCode; 32 | } 33 | public void setAccountCode(String accountCode) { 34 | this.accountCode = accountCode; 35 | } 36 | public String getAccountName() { 37 | return accountName; 38 | } 39 | public void setAccountName(String accountName) { 40 | this.accountName = accountName; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8082 3 | 4 | management: 5 | endpoints: 6 | web: 7 | exposure: 8 | include: "*" 9 | endpoint: 10 | health: 11 | show-details: always 12 | 13 | spring: 14 | cloud: 15 | stream: 16 | bindings: 17 | default: 18 | content-type: application/json 19 | binder: rabbitmq 20 | output: 21 | destination: account-destination 22 | group: customerGroup 23 | # producer: 24 | # partitionKeyExpression: payload.accountMessage.isEndWithDigit() 25 | # partitionCount: 2 26 | binders: 27 | rabbitmq: 28 | type: rabbit 29 | environment: 30 | spring: 31 | rabbitmq: 32 | host: 127.0.0.1 33 | port: 5672 34 | username: guest 35 | password: guest 36 | virtual-host: / 37 | 38 | logging: 39 | level: 40 | com.netflix: WARN 41 | org.springframework.web: WARN 42 | com.springcss: INFO 43 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/client/AccountMapper.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.client; 2 | 3 | import java.io.Serializable; 4 | 5 | public class AccountMapper implements Serializable { 6 | private static final long serialVersionUID = 1L; 7 | 8 | private String id; 9 | private String accountCode; 10 | private String accountName; 11 | 12 | public AccountMapper() { 13 | super(); 14 | } 15 | 16 | public AccountMapper(String id, String accountCode, String accountName) { 17 | super(); 18 | this.id = id; 19 | this.accountCode = accountCode; 20 | this.accountName = accountName; 21 | } 22 | 23 | public String getId() { 24 | return id; 25 | } 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | public String getAccountCode() { 30 | return accountCode; 31 | } 32 | public void setAccountCode(String accountCode) { 33 | this.accountCode = accountCode; 34 | } 35 | public String getAccountName() { 36 | return accountName; 37 | } 38 | public void setAccountName(String accountName) { 39 | this.accountName = accountName; 40 | } 41 | } -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/java/com/springcss/account/domain/Account.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account.domain; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | @Document 7 | public class Account { 8 | @Id 9 | private String id; 10 | private String accountCode; 11 | private String accountName; 12 | 13 | public Account() { 14 | super(); 15 | } 16 | 17 | public Account(String id, String accountCode, String accountName) { 18 | super(); 19 | this.id = id; 20 | this.accountCode = accountCode; 21 | this.accountName = accountName; 22 | } 23 | 24 | public String getId() { 25 | return id; 26 | } 27 | public void setId(String id) { 28 | this.id = id; 29 | } 30 | public String getAccountCode() { 31 | return accountCode; 32 | } 33 | public void setAccountCode(String accountCode) { 34 | this.accountCode = accountCode; 35 | } 36 | public String getAccountName() { 37 | return accountName; 38 | } 39 | public void setAccountName(String accountName) { 40 | this.accountName = accountName; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /reactive-spring-css/message/src/main/java/com/springcss/message/AccountChangedEvent.java: -------------------------------------------------------------------------------- 1 | package com.springcss.message; 2 | 3 | import java.io.Serializable; 4 | 5 | public class AccountChangedEvent implements Serializable { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | //事件类型 10 | private String type; 11 | //事件所对应的操作 12 | private String operation; 13 | //事件对应的领域模型 14 | private AccountMessage accountMessage; 15 | 16 | 17 | public AccountChangedEvent() { 18 | super(); 19 | } 20 | 21 | public AccountChangedEvent(String type, String operation, AccountMessage accountMessage) { 22 | super(); 23 | this.type = type; 24 | this.operation = operation; 25 | this.accountMessage = accountMessage; 26 | } 27 | 28 | public String getType() { 29 | return type; 30 | } 31 | 32 | public void setType(String type) { 33 | this.type = type; 34 | } 35 | 36 | public String getOperation() { 37 | return operation; 38 | } 39 | 40 | public void setOperation(String operation) { 41 | this.operation = operation; 42 | } 43 | 44 | public AccountMessage getAccountMessage() { 45 | return accountMessage; 46 | } 47 | 48 | public void setAccountMessage(AccountMessage accountMessage) { 49 | this.accountMessage = accountMessage; 50 | } 51 | } -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/client/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.client; 2 | 3 | import java.io.Serializable; 4 | 5 | public class OrderMapper implements Serializable { 6 | private static final long serialVersionUID = 1L; 7 | 8 | private String id; 9 | private String orderNumber; 10 | private String deliveryAddress; 11 | private String goods; 12 | 13 | public OrderMapper() { 14 | super(); 15 | } 16 | 17 | public OrderMapper(String id, String orderNumber, String deliveryAddress, String goods) { 18 | super(); 19 | this.id = id; 20 | this.orderNumber = orderNumber; 21 | this.deliveryAddress = deliveryAddress; 22 | this.goods = goods; 23 | } 24 | 25 | public String getId() { 26 | return id; 27 | } 28 | public void setId(String id) { 29 | this.id = id; 30 | } 31 | public String getOrderNumber() { 32 | return orderNumber; 33 | } 34 | public void setOrderNumber(String orderNumber) { 35 | this.orderNumber = orderNumber; 36 | } 37 | public String getDeliveryAddress() { 38 | return deliveryAddress; 39 | } 40 | public void setDeliveryAddress(String deliveryAddress) { 41 | this.deliveryAddress = deliveryAddress; 42 | } 43 | 44 | public String getGoods() { 45 | return goods; 46 | } 47 | 48 | public void setGoods(String goods) { 49 | this.goods = goods; 50 | } 51 | } -------------------------------------------------------------------------------- /reactive-spring-css/message/src/main/java/com/springcss/message/AccountMessage.java: -------------------------------------------------------------------------------- 1 | package com.springcss.message; 2 | 3 | import java.io.Serializable; 4 | 5 | public class AccountMessage implements Serializable { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | private String id; 10 | private String accountCode; 11 | private String accountName; 12 | 13 | public AccountMessage() { 14 | super(); 15 | } 16 | 17 | public AccountMessage(String id, String accountCode, String accountName) { 18 | super(); 19 | this.id = id; 20 | this.accountCode = accountCode; 21 | this.accountName = accountName; 22 | } 23 | 24 | public String getId() { 25 | return id; 26 | } 27 | 28 | public void setId(String id) { 29 | this.id = id; 30 | } 31 | 32 | public String getAccountCode() { 33 | return accountCode; 34 | } 35 | 36 | public void setAccountCode(String accountCode) { 37 | this.accountCode = accountCode; 38 | } 39 | 40 | public String getAccountName() { 41 | return accountName; 42 | } 43 | 44 | public void setAccountName(String accountName) { 45 | this.accountName = accountName; 46 | } 47 | 48 | public boolean isEndWithDigit() { 49 | 50 | char last = this.id.charAt(this.id.length() - 1); 51 | boolean result = Character.isDigit(last); 52 | return result; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/service/StubOrderService.java: -------------------------------------------------------------------------------- 1 | //package com.springcss.order.service; 2 | // 3 | //import java.util.Map; 4 | //import java.util.concurrent.ConcurrentHashMap; 5 | // 6 | //import org.springframework.stereotype.Service; 7 | // 8 | //import com.springcss.order.domain.Order; 9 | // 10 | //import reactor.core.publisher.Flux; 11 | //import reactor.core.publisher.Mono; 12 | // 13 | //@Service 14 | //public class StubOrderService { 15 | // 16 | // private final Map orders = new ConcurrentHashMap<>(); 17 | // 18 | // public Flux getOrders() { 19 | // return Flux.fromIterable(this.orders.values()); 20 | // } 21 | // 22 | // public Flux getOrdersByIds(final Flux ids) { 23 | // return ids.flatMap(id -> Mono.justOrEmpty(this.orders.get(id))); 24 | // } 25 | // 26 | // public Mono getOrderById(final String id) { 27 | // return Mono.justOrEmpty(this.orders.get(id)); 28 | // } 29 | // 30 | // public Mono createOrUpdateOrder(final Mono productMono) { 31 | // return productMono.doOnNext(product -> { 32 | // orders.put(product.getId(), product); 33 | // }).thenEmpty(Mono.empty()); 34 | // } 35 | // 36 | // public Mono deleteOrder(final String id) { 37 | // return Mono.justOrEmpty(this.orders.remove(id)); 38 | // } 39 | //} 40 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/domain/Order.java: -------------------------------------------------------------------------------- 1 | package com.springcss.order.domain; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | @Document 7 | public class Order{ 8 | 9 | @Id 10 | private String id; 11 | private String orderNumber; 12 | private String deliveryAddress; 13 | private String goods; 14 | 15 | public Order() { 16 | super(); 17 | } 18 | 19 | public Order(String id, String orderNumber, String deliveryAddress, String goods) { 20 | super(); 21 | this.id = id; 22 | this.orderNumber = orderNumber; 23 | this.deliveryAddress = deliveryAddress; 24 | this.goods = goods; 25 | } 26 | 27 | public String getId() { 28 | return id; 29 | } 30 | public void setId(String id) { 31 | this.id = id; 32 | } 33 | public String getOrderNumber() { 34 | return orderNumber; 35 | } 36 | public void setOrderNumber(String orderNumber) { 37 | this.orderNumber = orderNumber; 38 | } 39 | public String getDeliveryAddress() { 40 | return deliveryAddress; 41 | } 42 | public void setDeliveryAddress(String deliveryAddress) { 43 | this.deliveryAddress = deliveryAddress; 44 | } 45 | 46 | public String getGoods() { 47 | return goods; 48 | } 49 | 50 | public void setGoods(String goods) { 51 | this.goods = goods; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /r2dbc-demo/src/main/java/com/springcss/r2dbc/demo/controller/AccountController.java: -------------------------------------------------------------------------------- 1 | package com.springcss.r2dbc.demo.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.springcss.r2dbc.demo.domain.Account; 12 | import com.springcss.r2dbc.demo.repository.ReactiveAccountRepository; 13 | 14 | import reactor.core.publisher.Mono; 15 | 16 | @RestController 17 | @RequestMapping(value = "accounts") 18 | public class AccountController { 19 | 20 | @Autowired 21 | private ReactiveAccountRepository reactiveAccountRepository; 22 | 23 | @GetMapping(value = "/{accountId}") 24 | public Mono getAccountById(@PathVariable("accountId") Long accountId) { 25 | 26 | Mono account = reactiveAccountRepository.getAccountById(accountId); 27 | return account; 28 | } 29 | 30 | @PostMapping(value = "/") 31 | public Mono addAccount(@RequestBody Account account) { 32 | 33 | return reactiveAccountRepository.addAccount(account.getAccountCode(), account.getAccountName()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/repository/redis/AccountRedisRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.repository.redis; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.redis.core.ReactiveRedisTemplate; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.springcss.customer.client.AccountMapper; 8 | 9 | import reactor.core.publisher.Mono; 10 | 11 | @Repository 12 | public class AccountRedisRepositoryImpl implements AccountRedisRepository { 13 | 14 | @Autowired 15 | private ReactiveRedisTemplate reactiveRedisTemplate; 16 | 17 | private static final String HASH_NAME = "Account:"; 18 | 19 | @Override 20 | public Mono saveAccount(AccountMapper account) { 21 | return reactiveRedisTemplate.opsForValue().set(HASH_NAME + account.getId(), account); 22 | } 23 | 24 | @Override 25 | public Mono updateAccount(AccountMapper account) { 26 | return reactiveRedisTemplate.opsForValue().set(HASH_NAME + account.getId(), account); 27 | } 28 | 29 | @Override 30 | public Mono deleteAccount(String accountId) { 31 | return reactiveRedisTemplate.opsForValue().delete(HASH_NAME + accountId); 32 | } 33 | 34 | @Override 35 | public Mono findAccountById(String accountId) { 36 | return reactiveRedisTemplate.opsForValue().get(HASH_NAME + accountId); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/test/java/com/springcss/account/ReactorTests.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account; 2 | 3 | import org.junit.Test; 4 | 5 | import com.springcss.account.domain.Account; 6 | 7 | import reactor.core.publisher.Flux; 8 | import reactor.core.publisher.Mono; 9 | import reactor.test.StepVerifier; 10 | 11 | public class ReactorTests { 12 | Flux helloWorld = Flux.just("Hello", "World"); 13 | 14 | @Test 15 | public void testStepVerifier() { 16 | StepVerifier.create(helloWorld).expectNext("Hello").expectNext("World").expectComplete().verify(); 17 | } 18 | 19 | @Test 20 | public void testExpectNextMatches() { 21 | StepVerifier.create(Flux.just("jian-hu", "xiang-hu")).expectSubscription() 22 | .expectNextMatches(e -> e.startsWith("jian")).expectNextMatches(e -> e.startsWith("xiang")) 23 | .expectComplete().verify(); 24 | 25 | } 26 | 27 | @Test 28 | public void testAssertNext() { 29 | Account testAccount = new Account("1", "accountCode1", "accountName1"); 30 | 31 | StepVerifier 32 | .create(Flux.just(testAccount)) 33 | .expectSubscription() 34 | .assertNext( 35 | account -> account.getAccountCode().equals("accountCode1") 36 | ) 37 | .expectComplete() 38 | .verify(); 39 | } 40 | 41 | @Test 42 | public void testStepVerifierWithError() { 43 | Flux helloWorldWithException = helloWorld 44 | .concatWith(Mono.error(new IllegalArgumentException("exception"))); 45 | 46 | StepVerifier.create(helloWorldWithException).expectNext("Hello").expectNext("World") 47 | .expectErrorMessage("exception").verify(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/src/main/java/com/springcss/order/controller/StubOrderController.java: -------------------------------------------------------------------------------- 1 | //package com.springcss.order.controller; 2 | // 3 | //import org.springframework.beans.factory.annotation.Autowired; 4 | //import org.springframework.web.bind.annotation.DeleteMapping; 5 | //import org.springframework.web.bind.annotation.GetMapping; 6 | //import org.springframework.web.bind.annotation.PathVariable; 7 | //import org.springframework.web.bind.annotation.PostMapping; 8 | //import org.springframework.web.bind.annotation.RequestBody; 9 | //import org.springframework.web.bind.annotation.RequestMapping; 10 | //import org.springframework.web.bind.annotation.RestController; 11 | // 12 | //import com.springcss.order.domain.Order; 13 | //import com.springcss.order.service.StubOrderService; 14 | // 15 | //import reactor.core.publisher.Flux; 16 | //import reactor.core.publisher.Mono; 17 | // 18 | //@RestController 19 | //@RequestMapping("/orders") 20 | //public class StubOrderController { 21 | // 22 | // @Autowired 23 | // private StubOrderService orderService; 24 | // 25 | // @GetMapping("") 26 | // public Flux getOrders() { 27 | // return this.orderService.getOrders(); 28 | // } 29 | // 30 | // @GetMapping("/{id}") 31 | // public Mono getOrderById(@PathVariable("id") final String id) { 32 | // return this.orderService.getOrderById(id); 33 | // } 34 | // 35 | // @PostMapping("") 36 | // public Mono createOrder(@RequestBody final Mono order) { 37 | // return this.orderService.createOrUpdateOrder(order); 38 | // } 39 | // 40 | // @DeleteMapping("/{id}") 41 | // public Mono delete(@PathVariable("id") final String id) { 42 | // return this.orderService.deleteOrder(id); 43 | // } 44 | //} 45 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/test/java/com/springcss/account/AccountServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.mockito.BDDMockito.given; 5 | 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.mockito.Mockito; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.boot.test.mock.mockito.MockBean; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | 14 | import com.springcss.account.domain.Account; 15 | import com.springcss.account.repository.ReactiveAccountRepository; 16 | import com.springcss.account.service.AccountService; 17 | 18 | import reactor.core.publisher.Mono; 19 | import reactor.test.StepVerifier; 20 | 21 | @RunWith(SpringRunner.class) 22 | @SpringBootTest 23 | public class AccountServiceTest { 24 | 25 | @Autowired 26 | AccountService service; 27 | 28 | @MockBean 29 | ReactiveAccountRepository repository; 30 | 31 | @Test 32 | public void testGetAccountByAccountName() { 33 | Account mockAccount = new Account("Account1", "AccountCode1", "AccountName1"); 34 | 35 | // Mockito.when(repository.findAccountByAccountName("AccountName1")).thenReturn(Mono.just(mockAccount)); 36 | 37 | given(repository.findAccountByAccountName("AccountName1")).willReturn(Mono.just(mockAccount)); 38 | 39 | Mono account = service.getAccountByAccountName("AccountName1"); 40 | 41 | StepVerifier.create(account).expectNextMatches(results -> { 42 | assertThat(results.getAccountCode()).isEqualTo("AccountCode1"); 43 | assertThat(results.getAccountName()).isEqualTo("AccountName1"); 44 | return true; 45 | }).verifyComplete(); 46 | 47 | } 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/test/java/com/springcss/account/EmbeddedAccountRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; 10 | import org.springframework.data.mongodb.core.ReactiveMongoOperations; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | import com.springcss.account.domain.Account; 14 | import com.springcss.account.repository.ReactiveAccountRepository; 15 | 16 | import reactor.core.publisher.Mono; 17 | import reactor.test.StepVerifier; 18 | 19 | 20 | @RunWith(SpringRunner.class) 21 | @DataMongoTest 22 | public class EmbeddedAccountRepositoryTest { 23 | 24 | @Autowired 25 | ReactiveAccountRepository repository; 26 | 27 | @Autowired 28 | ReactiveMongoOperations operations; 29 | 30 | @Before 31 | public void setUp() { 32 | operations.dropCollection(Account.class); 33 | 34 | operations.insert(new Account("Account1", "AccountCode1", "AccountName1")); 35 | operations.insert(new Account("Account2", "AccountCode2", "AccountName2")); 36 | 37 | operations.findAll(Account.class).subscribe( 38 | account -> { 39 | System.out.println(account.getId() 40 | );} 41 | ); 42 | } 43 | 44 | @Test 45 | public void testGetAccountByAccountName() { 46 | Mono account = repository.findAccountByAccountName("AccountName1"); 47 | 48 | StepVerifier.create(account) 49 | .expectNextMatches(results -> { 50 | assertThat(results.getAccountCode()).isEqualTo("AccountCode1"); 51 | assertThat(results.getAccountName()).isEqualTo("AccountName1"); 52 | return true; 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/CustomerApplication.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.stream.annotation.EnableBinding; 6 | import org.springframework.cloud.stream.messaging.Sink; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; 9 | import org.springframework.data.redis.core.ReactiveRedisTemplate; 10 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 11 | import org.springframework.data.redis.serializer.RedisSerializationContext; 12 | import org.springframework.data.redis.serializer.StringRedisSerializer; 13 | 14 | import com.springcss.customer.client.AccountMapper; 15 | 16 | @SpringBootApplication 17 | @EnableBinding(Sink.class) 18 | public class CustomerApplication { 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(CustomerApplication.class, args); 22 | } 23 | 24 | @Bean 25 | ReactiveRedisTemplate reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) { 26 | return new ReactiveRedisTemplate<>(factory, RedisSerializationContext.string()); 27 | } 28 | 29 | @Bean 30 | ReactiveRedisTemplate redisOperations(ReactiveRedisConnectionFactory factory) { 31 | Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(AccountMapper.class); 32 | 33 | RedisSerializationContext.RedisSerializationContextBuilder builder = RedisSerializationContext 34 | .newSerializationContext(new StringRedisSerializer()); 35 | 36 | RedisSerializationContext context = builder.value(serializer).build(); 37 | 38 | return new ReactiveRedisTemplate<>(factory, context); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/java/com/springcss/account/controller/AccountController.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.PutMapping; 8 | import org.springframework.web.bind.annotation.RequestBody; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | import com.springcss.account.domain.Account; 13 | import com.springcss.account.service.AccountService; 14 | 15 | import reactor.core.publisher.Mono; 16 | 17 | @RestController 18 | @RequestMapping(value = "accounts") 19 | public class AccountController { 20 | 21 | @Autowired 22 | private AccountService accountService; 23 | 24 | @GetMapping(value = "/{accountId}") 25 | public Mono getAccountById(@PathVariable("accountId") String accountId) { 26 | // 27 | // Account account = new Account(); 28 | // account.setId(1L); 29 | // account.setAccountCode("DemoCode"); 30 | // account.setAccountName("DemoName"); 31 | 32 | Mono account = accountService.getAccountById(accountId); 33 | return account; 34 | } 35 | 36 | @GetMapping(value = "accountname/{accountName}") 37 | public Mono getAccountByAccountName(@PathVariable("accountName") String accountName) { 38 | 39 | Mono account = accountService.getAccountByAccountName(accountName); 40 | return account; 41 | } 42 | 43 | @PostMapping(value = "/") 44 | public Mono addAccount(@RequestBody Mono account) { 45 | 46 | return accountService.addAccount(account); 47 | } 48 | 49 | @PutMapping(value = "/") 50 | public Mono updateAccount(@RequestBody Mono account) { 51 | 52 | return accountService.updateAccount(account); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /reactive-spring-css/order-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.springcss 8 | order-service 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | Order Service 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.13.RELEASE 18 | 19 | 20 | 21 | 22 | 23 | com.springcss 24 | message 25 | 0.0.1-SNAPSHOT 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-data-mongodb-reactive 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-webflux 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-actuator 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-test 45 | test 46 | 47 | 48 | io.projectreactor 49 | reactor-test 50 | test 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-maven-plugin 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/test/java/com/springcss/account/LiveAccountRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration; 10 | import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; 11 | import org.springframework.data.mongodb.core.ReactiveMongoOperations; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | 14 | import com.springcss.account.domain.Account; 15 | import com.springcss.account.repository.ReactiveAccountRepository; 16 | 17 | import reactor.core.publisher.Mono; 18 | import reactor.test.StepVerifier; 19 | 20 | @RunWith(SpringRunner.class) 21 | @DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class) 22 | public class LiveAccountRepositoryTest { 23 | 24 | @Autowired 25 | ReactiveAccountRepository repository; 26 | 27 | @Autowired 28 | ReactiveMongoOperations operations; 29 | 30 | @Before 31 | public void setUp() { 32 | operations.dropCollection(Account.class); 33 | 34 | operations.insert(new Account("Account1", "AccountCode1", "AccountName1")); 35 | operations.insert(new Account("Account2", "AccountCode2", "AccountName2")); 36 | 37 | operations.findAll(Account.class).subscribe( 38 | account -> { 39 | System.out.println(account.getId() 40 | );} 41 | ); 42 | } 43 | 44 | @Test 45 | public void testGetAccountByAccountName() { 46 | Mono account = repository.findAccountByAccountName("AccountName1"); 47 | 48 | StepVerifier.create(account) 49 | .expectNextMatches(results -> { 50 | assertThat(results.getAccountCode()).isEqualTo("AccountCode1"); 51 | assertThat(results.getAccountName()).isEqualTo("AccountName1"); 52 | return true; 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/controller/CustomerController.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.PostMapping; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | import com.springcss.customer.domain.CustomerTicket; 11 | import com.springcss.customer.service.CustomerTicketService; 12 | 13 | import reactor.core.publisher.Flux; 14 | import reactor.core.publisher.Mono; 15 | 16 | @RestController 17 | @RequestMapping(value="customers") 18 | public class CustomerController { 19 | 20 | @Autowired 21 | private CustomerTicketService customerTicketService; 22 | 23 | @PostMapping(value = "/{accountId}/{orderNumber}") 24 | public Mono generateCustomerTicket( @PathVariable("accountId") String accountId, 25 | @PathVariable("orderNumber") String orderNumber) { 26 | 27 | Mono customerTicket = customerTicketService.generateCustomerTicket(accountId, orderNumber); 28 | 29 | return customerTicket; 30 | } 31 | 32 | @GetMapping(value = "/{id}") 33 | public Mono getCustomerTicketById(@PathVariable String id) { 34 | 35 | Mono customerTicket = customerTicketService.getCustomerTicketById(id); 36 | 37 | // CustomerTicket customerTicket = new CustomerTicket(); 38 | // customerTicket.setId(1L); 39 | // customerTicket.setAccountId(100L); 40 | // customerTicket.setOrderNumber("Order00001"); 41 | // customerTicket.setDescription("DemoOrder"); 42 | // customerTicket.setCreateTime(new Date()); 43 | // 44 | return customerTicket; 45 | } 46 | 47 | @GetMapping(value = "/") 48 | public Flux getCustomerTicketList( ) { 49 | Flux customerTickets = customerTicketService.getCustomerTickets(); 50 | 51 | return customerTickets; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /r2dbc-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.3.2.RELEASE 10 | 11 | 12 | com.springcss.r2dbc 13 | demo 14 | 0.0.1-SNAPSHOT 15 | demo 16 | Demo project for Spring Data R2dbc 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-data-r2dbc 26 | 27 | 28 | 29 | io.r2dbc 30 | r2dbc-pool 31 | 32 | 33 | 34 | dev.miku 35 | r2dbc-mysql 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-data-jdbc 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-webflux 47 | 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-test 57 | test 58 | 59 | 60 | 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-maven-plugin 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/event/ReactiveAccountChangedSink.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.event; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.cloud.stream.annotation.EnableBinding; 7 | import org.springframework.cloud.stream.annotation.StreamListener; 8 | 9 | import com.springcss.customer.client.AccountMapper; 10 | import com.springcss.customer.repository.redis.AccountRedisRepository; 11 | import com.springcss.message.AccountChangedEvent; 12 | import com.springcss.message.AccountMessage; 13 | 14 | import reactor.core.publisher.Mono; 15 | 16 | @EnableBinding(AccountChangedChannel.class) 17 | public class ReactiveAccountChangedSink { 18 | 19 | @Autowired 20 | AccountRedisRepository accountRedisRepository; 21 | 22 | private static final Logger logger = LoggerFactory.getLogger(ReactiveAccountChangedSink.class); 23 | 24 | @StreamListener(AccountChangedChannel.ACCOUNT_CHANGED) 25 | public void handleAccountChangedEvent(AccountChangedEvent accountChangedEvent) { 26 | 27 | logger.debug("Received a message of type " + accountChangedEvent.getType()); 28 | logger.debug("Received a {} event from the account service for account id {}", 29 | accountChangedEvent.getOperation(), 30 | accountChangedEvent.getAccountMessage().getId()); 31 | 32 | System.out.println("Received a account message of id " + accountChangedEvent.getAccountMessage().getId()); 33 | 34 | AccountMessage accountMessage = accountChangedEvent.getAccountMessage(); 35 | AccountMapper accountMapper = 36 | new AccountMapper(accountMessage.getId(), 37 | accountMessage.getAccountCode(), 38 | accountMessage.getAccountName()); 39 | 40 | if(accountChangedEvent.getOperation().equals("UPDATE")) { 41 | accountRedisRepository.updateAccount(accountMapper).subscribe(); 42 | } else if(accountChangedEvent.getOperation().equals("DELETE")) { 43 | accountRedisRepository.deleteAccount(accountMapper.getId()).subscribe(); 44 | } else { 45 | logger.error("The operations {} is undefined ", accountChangedEvent.getOperation()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/domain/CustomerTicket.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.domain; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.data.annotation.Id; 6 | import org.springframework.data.mongodb.core.mapping.Document; 7 | import org.springframework.util.Assert; 8 | 9 | 10 | @Document 11 | public class CustomerTicket { 12 | @Id 13 | private String id; 14 | private String accountId; 15 | private String orderNumber; 16 | private String description; 17 | private Date createTime; 18 | 19 | 20 | public CustomerTicket() { 21 | super(); 22 | } 23 | 24 | public CustomerTicket(String accountId, String orderNumber) { 25 | super(); 26 | 27 | Assert.notNull(accountId, "Account Id must not be null"); 28 | Assert.notNull(orderNumber, "Order Number must not be null"); 29 | 30 | this.accountId = accountId; 31 | this.orderNumber = orderNumber; 32 | } 33 | 34 | public CustomerTicket(String accountId, String orderNumber, String description, Date createTime) { 35 | 36 | this(accountId, orderNumber); 37 | 38 | this.description = description; 39 | this.createTime = createTime; 40 | } 41 | 42 | public CustomerTicket(String id, String accountId, String orderNumber, String description, Date createTime) { 43 | 44 | this(accountId, orderNumber); 45 | 46 | this.id = id; 47 | this.description = description; 48 | this.createTime = createTime; 49 | } 50 | 51 | public String getId() { 52 | return id; 53 | } 54 | 55 | public void setId(String id) { 56 | this.id = id; 57 | } 58 | 59 | public String getAccountId() { 60 | return accountId; 61 | } 62 | 63 | public void setAccountId(String accountId) { 64 | this.accountId = accountId; 65 | } 66 | 67 | public String getOrderNumber() { 68 | return orderNumber; 69 | } 70 | 71 | public void setOrderNumber(String orderNumber) { 72 | this.orderNumber = orderNumber; 73 | } 74 | 75 | public String getDescription() { 76 | return description; 77 | } 78 | 79 | public void setDescription(String description) { 80 | this.description = description; 81 | } 82 | 83 | public Date getCreateTime() { 84 | return createTime; 85 | } 86 | 87 | public void setCreateTime(Date createTime) { 88 | this.createTime = createTime; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/client/ReactiveAccountClient.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.client; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.web.reactive.function.client.WebClient; 8 | 9 | import com.springcss.customer.repository.redis.AccountRedisRepository; 10 | 11 | import reactor.core.publisher.Mono; 12 | 13 | @Component 14 | public class ReactiveAccountClient { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(ReactiveAccountClient.class); 17 | 18 | @Autowired 19 | private AccountRedisRepository accountRedisRepository; 20 | 21 | private Mono getAccountFromCache(String accountId) { 22 | logger.info("Get account from redis: {}", accountId); 23 | 24 | return accountRedisRepository.findAccountById(accountId); 25 | } 26 | 27 | private Mono putAccountIntoCache(AccountMapper account) { 28 | logger.info("Put account into redis: {}", account.getId()); 29 | 30 | return accountRedisRepository.saveAccount(account).flatMap( saved -> { 31 | Mono savedAccount = accountRedisRepository.findAccountById(account.getId()); 32 | 33 | return savedAccount; 34 | }); 35 | } 36 | 37 | public Mono findAccountById(String accountId){ 38 | logger.debug("Get account from remote: {}", accountId); 39 | 40 | //先从Redis中获取目标Account对象 41 | Mono accountMonoFromCache = getAccountFromCache(accountId); 42 | 43 | //如果Redis中没有目标Account对象,则进行远程获取 44 | Mono accountMono = accountMonoFromCache.switchIfEmpty(getAccountFromRemote(accountId)); 45 | 46 | return accountMono; 47 | } 48 | 49 | public Mono getAccountFromRemote(String accountId) { 50 | 51 | //远程获取Account对象 52 | Mono accountMonoFromRemote = WebClient.create() 53 | .get() 54 | .uri("http://127.0.0.1:8082/accounts/{accountId}", accountId) 55 | .retrieve() 56 | .bodyToMono(AccountMapper.class).log("getAccountFromRemote"); 57 | 58 | //将获取到的Account对象放入Redis中 59 | return accountMonoFromRemote.flatMap(this::putAccountIntoCache); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/test/java/com/springcss/account/AccountControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account; 2 | 3 | import static org.assertj.core.api.Assertions.assertThat; 4 | import static org.mockito.BDDMockito.given; 5 | import static org.mockito.Mockito.verify; 6 | import static org.mockito.Mockito.verifyNoMoreInteractions; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; 12 | import org.springframework.boot.test.mock.mockito.MockBean; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | import org.springframework.test.web.reactive.server.EntityExchangeResult; 15 | import org.springframework.test.web.reactive.server.WebTestClient; 16 | 17 | import com.springcss.account.controller.AccountController; 18 | import com.springcss.account.domain.Account; 19 | import com.springcss.account.service.AccountService; 20 | 21 | import reactor.core.publisher.Mono; 22 | 23 | @RunWith(SpringRunner.class) 24 | @WebFluxTest(controllers = AccountController.class) 25 | public class AccountControllerTest { 26 | 27 | @Autowired 28 | WebTestClient webClient; 29 | 30 | @MockBean 31 | AccountService service; 32 | 33 | @Test 34 | public void testGetAccountById() { 35 | Account mockAccount = new Account("Account1", "AccountCode1", "AccountName1"); 36 | 37 | given(service.getAccountById("Account1")).willReturn(Mono.just(mockAccount)); 38 | 39 | EntityExchangeResult result = webClient.get() 40 | .uri("http://localhost:8082/accounts/{accountId}", "Account1").exchange().expectStatus() 41 | .isOk().expectBody(Account.class).returnResult(); 42 | 43 | verify(service).getAccountById("Account1"); 44 | verifyNoMoreInteractions(service); 45 | 46 | assertThat(result.getResponseBody().getId()).isEqualTo("Account1"); 47 | assertThat(result.getResponseBody().getAccountCode()).isEqualTo("AccountCode1"); 48 | } 49 | 50 | // 51 | // @Test 52 | // public void testDeleteMedicine() { 53 | // given(service.deleteMedicineById("001")).willReturn(Mono.empty()); 54 | // 55 | // webClient.delete() 56 | // .uri("http://localhost:8081/v1/medicines/{medicineId}", "001").exchange().expectStatus() 57 | // .isOk().expectBody(Void.class).returnResult(); 58 | // 59 | // verify(service).deleteMedicineById("001"); 60 | // verifyNoMoreInteractions(service); 61 | // } 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/java/com/springcss/account/event/ReactiveAccountChangedSource.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account.event; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.cloud.stream.annotation.Output; 6 | import org.springframework.cloud.stream.messaging.Source; 7 | import org.springframework.cloud.stream.reactive.FluxSender; 8 | import org.springframework.cloud.stream.reactive.StreamEmitter; 9 | import org.springframework.messaging.Message; 10 | import org.springframework.messaging.support.MessageBuilder; 11 | import org.springframework.stereotype.Component; 12 | 13 | import com.springcss.account.domain.Account; 14 | import com.springcss.message.AccountChangedEvent; 15 | import com.springcss.message.AccountMessage; 16 | 17 | import reactor.core.publisher.Flux; 18 | import reactor.core.publisher.FluxSink; 19 | import reactor.core.publisher.Mono; 20 | 21 | @Component 22 | public class ReactiveAccountChangedSource { 23 | 24 | private static final Logger logger = LoggerFactory.getLogger(ReactiveAccountChangedSource.class); 25 | 26 | private FluxSink> eventSink; 27 | private Flux> flux; 28 | 29 | public ReactiveAccountChangedSource() { 30 | this.flux = Flux.>create(sink -> this.eventSink = sink).publish().autoConnect(); 31 | } 32 | 33 | private Mono publishAccountChangedEvent(String operation, Account account){ 34 | logger.debug("Sending message for Account Id: {}", account.getId()); 35 | 36 | AccountMessage accountMessage = new AccountMessage(account.getId(), account.getAccountCode(), account.getAccountName()); 37 | 38 | AccountChangedEvent originalevent = new AccountChangedEvent( 39 | AccountChangedEvent.class.getTypeName(), 40 | operation, 41 | accountMessage); 42 | 43 | Mono monoEvent = Mono.just(originalevent); 44 | 45 | return monoEvent.map(event -> eventSink.next(MessageBuilder.withPayload(event).build())).then(); 46 | } 47 | 48 | @StreamEmitter 49 | public void emit(@Output(Source.OUTPUT) FluxSender output) { 50 | output.send(this.flux); 51 | } 52 | 53 | public Mono publishAccountUpdatedEvent(Account account) { 54 | return publishAccountChangedEvent("UPDATE", account); 55 | } 56 | 57 | public Mono publishAccountDeletedEvent(Account account) { 58 | return publishAccountChangedEvent("DELETE", account); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/src/main/java/com/springcss/account/service/AccountService.java: -------------------------------------------------------------------------------- 1 | package com.springcss.account.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.data.domain.Example; 5 | import org.springframework.data.domain.ExampleMatcher; 6 | import org.springframework.data.domain.ExampleMatcher.GenericPropertyMatcher; 7 | import org.springframework.data.domain.ExampleMatcher.StringMatcher; 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.springcss.account.domain.Account; 11 | import com.springcss.account.event.ReactiveAccountChangedSource; 12 | import com.springcss.account.repository.ReactiveAccountRepository; 13 | 14 | import reactor.core.publisher.Flux; 15 | import reactor.core.publisher.Mono; 16 | 17 | @Service 18 | public class AccountService { 19 | 20 | @Autowired 21 | private ReactiveAccountRepository accountRepository; 22 | 23 | @Autowired 24 | private ReactiveAccountChangedSource accountChangedSource; 25 | 26 | public Mono getAccountById(String accountId) { 27 | 28 | return accountRepository.findById(accountId).log("getAccountById"); 29 | } 30 | 31 | public Mono getAccountByAccountName(String accountName) { 32 | 33 | return accountRepository.findAccountByAccountName(accountName).log("getAccountByAccountName"); 34 | } 35 | 36 | public Mono addAccount(Mono account){ 37 | 38 | Mono saveAccount = account.flatMap(accountRepository::save); 39 | 40 | return saveAccount.flatMap(accountChangedSource::publishAccountUpdatedEvent); 41 | } 42 | 43 | public Mono updateAccount(Mono account){ 44 | 45 | Mono saveAccount = account.flatMap(accountRepository::save); 46 | 47 | return saveAccount.flatMap(accountChangedSource::publishAccountUpdatedEvent); 48 | } 49 | 50 | public Flux getAccountsByAccountName(String accountName) { 51 | Account account = new Account(); 52 | account.setAccountName(accountName); 53 | 54 | ExampleMatcher matcher = ExampleMatcher.matching() 55 | .withIgnoreCase() 56 | .withMatcher(accountName, GenericPropertyMatcher.of(StringMatcher.STARTING)) 57 | .withIncludeNullValues(); 58 | 59 | Example example = Example.of(account, matcher); 60 | 61 | Flux accounts = accountRepository.findAll(example).log("getAccountsByAccountName"); 62 | 63 | return accounts; 64 | } 65 | 66 | } 67 | 68 | 69 | 70 | //return Mono.when(saveAccount, saveEvent); 71 | -------------------------------------------------------------------------------- /reactive-spring-css/account-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.springcss 8 | account-service 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | Account Service 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.13.RELEASE 18 | 19 | 20 | 21 | 22 | 23 | 24 | org.springframework.cloud 25 | spring-cloud-dependencies 26 | Greenwich.SR6 27 | pom 28 | import 29 | 30 | 31 | 32 | 33 | 34 | 35 | com.springcss 36 | message 37 | 0.0.1-SNAPSHOT 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-data-mongodb-reactive 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-webflux 47 | 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-actuator 52 | 53 | 54 | 55 | 56 | org.springframework.cloud 57 | spring-cloud-stream 58 | 59 | 60 | 61 | org.springframework.cloud 62 | spring-cloud-stream-reactive 63 | 64 | 65 | 66 | org.springframework.cloud 67 | spring-cloud-starter-stream-rabbit 68 | 69 | 70 | 71 | org.springframework.boot 72 | spring-boot-starter-test 73 | test 74 | 75 | 76 | io.projectreactor 77 | reactor-test 78 | test 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | org.springframework.boot 87 | spring-boot-maven-plugin 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/src/main/java/com/springcss/customer/service/CustomerTicketService.java: -------------------------------------------------------------------------------- 1 | package com.springcss.customer.service; 2 | 3 | import java.util.Date; 4 | import java.util.UUID; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import com.springcss.customer.client.AccountMapper; 12 | import com.springcss.customer.client.OrderMapper; 13 | import com.springcss.customer.client.ReactiveAccountClient; 14 | import com.springcss.customer.client.ReactiveOrderClient; 15 | import com.springcss.customer.domain.CustomerTicket; 16 | import com.springcss.customer.repository.CustomerTicketRepository; 17 | 18 | import reactor.core.publisher.Flux; 19 | import reactor.core.publisher.Mono; 20 | 21 | @Service 22 | public class CustomerTicketService { 23 | 24 | @Autowired 25 | private CustomerTicketRepository customerTicketRepository; 26 | 27 | @Autowired 28 | private ReactiveOrderClient orderClient; 29 | 30 | @Autowired 31 | private ReactiveAccountClient accountClient; 32 | 33 | private static final Logger logger = LoggerFactory.getLogger(CustomerTicketService.class); 34 | 35 | private Mono getRemoteOrderByOrderNumber(String orderNumber) { 36 | 37 | return orderClient.getOrderByOrderNumber(orderNumber); 38 | } 39 | 40 | private Mono getRemoteAccountByAccountId(String accountId) { 41 | 42 | return accountClient.findAccountById(accountId); 43 | 44 | // return accountClient.getAccountFromRemote(accountId); 45 | } 46 | 47 | public Mono generateCustomerTicket(String accountId, String orderNumber) { 48 | 49 | logger.debug("Generate customer ticket record with account: {} and order: {}", accountId, orderNumber); 50 | 51 | CustomerTicket customerTicket = new CustomerTicket(); 52 | customerTicket.setId("C_" + UUID.randomUUID().toString()); 53 | 54 | // 从远程account-service获取Account信息 55 | Mono accountMapper = getRemoteAccountByAccountId(accountId); 56 | 57 | // 从远程order-service中获取Order信息 58 | Mono orderMapper = getRemoteOrderByOrderNumber(orderNumber); 59 | 60 | Mono monoCustomerTicket = 61 | Mono.zip(accountMapper, orderMapper).flatMap(tuple -> { 62 | AccountMapper account = tuple.getT1(); 63 | OrderMapper order = tuple.getT2(); 64 | 65 | if(account == null || order == null) { 66 | return Mono.just(customerTicket); 67 | } 68 | 69 | customerTicket.setAccountId(account.getId()); 70 | customerTicket.setOrderNumber(order.getOrderNumber()); 71 | customerTicket.setCreateTime(new Date()); 72 | customerTicket.setDescription("TestCustomerTicket"); 73 | 74 | return Mono.just(customerTicket); 75 | }); 76 | 77 | return monoCustomerTicket.flatMap(customerTicketRepository::save); 78 | } 79 | 80 | public Flux getCustomerTickets() { 81 | 82 | return customerTicketRepository.findAll(); 83 | } 84 | 85 | public Mono getCustomerTicketById(String id) { 86 | 87 | return customerTicketRepository.findById(id); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /reactive-spring-css/customer-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.springcss 8 | customer-service 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | Customer Service 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.13.RELEASE 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | org.springframework.cloud 26 | spring-cloud-dependencies 27 | Greenwich.SR6 28 | pom 29 | import 30 | 31 | 32 | 33 | 34 | 35 | 36 | spring-snapshots 37 | Spring Snapshots 38 | https://repo.spring.io/snapshot 39 | 40 | true 41 | 42 | 43 | 44 | spring-milestones 45 | Spring Milestones 46 | https://repo.spring.io/milestone 47 | 48 | false 49 | 50 | 51 | 52 | spring-libs-snapshot 53 | https://repo.spring.io/libs-snapshot 54 | 55 | 56 | 57 | 58 | 59 | 60 | com.springcss 61 | message 62 | 0.0.1-SNAPSHOT 63 | 64 | 65 | 66 | org.springframework.boot 67 | spring-boot-starter-data-mongodb-reactive 68 | 69 | 70 | org.springframework.boot 71 | spring-boot-starter-webflux 72 | 73 | 74 | 75 | org.springframework.boot 76 | spring-boot-starter-actuator 77 | 78 | 79 | 80 | 81 | org.springframework.cloud 82 | spring-cloud-function-context 83 | 84 | 85 | org.springframework.cloud 86 | spring-cloud-stream-reactive 87 | 88 | 89 | org.springframework.cloud 90 | spring-cloud-starter-stream-rabbit 91 | 92 | 93 | org.springframework.cloud 94 | spring-cloud-stream 95 | 96 | 97 | org.springframework.boot 98 | spring-boot-starter-data-redis-reactive 99 | 100 | 101 | 102 | org.springframework.boot 103 | spring-boot-starter-data-redis 104 | 105 | 106 | 107 | org.springframework.data 108 | spring-data-redis 109 | 110 | 111 | redis.clients 112 | jedis 113 | 114 | 115 | 116 | org.springframework.boot 117 | spring-boot-starter-test 118 | test 119 | 120 | 121 | io.projectreactor 122 | reactor-test 123 | test 124 | 125 | 126 | 127 | 128 | 129 | 130 | org.springframework.boot 131 | spring-boot-maven-plugin 132 | 133 | 134 | 135 | 136 | --------------------------------------------------------------------------------