Overview
A microservices gateway is a system that provides centralized authentication, security control, unified logging, monitoring, and rate limiting by exposing a single entry point.
Spring Cloud Gateway Workflow
-
A client sends a request to Spring Cloud Gateway. The request is first extracted and assembled into a gateway context by
HttpWebHandlerAdapter, which is then passed toDispatcherHandler. -
DispatcherHandleris the main request dispatcher. It routes requests to the appropriate handler, such asRoutePredicateHandlerMapping(the route predicate handler mapper). -
The route predicate handler mapper finds the matching route and returns the corresponding
FilteringWebHandler. -
FilteringWebHandlerbuilds and executes a filter chain. It then forwards the request to the backend proxy service. After the service processes the request, the response is returned to the Gateway client.
In the filter chain, filters are divided into Pre and Post types. All Pre filters execute before request is forwarded to the backend. After the backend service finishes processing, Post filters execute before the response is sent back.
Key concepts: Route, Predicate, Filter.
Gateway route configuration can be static (in application.yml) or dynamic (in code). Dynamic routing is more flexible. Below are examples of both.
Dynamic Path-Based Routing Configuration
Java Code Configuration
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("hailtaxi-driver", r -> r.path("/driver/**").uri("lb://hailtaxi-driver"))
.route("hailtaxi-order", r -> r.path("/order/**").uri("lb://hailtaxi-order"))
.route("hailtaxi-pay", r -> r.path("/pay/**").uri("lb://hailtaxi-pay"))
.build();
}
Application.yml Configuration
spring:
cloud:
gateway:
routes:
- id: hailtaxi-driver
uri: lb://hailtaxi-driver
predicates:
- Path=/driver/**
- id: hailtaxi-order
uri: lb://hailtaxi-order
predicates:
- Path=/order/**
- id: hailtaxi-pay
uri: lb://hailtaxi-pay
predicates:
- Path=/pay/**
Configuration parameters:
routes: Route definitions.id: Unique identifier for the route.uri: Target service address. Can belb://IP:portorlb://${spring.application.name}.predicates: Conditions for route matching (returns boolean). For example,Path=/driver/**matches all requests starting with/driver.filters: Filters applied to matching requests.StripPrefix=1removes the first path segment before forwarding.
Example: Using Cookie Predicate
The following configuration allows requests only if they contain a Cookie named username with value itheima.
gateway:
routes:
- id: hailtaxi-driver
uri: lb://hailtaxi-driver
predicates:
- Path=/driver/**
- Cookie=username,itheima
Example: Using Method Predicate
The following configuration matches only GET and POST requests.
gateway:
routes:
- id: hailtaxi-driver
uri: lb://hailtaxi-driver
predicates:
- Path=/driver/**
- Method=GET,POST
Filters
Classification
- Default filters: Pre-built filters provided by the framework.
- Global default filters: Apply to all routes.
- Local default filters: Apply to specific routes.
- Custom filters: Implemented by developers.
- Global filters: Apply to all routes.
- Local filters: Apply only to the configured route.
Common Default Filters
| Filter Name | Description | Class | Parent Class |
|---|---|---|---|
| AddRequestHeader | Adds a header to the matching request | AddRequestHeaderGatewayFilterFactory | AbstractNameValueGatewayFilterFactory |
| AddRequestParameters | Adds parameters to the matching request | AddRequestHeaderGatewayFilterFactory | AbstractNameValueGatewayFilterFactory |
| AddResponseHeader | Adds a header to the response from the gateway | AddResponseHeaderGatewayFilterFactory | AbstractNameValueGatewayFilterFactory |
| StripPrefix | Removes a prefix from the request path | StripPrefixGatewayFilterFactory | AbstractGatewayFilterFactory |
Add Response Header Example
Adds a custom response header X-Response-Default-MyName: itheima to all routes.
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-MyName,itheima
Strip Prefix Example
StripPrefix=1 removes the first path segment (/api) from the request URI.
gateway:
routes:
- id: hailtaxi-driver
uri: lb://hailtaxi-driver
predicates:
- Path=/api/driver/**
filters:
- StripPrefix=1
Behavior:
| Configuration | Request URL | Forwarded URL |
|---|---|---|
| StripPrefix=1 | http://localhost:8001/api/driver/info/2 |
http://localhost:18081/driver/info/2 |
| StripPrefix=2 | http://localhost:8001/api/suri/driver/info/2 |
http://localhost:18081/driver/info/2 |
Add Prefix Example
Uses the PrefixPath filter to add a prefix before forwarding.
gateway:
routes:
- id: hailtaxi-driver
uri: lb://hailtaxi-driver
predicates:
- Path=/**
filters:
- PrefixPath=/driver
| Configuration | Request URL | Forwarded URL |
|---|---|---|
PrefixPath=/driver |
http://localhost:8001/info/2 |
http://localhost:18081/driver/info/2 |
Custom Filters
1. Implementing the GatewayFilter Interface
This creates a local filter that applies only to specific routes. The filter must implement GatewayFilter and Ordered.
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
public class CustomPayFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("CustomPayFilter PRE filter executed");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
System.out.println("CustomPayFilter POST filter executed");
}));
}
@Override
public int getOrder() {
return 0;
}
}
Usage in RouteLocator: (Comment out any route configuration in application.yml)
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route("hailtaxi-driver", r -> r.path("/api/driver/**")
.and().cookie("username", "itheima")
.and().header("token", "123456")
.filters(f -> f.filter(new CustomPayFilter())
.addResponseHeader("X-Response-Default-MyName", "itheima")
.addRequestHeader("myheader", "1234567")
.stripPrefix(1))
.uri("lb://hailtaxi-driver"))
.route("hailtaxi-order", r -> r.path("/order/**").uri("lb://hailtaxi-order"))
.route("hailtaxi-pay", r -> r.path("/pay/**").uri("lb://hailtaxi-pay"))
.build();
}
2. Extending GatewayFilterFactory
This approach allows you to create a configurable filter that can be used in both code and YAML configurations.
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class PayMethodGatewayFilterFactory extends AbstractGatewayFilterFactory<PayMethodGatewayFilterFactory.Config> {
public PayMethodGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
String payMethod = config.getPayMethod();
String message = config.getMessage();
log.info("PayMethodGatewayFilterFactory configuration: {} - {}", payMethod, message);
exchange.getRequest().mutate().header("paymethod", payMethod);
return chain.filter(exchange);
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("payMethod", "message");
}
@Override
public ShortcutType shortcutType() {
return ShortcutType.DEFAULT;
}
@Data
public static class Config {
private String payMethod;
private String message;
}
}
YAML configuration:
gateway:
routes:
- id: hailtaxi-driver
uri: lb://hailtaxi-driver
predicates:
- Path=/driver/**
- Cookie=username,itheima
- Header=token,^(?!\d+$)[\da-zA-Z]+$
- Method=GET,POST
filters:
- PayMethod=alipay,business integration
Cross-Origin (CORS) Configurasion
Global CORS Configuration
gateway:
globalcors:
corsConfigurations:
'[/**]':
allowedOrigins: "*"
allowedMethods:
- GET
- POST
- PUT
Programmatic CORS Configuration
Create a CorsWebFilter bean:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addExposedHeader("Authorization");
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
Token Bucket Algorithm (Leaky Bucket / Rate Limiting)

Flow:
- Every request must obtain an available token before being processed.
- Tokens are added to the bucket at a fixed rate, based on the configured limit.
- The bucket has a maximum capacity. If the bucket is full, new tokens are discarded or refused.
- A request must acquire a token from the bucket before proceeding with business logic. After processing, the token is removed.
- The bucket has a minimum threshold. When the token count reaches this minimum, tokens are not removed after processing, ensuring a minimum rate is always available.