Spring Cloud Gateway tutorial
When we implement API gateway pattern, Spring Cloud Gateway
is one of the options provided by Spring cloud framework.
Spring Cloud Gateway
enables routing to APIs and solves cross-cutting concerns like security, monitoring, resiliency.
It is based on Spring 5
and uses Netty web server
& reactor framework underneath. If you compare Spring Cloud Gateway
with Netflix's Zuul 1.0
, Spring Cloud Gateway
supports asynchronous & non blocking connections while Zuul 1.0
does not.
Spring Cloud Gateway
is based on below three concepts
-
Route
: A route consists of a unique id, destination uri, list of predicates & a list of filters. All predicates need to be fullfilled to match a route -
Predicates
: Contains logic to match a uri, for e.g if a request type if GET type, follows a particular path like /customers/ -
Filters
: Used to modify the incoming request, for e.g it can be used to add headers, or modify path.
In this Spring Cloud Gateway
tutorial, we will create a Customer service which returns a customer details but the actual service call to Customer service will go through Spring Cloud Gateway
. So a caller will send request to gateway which will route the call to the customer service. Similarly you can add more services like order service, account service.
Step 1) Add below dependencies in pom.xml for GatewayApplication
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.3</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-stub-runner</artifactId> <exclusions> <exclusion> <artifactId>spring-boot-starter-web</artifactId> <groupId>org.springframework.boot</groupId> </exclusion> </exclusions> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2021.0.3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Step 2) Create Gateway application
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } @Bean public RouteLocator myRoutes(RouteLocatorBuilder builder) { return builder.routes() route(p -> p.method(HttpMethod.GET).and().path("/customers/{id}") .filters(f -> f.addRequestHeader("Hello", "World").prefixPath("/v1")) .uri("http://localhost:8080")).build(); } }
Step 3) Add application.yml
server: port: 9999
Note that you can also configure routes in application.yml instead of creating in GatewayApplication class as shown below
server: port: 9999 spring: cloud: gateway: routes: - id: customer-service uri: http://localhost:8080 predicates: - Method=GET - Path=/customers/{id} filters: - AddRequestHeader=Hello, World - PrefixPath=/v1
Step 3) Create CustomerService application which returns a customer details
Create CustomerRestController, Customer, CustomerServiceApplication classes, application.yml file.
spring: application: name: customer-service server: port: 8080
spackage com.example.demo; public class Customer { private String id; private String name; // removed getters, setters for brevity }
package com.example.demo; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class CustomerRestController { private static final Logger LOG = LoggerFactory.getLogger(CustomerRestController.class); private List<Customer> customers = new ArrayList<>(); public CustomerRestController() { customers.add(new Customer("superman", "Clark Kent")); customers.add(new Customer("batman", "Ben Affleck")); customers.add(new Customer("thor", "Chris Hemsworth")); } @RequestMapping(value = "/v1/customers/{id}") public Customer getCustomer(@PathVariable String id) { LOG.info("returning toy"); return customers.stream().filter(customer -> customer.getId().equalsIgnoreCase(id)).findFirst().get(); } }
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class CustomerServiceApplication { public static void main(String[] args) { SpringApplication.run(CustomerServiceApplication.class, args); } }
Step 4) Testing Spring cloud gateway
CustomerServiceApplication
& GatewayApplication
, in browser navigate to http://localhost:9999/customers/batman.Note that above request goes to
GatewayApplication
which routes the request to http://localhost:8080/v1/customers/batman
You will see below page displayed in the broswer.
References :
Spring Cloud Gateway