├── README.md
├── TEST_MSA_no_configuration.md
├── actuator-demo
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── DemoApplication.java
│ │ │ └── DemoController.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
│ └── DemoApplicationTests.java
├── apigateway-service-no-config
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── apigatewayservice
│ │ │ ├── ApigatewayServiceApplication.java
│ │ │ ├── config
│ │ │ └── FilterConfig.java
│ │ │ └── filter
│ │ │ ├── AuthorizationHeaderFilter.java
│ │ │ ├── CustomFilter.java
│ │ │ ├── GlobalFilter.java
│ │ │ └── LoggingFilter.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── apigatewayservice
│ └── ApigatewayServiceApplicationTests.java
├── apigateway-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── apigatewayservice
│ │ │ ├── ApigatewayServiceApplication.java
│ │ │ ├── config
│ │ │ └── FilterConfig.java
│ │ │ └── filter
│ │ │ ├── AuthorizationHeaderFilter.java
│ │ │ ├── CustomFilter.java
│ │ │ ├── GlobalFilter.java
│ │ │ └── LoggingFilter.java
│ └── resources
│ │ ├── application.yml
│ │ └── bootstrap.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── apigatewayservice
│ └── ApigatewayServiceApplicationTests.java
├── catalog-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── catalogservice
│ │ │ ├── CatalogServiceApplication.java
│ │ │ ├── controller
│ │ │ └── CatalogController.java
│ │ │ ├── dto
│ │ │ └── CatalogDto.java
│ │ │ ├── jpa
│ │ │ ├── CatalogEntity.java
│ │ │ └── CatalogRepository.java
│ │ │ ├── messagequeue
│ │ │ ├── KafkaConsumer.java
│ │ │ └── KafkaConsumerConfig.java
│ │ │ ├── service
│ │ │ ├── CatalogService.java
│ │ │ └── CatalogServiceImpl.java
│ │ │ └── vo
│ │ │ └── ResponseCatalog.java
│ └── resources
│ │ ├── application.yml
│ │ └── data.sql
│ └── test
│ └── java
│ └── com
│ └── example
│ └── catalogservice
│ └── CatalogServiceApplicationTests.java
├── config-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── apiEncryptionKey.jks
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── configservice
│ │ │ └── ConfigServiceApplication.java
│ └── resources
│ │ ├── application.yml
│ │ └── bootstrap.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── configservice
│ └── ConfigServiceApplicationTests.java
├── cookie-demo
├── index.js
└── package.json
├── discoveryservice
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── discoveryservice
│ │ │ └── DiscoveryserviceApplication.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── discoveryservice
│ └── DiscoveryserviceApplicationTests.java
├── docker-files
├── Dockerfile
├── docker-compose.yml
└── mysql_data
│ └── mysql
│ └── mydb
│ ├── db.opt
│ ├── hibernate_sequence.frm
│ ├── hibernate_sequence.ibd
│ ├── orders.frm
│ └── orders.ibd
├── eclipse_lombok.pdf
├── first-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── first-service-demo.zip
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── firstservice
│ │ │ ├── CustomizationPort.java
│ │ │ ├── FirstServiceApplication.java
│ │ │ └── FirstServiceController.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── firstservice
│ └── FirstServiceApplicationTests.java
├── order-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mem
│ ├── testdb.h2.db
│ └── testdb.trace.db
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── orderservice
│ │ │ ├── OrderServiceApplication.java
│ │ │ ├── controller
│ │ │ └── OrderController.java
│ │ │ ├── dto
│ │ │ ├── Field.java
│ │ │ ├── KafkaOrderDto.java
│ │ │ ├── OrderDto.java
│ │ │ ├── Payload.java
│ │ │ └── Schema.java
│ │ │ ├── jpa
│ │ │ ├── OrderEntity.java
│ │ │ └── OrderRepository.java
│ │ │ ├── messagequeue
│ │ │ ├── KafkaProducer.java
│ │ │ ├── KafkaProducerConfig.java
│ │ │ └── OrderProducer.java
│ │ │ ├── service
│ │ │ ├── OrderService.java
│ │ │ └── OrderServiceImpl.java
│ │ │ └── vo
│ │ │ ├── RequestOrder.java
│ │ │ └── ResponseOrder.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── orderservice
│ └── OrderServiceApplicationTests.java
├── pdf
├── Section 0. Microservice와 Spring Cloud 소개.pdf
├── Section 1. Service Discovery.pdf
├── Section 2. API Gateway Service.pdf
├── Section 3. E-commerce 애플리케이션.pdf
├── Section 4. Users Microservice-part1.pdf
├── Section 5. Catalogs, Orders Microservice.pdf
├── Section 6. Users Microservice-part2.pdf
├── Section 7. Spring Config Server.pdf
├── Section 8. Spring Cloud Bus.pdf
├── Section 9. Encryption and Decryption.pdf
├── Section10. 마이크로서비스간 통신.pdf
├── Section11. Kafka를 이용한 데이터동기화-part1.pdf
├── Section12. Kafka를 이용한 데이터동기화-part2.pdf
├── Section13. Resilience4J_Trace.pdf
├── Section14. Monitoring.pdf
├── Section15. Docker.pdf
└── Section16. Deployment.pdf
├── second-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── secondservice
│ │ │ ├── SecondServiceApplication.java
│ │ │ └── SecondServiceController.java
│ └── resources
│ │ ├── application.properties
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── secondservice
│ └── SecondServiceApplicationTests.java
├── user-service-no-config
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── userservice
│ │ │ ├── EncryptDemo.java
│ │ │ ├── UserServiceApplication.java
│ │ │ ├── client
│ │ │ └── OrderServiceClient.java
│ │ │ ├── config
│ │ │ ├── CustomContainer.java
│ │ │ └── Resilience4JConfig.java
│ │ │ ├── controller
│ │ │ └── UserController.java
│ │ │ ├── dto
│ │ │ └── UserDto.java
│ │ │ ├── error
│ │ │ └── FeignErrorDecoder.java
│ │ │ ├── jpa
│ │ │ ├── UserEntity.java
│ │ │ └── UserRepository.java
│ │ │ ├── security
│ │ │ ├── AuthenticationFilter.java
│ │ │ └── WebSecurity.java
│ │ │ ├── service
│ │ │ ├── UserService.java
│ │ │ └── UserServiceImpl.java
│ │ │ └── vo
│ │ │ ├── Greeting.java
│ │ │ ├── RequestLogin.java
│ │ │ ├── RequestUser.java
│ │ │ ├── ResponseOrder.java
│ │ │ └── ResponseUser.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── userservice
│ └── UserServiceApplicationTests.java
├── user-service-no-security
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── userservice
│ │ │ ├── UserServiceApplication.java
│ │ │ ├── controller
│ │ │ └── UserController.java
│ │ │ ├── dto
│ │ │ └── UserDto.java
│ │ │ ├── jpa
│ │ │ ├── UserEntity.java
│ │ │ └── UserRepository.java
│ │ │ ├── security
│ │ │ └── WebSecurity.java
│ │ │ ├── service
│ │ │ ├── UserService.java
│ │ │ └── UserServiceImpl.java
│ │ │ └── vo
│ │ │ ├── Greeting.java
│ │ │ ├── RequestLogin.java
│ │ │ ├── RequestUser.java
│ │ │ ├── ResponseOrder.java
│ │ │ └── ResponseUser.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── userservice
│ └── UserServiceApplicationTests.java
├── user-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── userservice
│ │ │ ├── EncryptDemo.java
│ │ │ ├── UserServiceApplication.java
│ │ │ ├── client
│ │ │ └── OrderServiceClient.java
│ │ │ ├── config
│ │ │ ├── CustomContainer.java
│ │ │ └── Resilience4JConfig.java
│ │ │ ├── controller
│ │ │ └── UserController.java
│ │ │ ├── dto
│ │ │ └── UserDto.java
│ │ │ ├── error
│ │ │ └── FeignErrorDecoder.java
│ │ │ ├── jpa
│ │ │ ├── UserEntity.java
│ │ │ └── UserRepository.java
│ │ │ ├── security
│ │ │ ├── AuthenticationFilter.java
│ │ │ └── WebSecurity.java
│ │ │ ├── service
│ │ │ ├── UserService.java
│ │ │ └── UserServiceImpl.java
│ │ │ └── vo
│ │ │ ├── Greeting.java
│ │ │ ├── RequestLogin.java
│ │ │ ├── RequestUser.java
│ │ │ ├── ResponseOrder.java
│ │ │ └── ResponseUser.java
│ └── resources
│ │ ├── application.yml
│ │ └── bootstrap.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── userservice
│ └── UserServiceApplicationTests.java
└── zuul-service
├── .gitignore
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── example
│ │ └── zuulservice
│ │ ├── ZuulServiceApplication.java
│ │ └── filter
│ │ └── ZuulLoggingFilter.java
└── resources
│ └── application.yml
└── test
└── java
└── com
└── example
└── zuulservice
└── ZuulServiceApplicationTests.java
/README.md:
--------------------------------------------------------------------------------
1 | # msa_with_spring_cloud
2 |
3 | ### Configuration + Service discovery + Api gateway
4 | 1. config-service - Configuration service
5 | 2. discoveryservice - Service discovery
6 | 3. apigateway-service - Spring Cloud Gateway
7 | 4. zuul-service - Spring Cloud Netflix Zuul
8 |
9 | ### Sample codes
10 | 5. first-service - example for apigateway service
11 | 6. second-service - example for apigateway service
12 |
13 | ### E-commerce codes
14 | 7. catalog-service
15 | 8. order-service
16 | 9. user-service
17 |
18 | ### Docker files
19 | 10. docker-files
20 |
--------------------------------------------------------------------------------
/TEST_MSA_no_configuration.md:
--------------------------------------------------------------------------------
1 | ### Service 기동
2 | 1. eurkea server
3 | 2. apigateway
4 | - spring cloud bus 비활성
5 | - bootstrap.yml 삭제 (나중에 추가)
6 | - routes 확인
7 | 3. user-service
8 | - spring cloud bus 비활성
9 | - bootstrap.yml 삭제 (나중에 추가)
10 | - datasource 주석 해제
11 | - application.yml 파일에
12 | - gateway.ip 등록
13 | 4. order-service
14 | 5. catalog-service
15 |
16 | ### API TEST
17 | 1. 회원가입
18 | ```
19 | POST http://ip_address:8000/user-service/users
20 | {
21 | "email": "edowon0622@gmail.com",
22 | "name": "Dowon Lee",
23 | "pwd": "1234"
24 | }
25 | ```
26 | 2. 로그인
27 | ```
28 | POST http://ip_address:8000/user-service/login
29 | {
30 | "email": "edowon0622@gmail.com",
31 | "password": "1234"
32 | }
33 | ```
34 | 3. 상품목록 확인
35 | ```
36 | GET http://ip_address:8000/catalog-service/catalogs
37 | ```
38 | 4. 상품 주문
39 | ```
40 | POST http://ip_address:8000/uorderser-service/orders
41 | {
42 | "productId": "CATALOG-001",
43 | "qty": 10,
44 | "unitPrice": 1500
45 | }
46 | ```
47 | 5. 사용자 전체 목록 확인 (token 필요)
48 | ```
49 | POSTMAN -> Authorization -> Bearer Token
50 | GET http://ip_address:8000/user-service/users
51 | ```
52 | 6. 사용자 상세 보기 (token 필요)
53 | ```
54 | POSTMAN -> Authorization -> Bearer Token
55 | GET http://ip_address:8000/user-service/users/[userId]
56 | ```
57 |
--------------------------------------------------------------------------------
/actuator-demo/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/actuator-demo/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joneconsulting/msa_with_spring_cloud/5827d698c9793f1799eeafb26002cab50cd65d5d/actuator-demo/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/actuator-demo/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/actuator-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.4.4
9 |
10 |
11 | com.example
12 | demo
13 | 0.0.1-SNAPSHOT
14 | demo
15 | Demo project for Spring Boot
16 |
17 | 1.8
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-web
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-tomcat
28 | provided
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter-test
33 | test
34 |
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-actuator
39 | 2.4.4
40 |
41 |
42 |
43 | org.springdoc
44 | springdoc-openapi-ui
45 | 1.5.6
46 |
47 |
48 |
49 |
50 |
51 |
52 | org.springframework.boot
53 | spring-boot-maven-plugin
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/actuator-demo/src/main/java/com/example/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class DemoApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(DemoApplication.class, args);
11 | }
12 |
13 | }
--------------------------------------------------------------------------------
/actuator-demo/src/main/java/com/example/demo/DemoController.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.springframework.web.bind.annotation.RequestMapping;
4 | import org.springframework.web.bind.annotation.RestController;
5 |
6 | @RestController
7 | public class DemoController {
8 | @RequestMapping("/")
9 | public String home() {
10 | return "Hello World!";
11 | }
12 | }
--------------------------------------------------------------------------------
/actuator-demo/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8088
3 |
4 | spring:
5 | application:
6 | name: demo-app
7 |
8 | management:
9 | endpoints:
10 | web:
11 | exposure:
12 | include: health,metrics
13 |
--------------------------------------------------------------------------------
/actuator-demo/src/test/java/com/example/demo/DemoApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.demo;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class DemoApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joneconsulting/msa_with_spring_cloud/5827d698c9793f1799eeafb26002cab50cd65d5d/apigateway-service-no-config/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/apigateway-service-no-config/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17-ea-11-jdk-slim
2 | VOLUME /tmp
3 | COPY target/apigateway-service-1.0.jar ApigatewayService.jar
4 | ENTRYPOINT ["java", "-jar", "ApigatewayService.jar"]
--------------------------------------------------------------------------------
/apigateway-service-no-config/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.4.2
9 |
10 |
11 | com.example
12 | apigateway-service
13 | 1.0
14 | apigateway-service
15 | Demo project for Spring Boot
16 |
17 | 11
18 | 2020.0.0
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-starter-gateway
24 |
25 |
26 | org.springframework.cloud
27 | spring-cloud-starter-netflix-eureka-client
28 |
29 |
30 |
31 | org.projectlombok
32 | lombok
33 | true
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-test
38 | test
39 |
40 |
41 | io.jsonwebtoken
42 | jjwt
43 | 0.9.1
44 |
45 |
46 | javax.xml.bind
47 | jaxb-api
48 |
49 |
50 |
51 | org.springframework.cloud
52 | spring-cloud-starter-config
53 |
54 |
55 |
56 | org.springframework.cloud
57 | spring-cloud-starter-bootstrap
58 |
59 |
60 |
61 | org.springframework.boot
62 | spring-boot-starter-actuator
63 |
64 |
65 |
66 |
71 |
72 |
73 |
74 |
75 | io.micrometer
76 | micrometer-registry-prometheus
77 |
78 |
79 |
80 |
81 |
82 | org.springframework.cloud
83 | spring-cloud-dependencies
84 | ${spring-cloud.version}
85 | pom
86 | import
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | org.springframework.boot
95 | spring-boot-maven-plugin
96 |
97 |
98 |
99 | org.projectlombok
100 | lombok
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | spring-milestones
110 | Spring Milestones
111 | https://repo.spring.io/milestone
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/main/java/com/example/apigatewayservice/ApigatewayServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
5 | import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.context.annotation.Bean;
8 |
9 | @SpringBootApplication
10 | public class ApigatewayServiceApplication {
11 |
12 | public static void main(String[] args) {
13 | SpringApplication.run(ApigatewayServiceApplication.class, args);
14 | }
15 |
16 | @Bean
17 | public HttpTraceRepository httpTraceRepository() {
18 | return new InMemoryHttpTraceRepository();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/main/java/com/example/apigatewayservice/config/FilterConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.config;
2 |
3 | import org.springframework.cloud.gateway.route.RouteLocator;
4 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | //@Configuration
9 | public class FilterConfig {
10 | // @Bean
11 | public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
12 | return builder.routes()
13 | .route(r -> r.path("/first-service/**")
14 | .filters(f -> f.addRequestHeader("first-request", "first-request-header")
15 | .addResponseHeader("first-response", "first-response-header"))
16 | .uri("http://localhost:8081"))
17 | .route(r -> r.path("/second-service/**")
18 | .filters(f -> f.addRequestHeader("second-request", "second-request-header")
19 | .addResponseHeader("second-response", "second-response-header"))
20 | .uri("http://localhost:8082"))
21 | .build();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/main/java/com/example/apigatewayservice/filter/AuthorizationHeaderFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import com.google.common.net.HttpHeaders;
4 | import io.jsonwebtoken.Jwts;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.boot.web.servlet.server.Session;
7 | import org.springframework.cloud.gateway.filter.GatewayFilter;
8 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
9 | import org.springframework.core.env.Environment;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseCookie;
12 | import org.springframework.http.server.reactive.ServerHttpRequest;
13 | import org.springframework.http.server.reactive.ServerHttpResponse;
14 | import org.springframework.stereotype.Component;
15 | import org.springframework.web.server.ServerWebExchange;
16 | import reactor.core.publisher.Mono;
17 |
18 | @Component
19 | @Slf4j
20 | public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory {
21 | Environment env;
22 |
23 | public AuthorizationHeaderFilter(Environment env) {
24 | super(Config.class);
25 | this.env = env;
26 | }
27 |
28 | public static class Config {
29 | // Put configuration properties here
30 | }
31 |
32 | @Override
33 | public GatewayFilter apply(Config config) {
34 | return (exchange, chain) -> {
35 | ServerHttpRequest request = exchange.getRequest();
36 |
37 | if (!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
38 | return onError(exchange, "No authorization header", HttpStatus.UNAUTHORIZED);
39 | }
40 |
41 | String authorizationHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION).get(0);
42 | String jwt = authorizationHeader.replace("Bearer", "");
43 |
44 | // Create a cookie object
45 | // ServerHttpResponse response = exchange.getResponse();
46 | // ResponseCookie c1 = ResponseCookie.from("my_token", "test1234").maxAge(60 * 60 * 24).build();
47 | // response.addCookie(c1);
48 |
49 | if (!isJwtValid(jwt)) {
50 | return onError(exchange, "JWT token is not valid", HttpStatus.UNAUTHORIZED);
51 | }
52 |
53 | return chain.filter(exchange);
54 | };
55 | }
56 |
57 | private Mono onError(ServerWebExchange exchange, String err, HttpStatus httpStatus) {
58 | ServerHttpResponse response = exchange.getResponse();
59 | response.setStatusCode(httpStatus);
60 |
61 | log.error(err);
62 | return response.setComplete();
63 | }
64 |
65 | private boolean isJwtValid(String jwt) {
66 | boolean returnValue = true;
67 |
68 | String subject = null;
69 |
70 | try {
71 | subject = Jwts.parser().setSigningKey(env.getProperty("token.secret"))
72 | .parseClaimsJws(jwt).getBody()
73 | .getSubject();
74 | } catch (Exception ex) {
75 | returnValue = false;
76 | }
77 |
78 | if (subject == null || subject.isEmpty()) {
79 | returnValue = false;
80 | }
81 |
82 | return returnValue;
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/main/java/com/example/apigatewayservice/filter/CustomFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.cloud.gateway.filter.GatewayFilter;
5 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
6 | import org.springframework.http.server.reactive.ServerHttpRequest;
7 | import org.springframework.http.server.reactive.ServerHttpResponse;
8 | import org.springframework.stereotype.Component;
9 | import reactor.core.publisher.Mono;
10 |
11 | @Component
12 | @Slf4j
13 | public class CustomFilter extends AbstractGatewayFilterFactory {
14 | public CustomFilter() {
15 | super(Config.class);
16 | }
17 |
18 | @Override
19 | public GatewayFilter apply(Config config) {
20 | // Custom Pre Filter
21 | return (exchange, chain) -> {
22 | ServerHttpRequest request = exchange.getRequest();
23 | ServerHttpResponse response = exchange.getResponse();
24 |
25 | log.info("Custom PRE filter: request id -> {}", request.getId());
26 |
27 | // Custom Post Filter
28 | return chain.filter(exchange).then(Mono.fromRunnable(() -> {
29 | log.info("Custom POST filter: response code -> {}", response.getStatusCode());
30 | }));
31 | };
32 | }
33 |
34 | public static class Config {
35 | // Put the configuration properties
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/main/java/com/example/apigatewayservice/filter/GlobalFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import lombok.Data;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.cloud.gateway.filter.GatewayFilter;
6 | import org.springframework.cloud.gateway.filter.GatewayFilterChain;
7 | import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
8 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
9 | import org.springframework.cloud.gateway.support.ipresolver.RemoteAddressResolver;
10 | import org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver;
11 | import org.springframework.core.Ordered;
12 | import org.springframework.http.HttpStatus;
13 | import org.springframework.http.server.reactive.ServerHttpRequest;
14 | import org.springframework.http.server.reactive.ServerHttpResponse;
15 | import org.springframework.stereotype.Component;
16 | import org.springframework.web.server.ServerWebExchange;
17 | import reactor.core.publisher.Mono;
18 |
19 | @Component
20 | @Slf4j
21 | public class GlobalFilter extends AbstractGatewayFilterFactory {
22 | public GlobalFilter() {
23 | super(Config.class);
24 | }
25 |
26 | @Override
27 | public GatewayFilter apply(Config config) {
28 | return ((exchange, chain) -> {
29 | ServerHttpRequest request = exchange.getRequest();
30 | ServerHttpResponse response = exchange.getResponse();
31 |
32 | log.info("Global Filter baseMessage: {}, {}", config.getBaseMessage(), request.getRemoteAddress());
33 | if (config.isPreLogger()) {
34 | log.info("Global Filter Start: request id -> {}", request.getId());
35 | }
36 | return chain.filter(exchange).then(Mono.fromRunnable(()->{
37 | if (config.isPostLogger()) {
38 | log.info("Global Filter End: response code -> {}", response.getStatusCode());
39 | }
40 | }));
41 | });
42 | }
43 |
44 | @Data
45 | public static class Config {
46 | private String baseMessage;
47 | private boolean preLogger;
48 | private boolean postLogger;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/main/java/com/example/apigatewayservice/filter/LoggingFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import lombok.Data;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.cloud.gateway.filter.GatewayFilter;
6 | import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
7 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
8 | import org.springframework.core.Ordered;
9 | import org.springframework.http.server.reactive.ServerHttpRequest;
10 | import org.springframework.http.server.reactive.ServerHttpResponse;
11 | import org.springframework.stereotype.Component;
12 | import reactor.core.publisher.Mono;
13 |
14 | @Component
15 | @Slf4j
16 | public class LoggingFilter extends AbstractGatewayFilterFactory {
17 | public LoggingFilter() {
18 | super(Config.class);
19 | }
20 |
21 | @Override
22 | public GatewayFilter apply(Config config) {
23 | // return ((exchange, chain) -> {
24 | // ServerHttpRequest request = exchange.getRequest();
25 | // ServerHttpResponse response = exchange.getResponse();
26 | //
27 | // log.info("Global Filter baseMessage: {}", config.getBaseMessage());
28 | // if (config.isPreLogger()) {
29 | // log.info("Global Filter Start: request id -> {}", request.getId());
30 | // }
31 | // return chain.filter(exchange).then(Mono.fromRunnable(()->{
32 | // if (config.isPostLogger()) {
33 | // log.info("Global Filter End: response code -> {}", response.getStatusCode());
34 | // }
35 | // }));
36 | // });
37 | GatewayFilter filter = new OrderedGatewayFilter((exchange, chain) -> {
38 | ServerHttpRequest request = exchange.getRequest();
39 | ServerHttpResponse response = exchange.getResponse();
40 |
41 | log.info("Logging Filter baseMessage: {}", config.getBaseMessage());
42 | if (config.isPreLogger()) {
43 | log.info("Logging PRE Filter: request id -> {}", request.getId());
44 | }
45 | return chain.filter(exchange).then(Mono.fromRunnable(()->{
46 | if (config.isPostLogger()) {
47 | log.info("Logging POST Filter: response code -> {}", response.getStatusCode());
48 | }
49 | }));
50 | }, Ordered.LOWEST_PRECEDENCE);
51 |
52 | return filter;
53 | }
54 |
55 | @Data
56 | public static class Config {
57 | private String baseMessage;
58 | private boolean preLogger;
59 | private boolean postLogger;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8000
3 |
4 | eureka:
5 | client:
6 | register-with-eureka: true
7 | fetch-registry: true
8 | service-url:
9 | defaultZone: http://localhost:8761/eureka
10 |
11 | spring:
12 | application:
13 | name: apigateway-service
14 |
15 | cloud:
16 | gateway:
17 | default-filters:
18 | - name: GlobalFilter
19 | args:
20 | baseMessage: Spring Cloud Gateway Global Filter
21 | preLogger: true
22 | postLogger: true
23 | routes:
24 | # - id: user-service
25 | # uri: lb://USER-SERVICE
26 | # predicates:
27 | # - Path=/user-service/**
28 | - id: user-service
29 | uri: lb://USER-SERVICE
30 | predicates:
31 | - Path=/user-service/login
32 | - Method=POST
33 | filters:
34 | - RemoveRequestHeader=Cookie
35 | - RewritePath=/user-service/(?.*), /$\{segment}
36 | - id: user-service
37 | uri: lb://USER-SERVICE
38 | predicates:
39 | - Path=/user-service/users
40 | - Method=POST
41 | filters:
42 | - RemoveRequestHeader=Cookie
43 | - RewritePath=/user-service/(?.*), /$\{segment}
44 | - id: user-service
45 | uri: lb://USER-SERVICE
46 | predicates:
47 | - Path=/user-service/actuator/**
48 | - Method=GET,POST
49 | filters:
50 | - RemoveRequestHeader=Cookie
51 | - RewritePath=/user-service/(?.*), /$\{segment}
52 | - id: user-service
53 | uri: lb://USER-SERVICE
54 | predicates:
55 | - Path=/user-service/**
56 | - Method=GET
57 | filters:
58 | - RemoveRequestHeader=Cookie
59 | - RewritePath=/user-service/(?.*), /$\{segment}
60 | - AuthorizationHeaderFilter
61 | - id: catalog-service
62 | uri: lb://CATALOG-SERVICE
63 | predicates:
64 | - Path=/catalog-service/**
65 | - id: order-service
66 | uri: lb://ORDER-SERVICE
67 | predicates:
68 | - Path=/order-service/actuator/**
69 | - Method=GET,POST
70 | filters:
71 | - RemoveRequestHeader=Cookie
72 | - RewritePath=/order-service/(?.*), /$\{segment}
73 | - id: order-service
74 | uri: lb://ORDER-SERVICE
75 | predicates:
76 | - Path=/order-service/**
77 | - id: first-service
78 | uri: lb://MY-FIRST-SERVICE
79 | predicates:
80 | - Path=/first-service/**
81 | filters:
82 | - AddRequestHeader=first-request, first-request-header2
83 | - AddResponseHeader=first-response, first-response-header2
84 | # - CustomFilter
85 | - id: second-service
86 | uri: lb://MY-SECOND-SERVICE
87 | predicates:
88 | - Path=/second-service/**
89 | filters:
90 | - AddRequestHeader=second-request, second-request-header2
91 | - AddResponseHeader=second-response, second-response-header2
92 | # - name: CustomFilter
93 | - name: LoggingFilter
94 | args:
95 | baseMessage: Hi, there.
96 | preLogger: true
97 | postLogger: true
98 |
99 | token:
100 | expiration_time: 86400000
101 | secret: user_token
102 |
103 | management:
104 | endpoints:
105 | web:
106 | exposure:
107 | include: refresh, health, beans, httptrace, busrefresh, info, metrics, prometheus
--------------------------------------------------------------------------------
/apigateway-service-no-config/src/test/java/com/example/apigatewayservice/ApigatewayServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ApigatewayServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/apigateway-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/apigateway-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joneconsulting/msa_with_spring_cloud/5827d698c9793f1799eeafb26002cab50cd65d5d/apigateway-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/apigateway-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/apigateway-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17-ea-11-jdk-slim
2 | VOLUME /tmp
3 | COPY target/apigateway-service-1.0.jar ApigatewayService.jar
4 | ENTRYPOINT ["java", "-jar", "ApigatewayService.jar"]
--------------------------------------------------------------------------------
/apigateway-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.4.2
9 |
10 |
11 | com.example
12 | apigateway-service
13 | 1.0
14 | apigateway-service
15 | Demo project for Spring Boot
16 |
17 | 11
18 | 2020.0.0
19 |
20 |
21 |
22 | org.springframework.cloud
23 | spring-cloud-starter-gateway
24 |
25 |
26 | org.springframework.cloud
27 | spring-cloud-starter-netflix-eureka-client
28 |
29 |
30 |
31 | org.projectlombok
32 | lombok
33 | true
34 |
35 |
36 | org.springframework.boot
37 | spring-boot-starter-test
38 | test
39 |
40 |
41 | io.jsonwebtoken
42 | jjwt
43 | 0.9.1
44 |
45 |
46 | javax.xml.bind
47 | jaxb-api
48 |
49 |
50 |
51 | org.springframework.cloud
52 | spring-cloud-starter-config
53 |
54 |
55 |
56 | org.springframework.cloud
57 | spring-cloud-starter-bootstrap
58 |
59 |
60 |
61 | org.springframework.boot
62 | spring-boot-starter-actuator
63 |
64 |
65 |
66 | org.springframework.cloud
67 | spring-cloud-starter-bus-amqp
68 |
69 |
70 |
71 | io.micrometer
72 | micrometer-registry-prometheus
73 |
74 |
75 |
76 |
77 |
78 | org.springframework.cloud
79 | spring-cloud-dependencies
80 | ${spring-cloud.version}
81 | pom
82 | import
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | org.springframework.boot
91 | spring-boot-maven-plugin
92 |
93 |
94 |
95 | org.projectlombok
96 | lombok
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | spring-milestones
106 | Spring Milestones
107 | https://repo.spring.io/milestone
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/apigateway-service/src/main/java/com/example/apigatewayservice/ApigatewayServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
5 | import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.context.annotation.Bean;
8 |
9 | @SpringBootApplication
10 | public class ApigatewayServiceApplication {
11 |
12 | public static void main(String[] args) {
13 | SpringApplication.run(ApigatewayServiceApplication.class, args);
14 | }
15 |
16 | @Bean
17 | public HttpTraceRepository httpTraceRepository() {
18 | return new InMemoryHttpTraceRepository();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/apigateway-service/src/main/java/com/example/apigatewayservice/config/FilterConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.config;
2 |
3 | import org.springframework.cloud.gateway.route.RouteLocator;
4 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 |
8 | //@Configuration
9 | public class FilterConfig {
10 | // @Bean
11 | public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
12 | return builder.routes()
13 | .route(r -> r.path("/first-service/**")
14 | .filters(f -> f.addRequestHeader("first-request", "first-request-header")
15 | .addResponseHeader("first-response", "first-response-header"))
16 | .uri("http://localhost:8081"))
17 | .route(r -> r.path("/second-service/**")
18 | .filters(f -> f.addRequestHeader("second-request", "second-request-header")
19 | .addResponseHeader("second-response", "second-response-header"))
20 | .uri("http://localhost:8082"))
21 | .build();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/apigateway-service/src/main/java/com/example/apigatewayservice/filter/AuthorizationHeaderFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import com.google.common.net.HttpHeaders;
4 | import io.jsonwebtoken.Jwts;
5 | import lombok.extern.slf4j.Slf4j;
6 | import org.springframework.boot.web.servlet.server.Session;
7 | import org.springframework.cloud.gateway.filter.GatewayFilter;
8 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
9 | import org.springframework.core.env.Environment;
10 | import org.springframework.http.HttpStatus;
11 | import org.springframework.http.ResponseCookie;
12 | import org.springframework.http.server.reactive.ServerHttpRequest;
13 | import org.springframework.http.server.reactive.ServerHttpResponse;
14 | import org.springframework.stereotype.Component;
15 | import org.springframework.web.server.ServerWebExchange;
16 | import reactor.core.publisher.Mono;
17 |
18 | @Component
19 | @Slf4j
20 | public class AuthorizationHeaderFilter extends AbstractGatewayFilterFactory {
21 | Environment env;
22 |
23 | public AuthorizationHeaderFilter(Environment env) {
24 | super(Config.class);
25 | this.env = env;
26 | }
27 |
28 | public static class Config {
29 | // Put configuration properties here
30 | }
31 |
32 | @Override
33 | public GatewayFilter apply(Config config) {
34 | return (exchange, chain) -> {
35 | ServerHttpRequest request = exchange.getRequest();
36 |
37 | if (!request.getHeaders().containsKey(HttpHeaders.AUTHORIZATION)) {
38 | return onError(exchange, "No authorization header", HttpStatus.UNAUTHORIZED);
39 | }
40 |
41 | String authorizationHeader = request.getHeaders().get(HttpHeaders.AUTHORIZATION).get(0);
42 | String jwt = authorizationHeader.replace("Bearer", "");
43 |
44 | // Create a cookie object
45 | // ServerHttpResponse response = exchange.getResponse();
46 | // ResponseCookie c1 = ResponseCookie.from("my_token", "test1234").maxAge(60 * 60 * 24).build();
47 | // response.addCookie(c1);
48 |
49 | if (!isJwtValid(jwt)) {
50 | return onError(exchange, "JWT token is not valid", HttpStatus.UNAUTHORIZED);
51 | }
52 |
53 | return chain.filter(exchange);
54 | };
55 | }
56 |
57 | private Mono onError(ServerWebExchange exchange, String err, HttpStatus httpStatus) {
58 | ServerHttpResponse response = exchange.getResponse();
59 | response.setStatusCode(httpStatus);
60 |
61 | log.error(err);
62 | return response.setComplete();
63 | }
64 |
65 | private boolean isJwtValid(String jwt) {
66 | boolean returnValue = true;
67 |
68 | String subject = null;
69 |
70 | try {
71 | subject = Jwts.parser().setSigningKey(env.getProperty("token.secret"))
72 | .parseClaimsJws(jwt).getBody()
73 | .getSubject();
74 | } catch (Exception ex) {
75 | returnValue = false;
76 | }
77 |
78 | if (subject == null || subject.isEmpty()) {
79 | returnValue = false;
80 | }
81 |
82 | return returnValue;
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/apigateway-service/src/main/java/com/example/apigatewayservice/filter/CustomFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.cloud.gateway.filter.GatewayFilter;
5 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
6 | import org.springframework.http.server.reactive.ServerHttpRequest;
7 | import org.springframework.http.server.reactive.ServerHttpResponse;
8 | import org.springframework.stereotype.Component;
9 | import reactor.core.publisher.Mono;
10 |
11 | @Component
12 | @Slf4j
13 | public class CustomFilter extends AbstractGatewayFilterFactory {
14 | public CustomFilter() {
15 | super(Config.class);
16 | }
17 |
18 | @Override
19 | public GatewayFilter apply(Config config) {
20 | // Custom Pre Filter
21 | return (exchange, chain) -> {
22 | ServerHttpRequest request = exchange.getRequest();
23 | ServerHttpResponse response = exchange.getResponse();
24 |
25 | log.info("Custom PRE filter: request id -> {}", request.getId());
26 |
27 | // Custom Post Filter
28 | return chain.filter(exchange).then(Mono.fromRunnable(() -> {
29 | log.info("Custom POST filter: response code -> {}", response.getStatusCode());
30 | }));
31 | };
32 | }
33 |
34 | public static class Config {
35 | // Put the configuration properties
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/apigateway-service/src/main/java/com/example/apigatewayservice/filter/GlobalFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import lombok.Data;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.cloud.gateway.filter.GatewayFilter;
6 | import org.springframework.cloud.gateway.filter.GatewayFilterChain;
7 | import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
8 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
9 | import org.springframework.cloud.gateway.support.ipresolver.RemoteAddressResolver;
10 | import org.springframework.cloud.gateway.support.ipresolver.XForwardedRemoteAddressResolver;
11 | import org.springframework.core.Ordered;
12 | import org.springframework.http.HttpStatus;
13 | import org.springframework.http.server.reactive.ServerHttpRequest;
14 | import org.springframework.http.server.reactive.ServerHttpResponse;
15 | import org.springframework.stereotype.Component;
16 | import org.springframework.web.server.ServerWebExchange;
17 | import reactor.core.publisher.Mono;
18 |
19 | @Component
20 | @Slf4j
21 | public class GlobalFilter extends AbstractGatewayFilterFactory {
22 | public GlobalFilter() {
23 | super(Config.class);
24 | }
25 |
26 | @Override
27 | public GatewayFilter apply(Config config) {
28 | return ((exchange, chain) -> {
29 | ServerHttpRequest request = exchange.getRequest();
30 | ServerHttpResponse response = exchange.getResponse();
31 |
32 | log.info("Global Filter baseMessage: {}, {}", config.getBaseMessage(), request.getRemoteAddress());
33 | if (config.isPreLogger()) {
34 | log.info("Global Filter Start: request id -> {}", request.getId());
35 | }
36 | return chain.filter(exchange).then(Mono.fromRunnable(()->{
37 | if (config.isPostLogger()) {
38 | log.info("Global Filter End: response code -> {}", response.getStatusCode());
39 | }
40 | }));
41 | });
42 | }
43 |
44 | @Data
45 | public static class Config {
46 | private String baseMessage;
47 | private boolean preLogger;
48 | private boolean postLogger;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/apigateway-service/src/main/java/com/example/apigatewayservice/filter/LoggingFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice.filter;
2 |
3 | import lombok.Data;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.cloud.gateway.filter.GatewayFilter;
6 | import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
7 | import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
8 | import org.springframework.core.Ordered;
9 | import org.springframework.http.server.reactive.ServerHttpRequest;
10 | import org.springframework.http.server.reactive.ServerHttpResponse;
11 | import org.springframework.stereotype.Component;
12 | import reactor.core.publisher.Mono;
13 |
14 | @Component
15 | @Slf4j
16 | public class LoggingFilter extends AbstractGatewayFilterFactory {
17 | public LoggingFilter() {
18 | super(Config.class);
19 | }
20 |
21 | @Override
22 | public GatewayFilter apply(Config config) {
23 | // return ((exchange, chain) -> {
24 | // ServerHttpRequest request = exchange.getRequest();
25 | // ServerHttpResponse response = exchange.getResponse();
26 | //
27 | // log.info("Global Filter baseMessage: {}", config.getBaseMessage());
28 | // if (config.isPreLogger()) {
29 | // log.info("Global Filter Start: request id -> {}", request.getId());
30 | // }
31 | // return chain.filter(exchange).then(Mono.fromRunnable(()->{
32 | // if (config.isPostLogger()) {
33 | // log.info("Global Filter End: response code -> {}", response.getStatusCode());
34 | // }
35 | // }));
36 | // });
37 | GatewayFilter filter = new OrderedGatewayFilter((exchange, chain) -> {
38 | ServerHttpRequest request = exchange.getRequest();
39 | ServerHttpResponse response = exchange.getResponse();
40 |
41 | log.info("Logging Filter baseMessage: {}", config.getBaseMessage());
42 | if (config.isPreLogger()) {
43 | log.info("Logging PRE Filter: request id -> {}", request.getId());
44 | }
45 | return chain.filter(exchange).then(Mono.fromRunnable(()->{
46 | if (config.isPostLogger()) {
47 | log.info("Logging POST Filter: response code -> {}", response.getStatusCode());
48 | }
49 | }));
50 | }, Ordered.LOWEST_PRECEDENCE);
51 |
52 | return filter;
53 | }
54 |
55 | @Data
56 | public static class Config {
57 | private String baseMessage;
58 | private boolean preLogger;
59 | private boolean postLogger;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/apigateway-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8000
3 |
4 | eureka:
5 | client:
6 | register-with-eureka: true
7 | fetch-registry: true
8 | service-url:
9 | defaultZone: http://localhost:8761/eureka
10 |
11 | spring:
12 | application:
13 | name: apigateway-service
14 | rabbitmq:
15 | host: 127.0.0.1
16 | port: 5672
17 | username: guest
18 | password: guest
19 | cloud:
20 | gateway:
21 | default-filters:
22 | - name: GlobalFilter
23 | args:
24 | baseMessage: Spring Cloud Gateway Global Filter
25 | preLogger: true
26 | postLogger: true
27 | routes:
28 | # - id: user-service
29 | # uri: lb://USER-SERVICE
30 | # predicates:
31 | # - Path=/user-service/**
32 | - id: user-service
33 | uri: lb://USER-SERVICE
34 | predicates:
35 | - Path=/user-service/login
36 | - Method=POST
37 | filters:
38 | - RemoveRequestHeader=Cookie
39 | - RewritePath=/user-service/(?.*), /$\{segment}
40 | - id: user-service
41 | uri: lb://USER-SERVICE
42 | predicates:
43 | - Path=/user-service/users
44 | - Method=POST
45 | filters:
46 | - RemoveRequestHeader=Cookie
47 | - RewritePath=/user-service/(?.*), /$\{segment}
48 | - id: user-service
49 | uri: lb://USER-SERVICE
50 | predicates:
51 | - Path=/user-service/actuator/**
52 | - Method=GET,POST
53 | filters:
54 | - RemoveRequestHeader=Cookie
55 | - RewritePath=/user-service/(?.*), /$\{segment}
56 | - id: user-service
57 | uri: lb://USER-SERVICE
58 | predicates:
59 | - Path=/user-service/**
60 | - Method=GET
61 | filters:
62 | - RemoveRequestHeader=Cookie
63 | - RewritePath=/user-service/(?.*), /$\{segment}
64 | - AuthorizationHeaderFilter
65 | - id: catalog-service
66 | uri: lb://CATALOG-SERVICE
67 | predicates:
68 | - Path=/catalog-service/**
69 | - id: order-service
70 | uri: lb://ORDER-SERVICE
71 | predicates:
72 | - Path=/order-service/actuator/**
73 | - Method=GET,POST
74 | filters:
75 | - RemoveRequestHeader=Cookie
76 | - RewritePath=/order-service/(?.*), /$\{segment}
77 | - id: order-service
78 | uri: lb://ORDER-SERVICE
79 | predicates:
80 | - Path=/order-service/**
81 | - id: first-service
82 | uri: lb://MY-FIRST-SERVICE
83 | predicates:
84 | - Path=/first-service/**
85 | filters:
86 | - AddRequestHeader=first-request, first-request-header2
87 | - AddResponseHeader=first-response, first-response-header2
88 | # - CustomFilter
89 | - id: second-service
90 | uri: lb://MY-SECOND-SERVICE
91 | predicates:
92 | - Path=/second-service/**
93 | filters:
94 | - AddRequestHeader=second-request, second-request-header2
95 | - AddResponseHeader=second-response, second-response-header2
96 | # - name: CustomFilter
97 | - name: LoggingFilter
98 | args:
99 | baseMessage: Hi, there.
100 | preLogger: true
101 | postLogger: true
102 |
103 | #token:
104 | # secret: user_token
105 |
106 | management:
107 | endpoints:
108 | web:
109 | exposure:
110 | include: refresh, health, beans, httptrace, busrefresh, info, metrics, prometheus
--------------------------------------------------------------------------------
/apigateway-service/src/main/resources/bootstrap.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | cloud:
3 | config:
4 | uri: http://127.0.0.1:8888
5 | name: user-service
6 | # profiles:
7 | # active: dev
--------------------------------------------------------------------------------
/apigateway-service/src/test/java/com/example/apigatewayservice/ApigatewayServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.apigatewayservice;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ApigatewayServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/catalog-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/catalog-service/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/joneconsulting/msa_with_spring_cloud/5827d698c9793f1799eeafb26002cab50cd65d5d/catalog-service/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/catalog-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/catalog-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM openjdk:17-ea-11-jdk-slim
2 | VOLUME /tmp
3 | COPY target/catalog-service-1.0.jar CatalogService.jar
4 | ENTRYPOINT ["java", "-jar", "CatalogService.jar"]
--------------------------------------------------------------------------------
/catalog-service/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.4.2
9 |
10 |
11 | com.example
12 | catalog-service
13 | 1.0
14 | catalog-service
15 | Demo project for Spring Boot
16 |
17 | 11
18 | 2020.0.0
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-data-jpa
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-starter-web
28 |
29 |
30 | org.springframework.cloud
31 | spring-cloud-starter-netflix-eureka-client
32 |
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-devtools
37 | runtime
38 | true
39 |
40 |
41 | com.h2database
42 | h2
43 | 1.3.176
44 | runtime
45 |
46 |
47 |
48 | org.modelmapper
49 | modelmapper
50 | 2.3.8
51 |
52 |
53 |
54 | org.projectlombok
55 | lombok
56 | true
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-test
61 | test
62 |
63 |
64 |
65 |
66 | org.springframework.kafka
67 | spring-kafka
68 |
69 |
70 |
71 |
72 |
73 | org.springframework.cloud
74 | spring-cloud-dependencies
75 | ${spring-cloud.version}
76 | pom
77 | import
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | org.springframework.boot
86 | spring-boot-maven-plugin
87 |
88 |
89 |
90 | org.projectlombok
91 | lombok
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | spring-milestones
101 | Spring Milestones
102 | https://repo.spring.io/milestone
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/catalog-service/src/main/java/com/example/catalogservice/CatalogServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.catalogservice;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class CatalogServiceApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(CatalogServiceApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/catalog-service/src/main/java/com/example/catalogservice/controller/CatalogController.java:
--------------------------------------------------------------------------------
1 | package com.example.catalogservice.controller;
2 |
3 | import com.example.catalogservice.jpa.CatalogEntity;
4 | import com.example.catalogservice.service.CatalogService;
5 | import com.example.catalogservice.vo.ResponseCatalog;
6 | import org.modelmapper.ModelMapper;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.core.env.Environment;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.http.ResponseEntity;
11 | import org.springframework.web.bind.annotation.GetMapping;
12 | import org.springframework.web.bind.annotation.RequestMapping;
13 | import org.springframework.web.bind.annotation.RestController;
14 |
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | @RestController
19 | @RequestMapping("/catalog-service")
20 | public class CatalogController {
21 | Environment env;
22 | CatalogService catalogService;
23 |
24 | @Autowired
25 | public CatalogController(Environment env, CatalogService catalogService) {
26 | this.env = env;
27 | this.catalogService = catalogService;
28 | }
29 |
30 | @GetMapping("/health_check")
31 | public String status() {
32 | return String.format("It's Working in Catalog Service on PORT %s",
33 | env.getProperty("local.server.port"));
34 | }
35 |
36 | @GetMapping("/catalogs")
37 | public ResponseEntity> getCatalogs() {
38 | Iterable catalogList = catalogService.getAllCatalogs();
39 |
40 | List result = new ArrayList<>();
41 | catalogList.forEach(v -> {
42 | result.add(new ModelMapper().map(v, ResponseCatalog.class));
43 | });
44 |
45 | return ResponseEntity.status(HttpStatus.OK).body(result);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/catalog-service/src/main/java/com/example/catalogservice/dto/CatalogDto.java:
--------------------------------------------------------------------------------
1 | package com.example.catalogservice.dto;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 |
7 | @Data
8 | public class CatalogDto implements Serializable {
9 | private String productId;
10 | private Integer qty;
11 | private Integer unitPrice;
12 | private Integer totalPrice;
13 |
14 | private String orderId;
15 | private String userId;
16 | }
17 |
--------------------------------------------------------------------------------
/catalog-service/src/main/java/com/example/catalogservice/jpa/CatalogEntity.java:
--------------------------------------------------------------------------------
1 | package com.example.catalogservice.jpa;
2 |
3 | import lombok.Data;
4 | import org.hibernate.annotations.ColumnDefault;
5 |
6 | import javax.persistence.*;
7 | import java.io.Serializable;
8 | import java.util.Date;
9 |
10 | @Data
11 | @Entity
12 | @Table(name = "catalog")
13 | public class CatalogEntity implements Serializable {
14 | @Id
15 | @GeneratedValue(strategy = GenerationType.IDENTITY)
16 | private Long id;
17 |
18 | @Column(nullable = false, length = 120, unique = true)
19 | private String productId;
20 | @Column(nullable = false)
21 | private String productName;
22 | @Column(nullable = false)
23 | private Integer stock;
24 | @Column(nullable = false)
25 | private Integer unitPrice;
26 |
27 | @Column(nullable = false, updatable = false, insertable = false)
28 | @ColumnDefault(value = "CURRENT_TIMESTAMP")
29 | private Date createdAt;
30 | }
31 |
--------------------------------------------------------------------------------
/catalog-service/src/main/java/com/example/catalogservice/jpa/CatalogRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.catalogservice.jpa;
2 |
3 | import org.springframework.data.repository.CrudRepository;
4 |
5 | public interface CatalogRepository extends CrudRepository {
6 | CatalogEntity findByProductId(String productId);
7 | }
8 |
--------------------------------------------------------------------------------
/catalog-service/src/main/java/com/example/catalogservice/messagequeue/KafkaConsumer.java:
--------------------------------------------------------------------------------
1 | package com.example.catalogservice.messagequeue;
2 |
3 | import com.example.catalogservice.jpa.CatalogEntity;
4 | import com.example.catalogservice.jpa.CatalogRepository;
5 | import com.fasterxml.jackson.core.JsonProcessingException;
6 | import com.fasterxml.jackson.core.type.TypeReference;
7 | import com.fasterxml.jackson.databind.ObjectMapper;
8 | import lombok.extern.slf4j.Slf4j;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.kafka.annotation.KafkaListener;
11 | import org.springframework.stereotype.Service;
12 |
13 | import java.util.HashMap;
14 | import java.util.Map;
15 |
16 | @Service
17 | @Slf4j
18 | public class KafkaConsumer {
19 | CatalogRepository repository;
20 |
21 | @Autowired
22 | public KafkaConsumer(CatalogRepository repository) {
23 | this.repository = repository;
24 | }
25 |
26 | @KafkaListener(topics = "example-catalog-topic")
27 | public void updateQty(String kafkaMessage) {
28 | log.info("Kafka Message: ->" + kafkaMessage);
29 |
30 | Map