Master Spring Cloud Gateway in 3 Minutes – Complete Service Gateway Guide
This article introduces Spring Cloud Gateway as a high‑performance replacement for Zuul, explains its core components (Route, Predicate, Filter) and request flow, provides step‑by‑step setup of a gateway project, demonstrates route configuration, custom GlobalFilter and GatewayFilter implementations, and validates the behavior with example requests.
Background
Spring Cloud Gateway is built on Spring 5, Spring Boot 2 and Project Reactor to provide a simple yet efficient API routing solution for microservice architectures. It replaces the first‑generation Zuul component, offering better performance and richer features.
Workflow
The gateway consists of three core components:
Route : defined by an ID, a target URI, a set of predicates and a set of filters. When the predicates evaluate to true, the request is matched to the route.
Predicate : a Java 8 Predicate<ServerWebExchange> that matches request attributes such as headers or parameters.
Filter : intercepts and modifies request parameters or response data.
The request processing steps are:
Match the incoming request against predicates to obtain a Route.
Pass the request through the filter chain for pre‑processing (e.g., header modification).
Forward the request to the target URI via the ProxyFilter.
Execute post‑processing filters (e.g., response header changes).
Return the final response to the client.
Quick Start
1. Create a Spring Boot project named gateway-server and add the following dependencies in pom.xml:
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring-boot.version>2.2.5.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
<!-- Spring Cloud Gateway starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>2. Add the main application class:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}3. Create application.yaml with route definitions:
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: baidu
uri: https://www.baidu.com
predicates:
- Path=/baidu
filters:
- StripPrefix=1
- id: myRoute
uri: http://127.0.0.1:9001
predicates:
- Path=/myRoute/**
filters:
- StripPrefix=14. Implement a simple downstream service (e.g., a Spring Boot app listening on port 9001) with a controller:
@RestController
public class HelloController {
@GetMapping("/hello")
public String index() {
return "hello world!";
}
}Route Rules
The routes section defines each route's id, target uri, matching predicates (commonly Path or Host) and filters. Multiple predicates can be combined to satisfy complex matching requirements.
Custom Filters
Spring Cloud Gateway supports two filter types:
GlobalFilter : loaded at startup and applied to all routes.
GatewayFilter : configured per route via spring.cloud.gateway.routes[].filters.
GlobalFilter example :
@Component
public class PreGlobalFilter implements GlobalFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(PreGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
LOGGER.info("Global Pre Filter executed");
return chain.filter(exchange);
}
}
@Component
public class PostGlobalFilter implements GlobalFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(PostGlobalFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
LOGGER.info("Global Post Filter executed");
}));
}
}GatewayFilter example (token authentication) :
@Component
public class TokenGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenGatewayFilterFactory.Config> {
private static final Logger LOGGER = LoggerFactory.getLogger(TokenGatewayFilterFactory.class);
public TokenGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
Map<String, Integer> tokenMap = new HashMap<>();
tokenMap.put("hahaha", 1);
return (exchange, chain) -> {
LOGGER.info("TokenGatewayFilterFactory pre Filter executed");
ServerHttpRequest request = exchange.getRequest();
String requestPath = request.getPath().toString();
if ("/dc".equals(requestPath)) {
return chain.filter(exchange);
}
ServerHttpResponse response = exchange.getResponse();
String token = request.getHeaders().getFirst(config.getTokenHeaderName());
Integer userId = tokenMap.get(token);
if (userId == null) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
DataBuffer buffer = response.bufferFactory().wrap("Invalid token, authentication failed!".getBytes());
return response.writeWith(Flux.just(buffer));
}
ServerHttpRequest newRequest = request.mutate()
.header(config.getUserIdHeaderName(), String.valueOf(userId))
.build();
return chain.filter(exchange.mutate().request(newRequest).build());
};
}
public static class Config {
private String tokenHeaderName;
private String userIdHeaderName;
public String getTokenHeaderName() { return tokenHeaderName; }
public void setTokenHeaderName(String tokenHeaderName) { this.tokenHeaderName = tokenHeaderName; }
public String getUserIdHeaderName() { return userIdHeaderName; }
public void setUserIdHeaderName(String userIdHeaderName) { this.userIdHeaderName = userIdHeaderName; }
}
}Register the filter in application.yaml:
spring:
cloud:
gateway:
routes:
- id: myRoute
uri: http://127.0.0.1:9001
predicates:
- Path=/myRoute/**
filters:
- StripPrefix=1
- name: Token
args:
tokenHeaderName: token
userIdHeaderName: userIdTesting
Start both the gateway and the downstream service, then access: http://127.0.0.1:8080/baidu → forwards to https://www.baidu.com. http://127.0.0.1:8080/myRoute/hello → forwards to http://127.0.0.1:9001/hello and returns "hello world!".
When the token header is missing, the custom filter returns HTTP 401 with the message "Invalid token, authentication failed!".
When a valid token is supplied, the request is enriched with a userId header and proceeds normally.
Conclusion
Spring Cloud Gateway provides a powerful, flexible API gateway suitable for modern microservice systems, successfully superseding Zuul. The article covered its architecture, basic configuration, route definition, and how to extend it with custom global and per‑route filters.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Pan Zhi's Tech Notes
Sharing frontline internet R&D technology, dedicated to premium original content.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
