A Guide to Spring Cloud Gateway

Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross-cutting concerns to them, such as security, monitoring/metrics, and resiliency.

In this post, I will cover common uses of Spring Cloud Gateway. This post is based on Java 21, Spring Boot 3.5.3, and Spring Cloud 2025.0.0.

Spring Cloud Gateway Server WebFlux

1. Create Project and Add Dependencies

Using Gradle

$ mkdir spring-cloud-gateway && cd spring-cloud-gateway
$ gradle --configuration-cache \
init --use-defaults \
--type java-application \
--package com.taogen.springcloud

app/build.gradle.kts

plugins {
java
id("org.springframework.boot") version "3.5.3"
// Use the Spring Dependency Management plugin to manage Spring Cloud dependencies.
id("io.spring.dependency-management") version "1.1.7"
}

extra["springCloudVersion"] = "2025.0.0"

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.cloud:spring-cloud-starter-gateway-server-webflux")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client")
implementation("org.springframework.boot:spring-boot-starter-actuator")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

dependencyManagement {
imports {
mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
}
}

tasks.withType<Test> {
useJUnitPlatform()
}

Using Maven

$ mvn -B archetype:generate \
-DgroupId=com.taogen.springcloud \
-DartifactId=spring-cloud-gateway \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.5

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.taogen.springcloud</groupId>
<artifactId>spring-cloud-gateway</artifactId>
<version>1.0-SNAPSHOT</version>

<name>spring-cloud-gateway</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>21</maven.compiler.release>
<java.version>21</java.version>
<spring-boot.version>3.5.3</spring-boot.version>
<spring-cloud.version>2025.0.0</spring-cloud.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway-server-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.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>
</plugin>
</plugins>
</build>
</project>

Using Spring Initializr

Go to https://start.spring.io/

Project Metadata

  • Group: com.taogen.springcloud
  • Artifact: spring-cloud-gateway

Add dependencies

  • Reactive Gateway
  • Eureka Discovery Client
  • Spring Reactive Web
  • Spring Boot Actuator

2. Spring Configuration

application.yml

eureka:
instance:
preferIpAddress: true
instanceId: ${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}
client:
registerWithEureka: true
fetchRegistry: true
serviceUrl:
defaultZone: http://localhost:8761/eureka/
healthcheck:
enabled: true

server:
port: 8072

management:
endpoint:
gateway:
access: read_only
endpoints:
web:
exposure:
include: health,info,beans,gateway

# Automated mapping of routes via service discovery
spring:
application:
name: my-spring-cloud-gateway
cloud:
gateway:
server:
webflux:
discovery:
locator:
enabled: true
lower-case-service-id: true

3. The Application

1. Spring Boot application entry point

1. SpringCloudGatewayApplication.java

package com.taogen.springcloud;  

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringCloudGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudGatewayApplication.class, args);
}
}

2. RestTemplate config

RestTemplateConfig.java

package com.taogen.springcloud;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

3. Request Eureka client services through Spring Cloud Gateway

MyController.java

package com.taogen.springcloud;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/")
public class MyController {
@Autowired
private DiscoveryClient discoveryClient;

@Autowired
private RestTemplate restTemplate;

@GetMapping("/callEurekaClientThroughGateway")
public String callEurekaClientThroughGateway() {
// the same with the value of spring.application.name in Spring Coud Gateway application
String serviceId = "my-spring-cloud-gateway";
String serviceUrl = discoveryClient.getInstances(serviceId).get(0).getUri().toString();
String response = restTemplate.getForObject(serviceUrl + "/eureka-client-1/greeting", String.class);
return response;
}
}

4. Start and Verification

Starting Spring Cloud Eureka Client

Running the main() method in the SpringCloudGatewayApplication to start the Spring Cloud Gateway server.

Verification

Request the /callEurekaClientThroughGateway endpoint to see the result of requesting Eureka client services through Spring Cloud Gateway.

5. Gateway Actuator API

The /gateway actuator endpoint lets you monitor and interact with a Spring Cloud Gateway application.

To enable Gateway Actuator API, you need to add the following configuration:

application.properties

management.endpoint.gateway.access=read_only
management.endpoints.web.exposure.include=gateway

Or application.yml

management:
endpoint:
gateway:
access: read_only
endpoints:
web:
exposure:
include: gateway

Open http://localhost:8072/actuator/gateway to view Gateway Actuator endpoints.

References

[1] Spring Microservices in Action, Second Edition

[2] Spring Cloud Gateway Documentation