Backend Development 8 min read

Build a Minimal Spring Cloud Gateway with Controller‑Based Routing

This article explains how to use Spring Cloud Gateway 3.1.5 to create a lightweight API gateway by configuring routes in YAML and implementing routing logic directly in a Spring MVC or WebFlux controller with ProxyExchange, covering features, code examples, and dynamic path mapping.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Build a Minimal Spring Cloud Gateway with Controller‑Based Routing

Spring Cloud Gateway 3.1.5 is a reactive, high‑performance API gateway built on Spring Framework 5, Spring Boot 2 and Project Reactor, providing routing, load‑balancing, security, rate limiting, circuit breaking and seamless integration with other Spring Cloud components.

Reactive non‑blocking model for high throughput and low latency.

Multiple routing predicates (path, query, header, host, etc.).

Global and custom filters for request/response manipulation.

Dynamic route and filter configuration at runtime.

Integration with Spring Cloud Discovery for service‑registry‑based routing.

Integration with Spring Cloud Security for authentication and authorization.

Integration with Spring Cloud Circuit Breaker for fault tolerance.

Integration with Spring Cloud Stream for event‑driven architectures.

Extensible with other Spring Cloud components such as Netflix, Consul, Zookeeper.

Typical gateway configuration is done in application.yml (or application.properties ) and requires only a few lines to enable the gateway and define routes.

<code>spring:
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          # Enable service‑name based route discovery
          enabled: true
          lowerCaseServiceId: true
      # Default filters applied to all routes
      default-filters:
        - StripPrefix=1
      routes:
        - id: alibaba
          # Load‑balance via service discovery
          uri: lb://cloudAlibaba
          predicates:
            - name: Path
              args:
                a: /api-1/**
        - id: ooxx
          uri: http://www.baidu.com
          predicates:
            - Path=/api-x/**
        - id: xxoo
          uri: http://localhost:8082
          predicates:
            - Path=/api-x/**
            - Host=localhost:9099
            - Weight=G1, 5
</code>

For ultra‑simple scenarios you can avoid a separate gateway service and implement routing directly in a controller using the ProxyExchange utility. The following example shows a Spring MVC controller that forwards a request to a downstream service, adds a custom header, and returns a static response.

<code>@RestController
@RequestMapping("/proxy/api")
public class GatewayController {

  @GetMapping("")
  public Object order(@RequestHeader("token") String token,
                      Integer id,
                      ProxyExchange<Map<String, Object>> exchange) {
    Map<String, Object> body = new HashMap<>();
    body.put("id", id);
    body.put("token", token);
    return exchange.uri("http://localhost:9000/business/index")
                   .header("key", "123123")
                   .body(body)
                   .post(result -> ResponseEntity.ok("success"));
  }
}
</code>

If you prefer a reactive stack, the same idea works with WebFlux. The controller below injects the target URI from configuration and forwards the request using ProxyExchange in a non‑blocking way.

<code>@RestController
@RequestMapping("/proxy/api")
public class GatewayController {

  @Value("${remote.api}")
  private URI api;

  @GetMapping("")
  public Mono<ResponseEntity<?>> proxy(ProxyExchange<Map<String, Object>> proxy) throws Exception {
    return proxy.uri(api.toString() + "/creat/user").get();
  }
}
</code>

When you need to forward any path under a fixed prefix, you can use a wildcard mapping and let ProxyExchange forward the remaining part of the URI to the downstream service.

<code>@RestController
@RequestMapping("/proxy/api")
public class GatewayController {

  @Value("${remote.api}")
  private URI api;

  @GetMapping("/**")
  public Object common(ProxyExchange<Map<String, Object>> exchange) {
    String path = exchange.path("/proxy/api/");
    return exchange.uri(api.toString() + path).get();
  }
}
</code>

All gateway handler methods can leverage the full capabilities of Spring MVC and WebFlux, allowing you to inject request headers, query parameters, and apply annotations for request validation. The header() method on ProxyExchange lets you add or modify response headers, and you can provide a mapper function to transform the downstream ResponseEntity before returning it.

By default, sensitive headers such as Cookie and Authorization , as well as proxy‑related headers (e.g., x-forwarded-* ), are not forwarded to downstream services, enhancing security.

Done!!

microservicesbackend developmentAPI gatewaySpring Cloud Gatewayproxyexchange
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login 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.