Spring Cloud Gateway:如何创建PRE/POST类型过滤器?
Hi there! Since you’re familiar with Zuul’s filter model, adapting to Spring Cloud Gateway will feel intuitive—let’s walk through how to implement PRE and POST filters, along with examples that align with your existing knowledge.
Key Difference from Zuul
In Zuul, you’d extend ZuulFilter and specify a filterType (pre/post/route). In Spring Cloud Gateway, filters are categorized into two main types:
- Global Filters: Apply to all routes automatically.
- Gateway Filters: Apply to specific routes (you can bind them to your route definitions, just like your
/getroute example).
Both can handle PRE or POST logic—let’s cover examples for each scenario.
Implementing a PRE Filter
PRE filters run before the request is routed to the target service. Common use cases include adding request headers, validating tokens, or modifying request parameters.
Example 1: Global PRE Filter (Applies to All Routes)
Implement GlobalFilter and Ordered (to set execution order, similar to Zuul’s filterOrder):
import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class PreGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, org.springframework.cloud.gateway.filter.GatewayFilterChain chain) { // PRE logic: executes before routing ServerHttpRequest request = exchange.getRequest(); System.out.println("PRE Filter: Processing request to " + request.getPath()); // Modify the request (e.g., add a custom header) ServerHttpRequest modifiedRequest = request.mutate() .header("X-Custom-Pre-Header", "Pre-Processed") .build(); // Pass the modified request to the next filter in the chain return chain.filter(exchange.mutate().request(modifiedRequest).build()); } @Override public int getOrder() { // Lower number = runs earlier (matches Zuul's filterOrder behavior) return -100; } }
Example 2: Route-Specific PRE Filter
If you want the filter to apply only to specific routes (like your /get route), define a GatewayFilter and bind it directly to your route:
import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GatewayConfig { @Bean public RouteLocator myRoutes(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/get") // Add route-specific PRE filter .filter((exchange, chain) -> { ServerHttpRequest modifiedRequest = exchange.getRequest().mutate() .header("X-Route-Specific-Pre", "Only-For-Get-Route") .build(); return chain.filter(exchange.mutate().request(modifiedRequest).build()); }) .addRequestHeader("X-SpringOne", "Awesome") .uri("http://httpbin.org:80")) .build(); } }
Implementing a POST Filter
POST filters run after the target service responds, before sending the response back to the client. Common use cases include modifying response headers, logging response times, or transforming response bodies.
Example 1: Global POST Filter
import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class PostGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, org.springframework.cloud.gateway.filter.GatewayFilterChain chain) { // First run the full filter chain (PRE + routing), then execute POST logic return chain.filter(exchange).then(Mono.fromRunnable(() -> { ServerHttpResponse response = exchange.getResponse(); System.out.println("POST Filter: Processing response with status " + response.getStatusCode()); // Modify response headers here response.getHeaders().add("X-Custom-Post-Header", "Post-Processed"); })); } @Override public int getOrder() { // Higher number = runs later (POST filters typically use high order values) return 100; } }
Example 2: Route-Specific POST Filter
Bind a POST filter directly to your /get route:
import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GatewayConfig { @Bean public RouteLocator myRoutes(RouteLocatorBuilder builder) { return builder.routes() .route(r -> r.path("/get") .addRequestHeader("X-SpringOne", "Awesome") // Add route-specific POST filter .filter((exchange, chain) -> { return chain.filter(exchange).then(Mono.fromRunnable(() -> { exchange.getResponse().getHeaders().add("X-Route-Specific-Post", "Only-For-Get-Response"); })); }) .uri("http://httpbin.org:80")) .build(); } }
Pro Tips for Zuul Migrators
- Filter Order: Use the
Orderedinterface to control execution order—lower numbers run earlier (ideal for PRE filters that need to execute first), while higher numbers run later (perfect for POST filters that run after routing). - Reactive Programming: Spring Cloud Gateway is built on Reactor, so all filters use
Mono/Flux. Start with simple examples like the ones above if you’re new to reactive code. - Built-in Filters: Gateway has many ready-to-use filters (like
AddRequestHeader,AddResponseHeader) that you can leverage instead of writing custom ones—your existingaddRequestHeadercall is a great example!
Let me know if you need clarification on any part of this!
内容的提问来源于stack exchange,提问作者rm12345

