Implementation of Spring Cloud Gateway with Spring WebFlux
Create the Gateway Project
Step 1: Create the Spring Project
We will create the new spring reactive project for the gateway service and add the below dependencies into the project.
Dependencies
- Spring Reactive Web
- Spring Gateway
- Lombok
- Spring DevTools
After creating the project, structure will be like below.
Step 2: Configure the Application properties
Open the application.properties file and rename into application.yml to add the gateway configuration.
server:
port: 8088
spring:
application:
name: gateway-service
cloud:
gateway:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
routes:
- id: example_route
uri: http://localhost:8081
predicates:
- Path=/example/**
filters:
- AddRequestHeader=X-Request-Example, Gateway-Request
- AddResponseHeader=X-Response-Example, Gateway-Response
Step 3: Create the CustomFilter class
We will now create the CustomFilter class to demonstrate how to send request and responses in the application.
Go to src > main > java > org.example.webfluxapi > filters > CustomFilter and put the below code.
package org.example.webfluxapi.filters;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config> {
public CustomFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// Pre-processing
if (!exchange.getRequest().getHeaders().containsKey("X-Request-Id")) {
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
// Post-processing
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
exchange.getResponse().getHeaders().add("X-Response-Default-Foo", "Default-Bar");
}));
};
}
public static class Config {
// Put the configuration properties for your filter here
}
}
Step 4: Create the GatewayConfig class
We will create the GatewayConfig class to define the routes and filters of the application.
Go to src > main > java > org.example.webfluxapi > config > GatewayConfig and put the below code.
package org.example.webfluxapi.config;
import org.example.webfluxapi.filters.CustomFilter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, CustomFilter customFilter) {
return builder.routes()
.route("example_route", r -> r.path("/example/service/**")
.filters(f -> f.filter(customFilter.apply(new CustomFilter.Config())))
.uri("http://localhost:8081"))
.build();
}
}
Step 5: Main Class
No changes are required in the main class of the project.
package org.example.webfluxapi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class WebfluxApiApplication {
public static void main(String[] args) {
SpringApplication.run(WebfluxApiApplication.class, args);
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.7-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>webflux-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>webflux-api</name>
<description>webflux-api</description>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</pluginRepository>
</pluginRepositories>
</project>
Step 6: Run the application
Once complete the project, we will now run the application and then it will start at port 8088.
Create the Example-microservice
Step 1: Create the Spring Project
Now, we will create one new spring reactive project for the example-microservice service by adding the below dependencies into the project.
Dependencies:
- Spring Reactive Web
- Lombok
- Spring DevTools
Folder Structure:
Step 2: Configure the Application properties
Open the application.properties file and rename into application.yml to add the server port configuration.
server:
port: 8081
spring:
application:
name: example-microservice
Step 3: Create the ExampleController class
We will create the ExampleController class to define the simple REST endpoint of the Spring application.
Go to src > main > src > org.example.examplemicroservice > ExampleController and put the below code.
package org.example.examplemicroservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class ExampleController {
@GetMapping("/example/service")
public Mono<String> exampleEndpoint() {
return Mono.just("Hello from the Example Microservice!");
}
}
Step 4: Main Class
No changes are required in the main class.
package org.example.examplemicroservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExampleMicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleMicroserviceApplication.class, args);
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.example</groupId>
<artifactId>example-microservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>example-microservice</name>
<description>example-microservice</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Step 5: Run the application
Once complete the project, we will now run the application and then it will start at port 8081.
Testing the API Endpoint Gateway
After successfully running both the gateway and microservices, we will now test the endpoints:
API Endpoint:
GET http://localhost:8080/example/service
Output:
Spring Cloud Gateway with Spring WebFlux
Spring Cloud Gateway is the library that allows you to build API gateways on top of Spring WebFlux. It provides a simple and effective way to route requests, apply filters, and manage cross-cutting concerns reactively. This article will guide you through demonstrating how to set up Spring Cloud Gateway with a simple microservice and route requests through the gateway to the microservice.
Spring Cloud Gateway routes incoming requests to downstream services based on various predicates and filters. It allows you to apply custom logic to the request and response flows using filters. This setup can be particularly useful in microservices architecture, where it acts as the entry point for external requests and forwards them to the appropriate microservices.
Project Overview:
We will create two main components:
- Gateway Service: This service will use Spring Cloud Gateway to route incoming requests to downstream services. It will be configured to handle requests, apply filters, and manage cross-cutting concerns.
- Example Microservice: This is a simple microservice that will serve as the target for the requests routed through the gateway.