Spring Cloud Gateway: Concepts, Configuration, Routing, Filters, and CORS Handling
This article introduces Spring Cloud Gateway as a unified entry point for microservices, explains its core functions, compares it with Zuul, provides Maven and YAML configuration examples, details route definitions, filter types and ordering, shows how to implement custom filters, and demonstrates CORS solutions using both YAML and Java code.
1. Basic Concepts of Gateway
Spring Cloud Gateway is the unified entry point for all microservices.
1.1 Main Functions
Reverse proxy (request forwarding)
Routing and load balancing
Authentication and authorization
Rate limiting
1.2 Advantages over Zuul
Spring Cloud Gateway is built on Spring 5 WebFlux, offering reactive programming and superior performance compared to the servlet‑based, blocking implementation of Zuul.
Although Nginx can also serve as a gateway, it requires Lua scripts, has a higher learning cost, and is rarely used for this purpose; however, in pure performance terms, Nginx is the fastest.
1.3 Architecture Diagram
Microservices only accept requests from the gateway; direct access is rejected, which greatly protects services and enables request‑level rate limiting.
2. Configuring Gateway in Spring Boot
2.1 Maven Dependency
<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'><!--网关 起步依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现 起步依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</code>2.2 application.yml Configuration
<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>server:
port: 10086 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos 地址
gateway:
routes:
- id: user-service # 路由 id,唯一
uri: lb://userservice # 使用服务名 + 负载均衡
predicates:
- Path=/user/** # 路径匹配
- id: card-service
uri: lb://cardservice
predicates:
- Path=/card/**
</code>Note: The routes list can contain multiple entries; each entry starts with a dash.
Using lb://userservice lets the program resolve the actual instance via load balancing, avoiding hard‑coded URLs.
2.3 Route Configuration Details
Four main parts of a route:
Route ID (id)
Target URI (uri)
Predicates – rules that determine whether a request matches the route
Filters – processing applied to request or response
2.3.1 Route ID
The unique identifier of the route.
2.3.2 Route Target
The destination address; lb://service-name uses service‑name based load balancing, which is more maintainable than a fixed HTTP URL.
2.3.3 Predicates
Predicates are strings parsed by PredicateFactory classes. For example, Path=/user/** is handled by PathRoutePredicateFactory.
2.3.4 Filters
Spring Cloud Gateway provides 34 filter factories. Common ones include adding request headers, rate limiting, etc.
2.4 Example of Local (Route‑Specific) Filter
<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
filters:
- AddRequestHeader=token,test # 添加请求头
</code>This filter adds a request header token: test to all requests routed to userservice.
2.5 Example of Global (Default) Filter
<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
default-filters:
- AddRequestHeader=token,test # 添加请求头
</code>Filters under default-filters apply to all routes.
3. Custom Global Filter Implementation
When built‑in filter factories are insufficient, a Java class implementing GlobalFilter and Ordered can be created.
<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>@Component
public class GateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. Get query parameters
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
String userName = params.getFirst("userName");
if ("root".equals(userName)) {
// allow
return chain.filter(exchange);
}
// deny
exchange.getResponse().setStatusCode(500);
return exchange.getResponse().setComplete();
}
@Override
public int getOrder() {
return -1; // higher priority
}
}
</code>The Order value determines execution precedence; larger numbers mean lower priority.
4. Filter Execution Order
Three kinds of filters exist:
Default filters (default-filters)
Route‑specific filters (filters)
Global Java filters (GlobalFilter)
The execution sequence is: default filters → route‑specific filters → global filters.
5. Cross‑Origin (CORS) Issues
5.1 Concept
Cross‑origin occurs when the request origin (protocol, domain, or port) differs from the server’s. Browsers block such AJAX requests unless the server explicitly allows them.
5.2 Common Solution – CORS
Configure Spring Cloud Gateway to return appropriate CORS headers.
5.3 CORS Configuration via application.yml
<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>spring:
cloud:
gateway:
globalcors:
add-to-simple-url-handler-mapping: true
corsConfigurations:
'[/**]':
allowedOrigins:
- "http://localhost:8090"
allowedMethods:
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*"
allowCredentials: true
maxAge: 360000
</code>5.4 CORS Configuration via Java Bean
<code style='padding: 15px 16px 16px; color: rgb(171, 178, 191); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; font-size: 12px'>@Configuration
public class CorsConfig {
private static final String MAX_AGE = "18000L";
@Bean
public WebFilter corsFilter() {
return (ServerWebExchange ctx, WebFilterChain chain) -> {
ServerHttpRequest request = ctx.getRequest();
if (!CorsUtils.isCorsRequest(request)) {
return chain.filter(ctx);
}
HttpHeaders requestHeaders = request.getHeaders();
ServerHttpResponse response = ctx.getResponse();
HttpHeaders headers = response.getHeaders();
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());
headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());
HttpMethod method = requestHeaders.getAccessControlRequestMethod();
if (method != null) {
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, method.name());
}
headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");
headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
return chain.filter(ctx);
};
}
}
</code>Both approaches ensure that browsers can successfully perform cross‑origin AJAX calls.
6. Additional Notes
The article also includes promotional sections and QR‑code images, which are not part of the technical content.
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.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
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.
