Master Spring Cloud Gateway: Basics, Custom Filters, Nacos Integration & Dynamic Routing
This comprehensive guide explains why a gateway is essential in microservice architectures, outlines Spring Cloud Gateway's core features, walks through building a gateway from scratch, and demonstrates advanced topics such as custom predicates, filters, Nacos service discovery, dynamic routing, and global error handling.
Hello everyone, I'm Su San~
This article introduces an important role in microservices: the gateway. Since Alibaba's ecosystem lacks a gateway, we choose Spring Cloud Gateway as the "child".
Why do we need a gateway?
In monolithic architecture there is a single service for client calls, but microservices split a system into many services. Without a gateway, clients must record each service's address locally.
Problems without a gateway:
Clients must request multiple services, increasing code and configuration complexity.
Authentication becomes complex as each service needs its own.
Cross‑origin requests are harder to handle.
Basic functions of a gateway
A gateway is the portal for all microservices. Routing is the most basic function; additional functions include authentication, authorization, circuit breaking, rate limiting, logging, monitoring, etc.
Why choose Spring Cloud Gateway?
Earlier versions used Zuul, but Zuul's upgrade kept missing. Spring Cloud developed its own gateway to replace Zuul.
Spring Cloud Gateway is built on Spring Boot 2.x, Spring WebFlux, and Project Reactor, offering better compatibility and performance.
Key terms in Spring Cloud Gateway
Route : Basic building block consisting of ID, target URI, predicates, and filters.
Predicate : Similar to Java 8 Predicate, matches request attributes such as headers or parameters.
Filter : Modifies request or response before or after routing.
How to set up the gateway
Create a project cloud-gateway9023 and add the dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>Note: Remove spring-boot-starter-web to avoid startup errors.
What is a Predicate?
Predicate comes from Java 8's functional interface. It returns a boolean and can be combined with logical operators. Spring Cloud Gateway provides many built‑in predicates in the org.springframework.cloud.gateway.handler.predicate package.
What is a Filter?
Filters in Spring Cloud Gateway are similar to those in Spring MVC. They have two lifecycles:
PRE : Executed before routing (e.g., authentication, logging).
POST : Executed after routing (e.g., adding response headers, metrics).
Filters can be GatewayFilter (applied to specific routes) or GlobalFilter (applied to all routes).
GatewayFilter (local filter)
Example of adding a response header:
spring:
cloud:
gateway:
routes:
- id: gateway-provider_1
uri: http://localhost:9024
predicates:
- Path=/gateway/provider/**
filters:
- AddResponseHeader=X-Response-Foo,BarResulting response contains the header X-Response-Foo=Bar.
Note: Filter names only need the prefix; the full name is xxxGatewayFilterFactory.
Custom local filter example
Simulate an authorization check: if a request contains a token header or parameter, allow; otherwise return 401.
/**
* Name must be xxxGatewayFilterFactory
*/
@Component
@Slf4j
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {
private static final String AUTHORIZE_TOKEN = "token";
// constructor, shortcutFieldOrder, apply method omitted for brevity
@Data @AllArgsConstructor @NoArgsConstructor
public static class Config { private boolean enabled; }
}Configure the filter in the route:
spring:
cloud:
gateway:
routes:
- id: gateway-provider_1
uri: http://localhost:9024
predicates:
- Path=/gateway/provider/**
filters:
- AddResponseHeader=X-Response-Foo,Bar
- Authorize=trueRequests without token receive 401; with token succeed.
GlobalFilter (global filter)
Global filters apply to all routes without configuration. Example logs request path, remote IP, and response status:
@Component @Order(Integer.MIN_VALUE)
public class AccessLogGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().pathWithinApplication().value();
InetSocketAddress remote = request.getRemoteAddress();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
HttpStatus status = exchange.getResponse().getStatusCode();
log.info("Request path:{}, remote IP:{}, status:{}", path, remote, status);
}));
}
}Integrating a service registry (Nacos)
Hard‑coding URIs prevents IP changes and load balancing. Add Nacos discovery dependency and enable it in the main class.
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>Configure application.yml:
spring:
application:
name: cloud-gateway
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848Use lb://service-name as the URI to enable load balancing.
Dynamic routing with Nacos Config
Store gateway routes in Nacos Config Center. Add spring-cloud-starter-alibaba-nacos-config dependency and configure bootstrap.yml to point to Nacos.
spring:
application:
name: cloud-gateway
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yamlCreate a dataId cloud-gateway.yaml in Nacos with route definitions. Changes take effect without restarting the gateway.
Custom global error handling
When a downstream service is unavailable, Spring Cloud Gateway returns a default error page. Implement a global error handler by creating a class that implements ErrorWebExceptionHandler:
@Component @Order(-1) @RequiredArgsConstructor
public class GlobalErrorExceptionHandler implements ErrorWebExceptionHandler {
private final ObjectMapper objectMapper;
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
ServerHttpResponse response = exchange.getResponse();
if (response.isCommitted()) return Mono.error(ex);
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
if (ex instanceof ResponseStatusException) {
response.setStatusCode(((ResponseStatusException) ex).getStatus());
}
return response.writeWith(Mono.fromSupplier(() -> {
DataBufferFactory bufferFactory = response.bufferFactory();
try {
CommonResponse result = new CommonResponse("500", ex.getMessage(), null);
return bufferFactory.wrap(objectMapper.writeValueAsBytes(result));
} catch (JsonProcessingException e) {
return bufferFactory.wrap(new byte[0]);
}
}));
}
}Summary
Why a gateway is needed and its basic functions.
How to build a microservice gateway from scratch.
Concept of Predicate (assertion).
Concept of filters, built‑in filters, and how to create custom filters.
Integrating Nacos for service discovery and load balancing.
Using Nacos as a config center for dynamic routing.
Global error handling in Spring Cloud Gateway.
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.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
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.
