Learn how to build an API Gateway using Spring Cloud Gateway. Route requests to multiple microservices, configure custom filters, and enable monitoring.
-
Generate a new Spring Boot project using Spring Initializr.
- Visit https://start.spring.io/.
- Configure the project:
- Spring Boot Version: Select 3.4.1.
- Group Id:
com.microservices
- Artifact Id:
api-gateway
- Name:
ApiGateway
- Dependencies:
- Spring Cloud Gateway
- Spring Boot Actuator
- Click Generate to download the project zip file.
- Extract the downloaded zip file into a folder named
ApiGateway
.
-
Import the project into your IDE.
-
Enable Gateway functionality in
ApiGatewayApplication
.- Open
ApiGatewayApplication.java
in thesrc/main/java/com/microservices/apigateway
folder and ensure it contains:package com.microservices.apigateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ApiGatewayApplication { public static void main(String[] args) { SpringApplication.run(ApiGatewayApplication.class, args); } }
- Open
-
Configure basic routing in
application.yml
.- Create
application.yml
insrc/main/resources
and add:server: port: 8080 spring: cloud: gateway: routes: - id: user-service uri: http://localhost:8081 predicates: - Path=/users/** - id: product-service uri: http://localhost:8082 predicates: - Path=/products/**
- Create
-
Run the API Gateway application.
- Start the application:
./mvnw spring-boot:run
- Start the application:
-
Test basic routing.
- Start
UserService
(port8081
) andProductService
(port8082
). - Use Postman or a browser to test:
http://localhost:8080/users
routes toUserService
.http://localhost:8080/products
routes toProductService
.
- Start
-
Create
UserService
.- Generate a new Spring Boot project using Spring Initializr with:
- Artifact Id:
user-service
- Dependencies: Spring Web
- Artifact Id:
- Add
UserController
:package com.microservices.userservice; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class UserController { @GetMapping("/users") public String getUsers() { return "List of users from UserService"; } }
- Generate a new Spring Boot project using Spring Initializr with:
-
Create
ProductService
.- Generate another Spring Boot project using Spring Initializr with:
- Artifact Id:
product-service
- Dependencies: Spring Web
- Artifact Id:
- Add
ProductController
:package com.microservices.productservice; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ProductController { @GetMapping("/products") public String getProducts() { return "List of products from ProductService"; } }
- Generate another Spring Boot project using Spring Initializr with:
-
Run
UserService
andProductService
.- Configure ports in their respective
application.yml
files:server: port: 8081 # For UserService
server: port: 8082 # For ProductService
- Verify endpoints:
http://localhost:8081/users
http://localhost:8082/products
- Configure ports in their respective
-
Create a global logging filter.
- Add
LoggingFilter.java
insrc/main/java/com/microservices/apigateway
:package com.microservices.apigateway; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; @Component @Order(1) public class LoggingFilter implements GlobalFilter { private static final Logger logger = LoggerFactory.getLogger(LoggingFilter.class); @Override public Mono<Void> filter(org.springframework.web.server.ServerWebExchange exchange, org.springframework.cloud.gateway.filter.GatewayFilterChain chain) { logger.info("Incoming request: " + exchange.getRequest().getURI()); return chain.filter(exchange).then(Mono.fromRunnable(() -> { logger.info("Outgoing response: " + exchange.getResponse().getStatusCode()); })); } }
- Add
-
Test the global logging filter.
- Access
/users
or/products
and verify request/response logs in the console.
- Access
-
Add a route with custom headers.
- Update
application.yml
:spring: cloud: gateway: routes: - id: custom-route uri: http://httpbin.org:80 predicates: - Path=/custom/** filters: - AddRequestHeader=X-Custom-Header, CustomValue
- Update
-
Test the custom route.
- Access
http://localhost:8080/custom
and verify the custom header in the request.
- Access
-
Add a rate limiter.
- Add the
spring-boot-starter-data-redis
dependency inpom.xml
:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
- Configure rate limiting in
application.yml
:spring: cloud: gateway: routes: - id: rate-limited-route uri: http://httpbin.org:80 predicates: - Path=/rate-limited/** filters: - RequestRateLimiter: redis-rate-limiter.replenishRate=2 redis-rate-limiter.burstCapacity=2
- Add the
-
Test the rate limiter.
- Access
/rate-limited
multiple times. Verify requests are limited to 2 per burst.
- Access
-
Enable Spring Boot Actuator.
- Ensure this dependency is added:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
- Ensure this dependency is added:
-
Expose management endpoints.
- Add to
application.yml
:management: endpoints: web: exposure: include: routes,filters
- Add to
-
View active routes and filters.
- Access:
http://localhost:8080/actuator/routes
http://localhost:8080/actuator/filters
- Access:
-
Add a custom filter for response headers.
- Modify outgoing responses to include a custom header.
-
Test load balancing.
- Deploy multiple instances of
UserService
and test gateway load balancing.
- Deploy multiple instances of
-
Integrate Circuit Breakers.
- Add Resilience4j-based circuit breakers to specific routes.