Cloud Native 17 min read

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.

Pan Zhi's Tech Notes
Pan Zhi's Tech Notes
Pan Zhi's Tech Notes
Master Spring Cloud Gateway in 3 Minutes – Complete Service Gateway Guide

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=1

4. 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: userId

Testing

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavamicroservicesAPI Gatewayspring-bootSpring Cloud GatewayCustom Filter
Pan Zhi's Tech Notes
Written by

Pan Zhi's Tech Notes

Sharing frontline internet R&D technology, dedicated to premium original content.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.