以下为每个核心工具类提供可直接运行的代码示例,覆盖上下文操作、路由处理、请求响应修改、过滤器开发、异常处理等场景,所有示例基于 Spring Cloud Gateway 3.1.x(主流稳定版本)。
一、上下文操作工具类
1. ServerWebExchangeUtils(核心)
场景:获取路由信息、修改转发 URL、标记原始请求 URL
java
运行
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.cloud.gateway.route.Route;
import java.net.URI;
// 网关过滤器中使用
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1. 获取匹配的路由(简化写法)
Route route = ServerWebExchangeUtils.getRoute(exchange);
if (route == null) {
return chain.filter(exchange); // 无匹配路由,直接放行
}
System.out.println("匹配的路由ID:" + route.getId());
System.out.println("路由目标URI:" + route.getUri());
// 2. 记录原始请求URL(重写URL必备,避免丢失原地址)
ServerWebExchangeUtils.addOriginalRequestUrl(exchange, exchange.getRequest().getURI());
// 3. 修改网关转发的目标URL(同机房收敛场景:转发到上海机房实例)
URI targetUri = URI.create("http://10.0.0.100:8080/order");
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, targetUri);
// 4. 判断是否匹配到路由
boolean isMatched = ServerWebExchangeUtils.isRouteMatched(exchange);
System.out.println("路由匹配状态:" + isMatched);
return chain.filter(exchange);
}
2. AttributeAccessorSupport(扩展示例)
场景:自定义上下文属性存取(过滤器间传递数据)
java
运行
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.ServerWebExchangeDecorator;
import org.springframework.core.AttributeAccessorSupport;
// 自定义Exchange(继承扩展AttributeAccessorSupport)
public class CustomServerWebExchange extends ServerWebExchangeDecorator {
private final AttributeAccessorSupport attributes = new AttributeAccessorSupport();
public CustomServerWebExchange(ServerWebExchange delegate) {
super(delegate);
}
// 重写属性存取方法
@Override
public <T> T getAttribute(String name) {
T attr = super.getAttribute(name);
return attr != null ? attr : (T) attributes.getAttribute(name);
}
@Override
public void setAttribute(String name, Object value) {
super.setAttribute(name, value);
attributes.setAttribute(name, value);
}
// 自定义属性:跨过滤器传递灰度标记
public void setGrayFlag(boolean isGray) {
setAttribute("gray_flag", isGray);
}
public Boolean getGrayFlag() {
return getAttribute("gray_flag");
}
}
// 使用示例
CustomServerWebExchange customExchange = new CustomServerWebExchange(exchange);
customExchange.setGrayFlag(true);
System.out.println("灰度标记:" + customExchange.getGrayFlag());
二、路由匹配 / 构建工具类
1. RoutePredicateFactory(自定义断言)
场景:自定义机房匹配断言(仅允许上海机房请求通过)
java
运行
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.GatewayPredicate;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
@Component
public class IdcRoutePredicateFactory extends AbstractRoutePredicateFactory<IdcRoutePredicateFactory.Config> {
// 配置参数名
public static final String IDC_KEY = "idc";
public IdcRoutePredicateFactory() {
super(Config.class);
}
// 配置参数列表(供yml配置使用)
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList(IDC_KEY);
}
// 断言逻辑:请求头X-Idc匹配配置值则通过
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return exchange -> {
String requestIdc = exchange.getRequest().getHeaders().getFirst("X-Idc");
return config.getIdc().equals(requestIdc);
};
}
// 配置类(接收yml中的参数)
public static class Config {
private String idc;
public String getIdc() {
return idc;
}
public void setIdc(String idc) {
this.idc = idc;
}
}
}
// yml配置使用该断言
/*
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
predicates:
- Path=/order/**
- Idc=shanghai # 自定义机房断言
*/
exchange->等同于下面实现代码,lambda特性
等价于手动实现Predicate接口
return new Predicate<ServerWebExchange>() {
// 这里的test方法是Predicate接口要求必须实现的!
@Override
public boolean test(ServerWebExchange exchange) { // 定义exchange参数
String requestIdc = exchange.getRequest().getHeaders().getFirst("X-Idc");
return config.getIdc().equals(requestIdc);
}
};
2. RouteLocatorBuilder(编程式构建路由)
场景:动态构建多机房路由规则
java
运行
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 DynamicRouteConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 上海机房订单服务路由
.route("order-shanghai", r -> r
.header("X-Idc", "shanghai") // 机房头匹配
.and().path("/order/**") // 路径匹配
.uri("lb://order-service-shanghai")) // 上海机房服务
// 北京机房订单服务路由
.route("order-beijing", r -> r
.header("X-Idc", "beijing")
.and().path("/order/**")
.uri("lb://order-service-beijing"))
// 默认路由(无机房头)
.route("order-default", r -> r
.path("/order/**")
.uri("lb://order-service-default"))
.build();
}
}
3. RouteDefinitionWriter(动态添加路由)
场景:运行时新增路由(无需重启网关)
java
运行
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.cloud.gateway.route.builder.PredicateDefinitionBuilder;
import org.springframework.cloud.gateway.route.builder.UriDefinitionBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
public class DynamicRouteController {
private final RouteDefinitionWriter routeDefinitionWriter;
public DynamicRouteController(RouteDefinitionWriter routeDefinitionWriter) {
this.routeDefinitionWriter = routeDefinitionWriter;
}
// 接口:POST /add-route
@PostMapping("/add-route")
public ResponseEntity<String> addRoute(@RequestBody RouteDefinition route) {
// 示例:手动构建路由(也可接收JSON参数)
RouteDefinition newRoute = new RouteDefinition();
newRoute.setId("dynamic-pay-route");
// 设置路径断言
newRoute.getPredicates().add(
PredicateDefinitionBuilder.path("/pay/**").build()
);
// 设置转发URI
newRoute.setUri(UriDefinitionBuilder.uri("lb://pay-service").build());
// 写入路由(响应式操作)
Mono<Void> result = routeDefinitionWriter.save(Mono.just(newRoute));
result.subscribe(
success -> {},
error -> ResponseEntity.badRequest().body("添加路由失败:" + error.getMessage())
);
return ResponseEntity.ok("路由添加成功");
}
}
三、请求 / 响应处理工具类
1. ServerHttpRequestDecorator(修改请求)
场景:重写请求路径、添加自定义请求头
java
运行
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import reactor.core.publisher.Mono;
public class ModifyRequestFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 原始请求
ServerHttpRequest originalRequest = exchange.getRequest();
// 装饰请求:添加机房头 + 重写路径
ServerHttpRequest modifiedRequest = originalRequest.mutate()
.header("X-Idc", "shanghai") // 添加机房标识
.header("X-Request-Id", java.util.UUID.randomUUID().toString()) // 请求ID
.path("/v2" + originalRequest.getPath()) // 路径重写:/order → /v2/order
.build();
// 替换exchange中的请求
ServerWebExchange modifiedExchange = exchange.mutate()
.request(modifiedRequest)
.build();
return chain.filter(modifiedExchange);
}
}
2. ServerHttpResponseDecorator(修改响应)
场景:统一包装响应体、修改响应状态码
java
运行
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
public class ModifyResponseFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
// 装饰响应:统一包装JSON返回体
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Flux<? extends DataBuffer> body) {
// 仅处理JSON响应
if (originalResponse.getHeaders().getContentType() == MediaType.APPLICATION_JSON) {
// 合并响应体为单个Buffer
return super.writeWith(body.collectList().flatMap(dataBuffers -> {
// 读取原始响应内容
StringBuilder responseContent = new StringBuilder();
for (DataBuffer buffer : dataBuffers) {
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
responseContent.append(new String(bytes, StandardCharsets.UTF_8));
// 释放缓冲区(避免内存泄漏)
org.springframework.core.io.buffer.DataBufferUtils.release(buffer);
}
// 包装响应体
String wrappedResponse = String.format(
"{\"code\":200,\"msg\":\"success\",\"data\":%s}",
responseContent.toString()
);
// 构建新的响应Buffer
DataBuffer buffer = bufferFactory.wrap(wrappedResponse.getBytes(StandardCharsets.UTF_8));
// 设置响应头
originalResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON);
originalResponse.setStatusCode(HttpStatus.OK);
return Mono.just(buffer);
}));
}
// 非JSON响应直接放行
return super.writeWith(body);
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
}
3. DataBufferUtils(处理请求体)
场景:读取完整 POST 请求体、释放缓冲区
java
运行
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
public Mono<Void> readRequestBody(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 仅处理POST请求
if (request.getMethod().equals(org.springframework.http.HttpMethod.POST)) {
// 读取请求体(Flux<DataBuffer> → 完整字符串)
Mono<String> requestBodyMono = DataBufferUtils.join(request.getBody())
.map(buffer -> {
byte[] bytes = new byte[buffer.readableByteCount()];
buffer.read(bytes);
// 必须释放缓冲区!
DataBufferUtils.release(buffer);
return new String(bytes, StandardCharsets.UTF_8);
});
return requestBodyMono.flatMap(requestBody -> {
System.out.println("完整请求体:" + requestBody);
// 业务处理:如解析JSON、验签等
return chain.filter(exchange);
});
}
return chain.filter(exchange);
}
4. HttpHeadersUtils(提取真实 IP)
场景:处理反向代理 / CDN 场景,提取客户端真实 IP
java
运行
import org.springframework.cloud.gateway.support.HttpHeadersUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.server.ServerWebExchange;
import java.net.InetSocketAddress;
public String getRealClientIp(ServerWebExchange exchange) {
HttpHeaders headers = exchange.getRequest().getHeaders();
InetSocketAddress remoteAddress = exchange.getRequest().getRemoteAddress();
// 提取真实IP(优先X-Forwarded-For → X-Real-IP → 远程地址)
String realIp = HttpHeadersUtils.extractClientIp(headers, remoteAddress);
// 判断Content-Type是否为JSON
boolean isJson = HttpHeadersUtils.isContentType(headers, org.springframework.http.MediaType.APPLICATION_JSON);
System.out.println("客户端真实IP:" + realIp);
System.out.println("是否JSON请求:" + isJson);
return realIp;
}
四、过滤器执行工具类
1. GatewayFilterFactory(自定义过滤器)
场景:自定义机房标记过滤器(给请求添加机房头)
java
运行
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
@Component
public class IdcTagGatewayFilterFactory extends AbstractGatewayFilterFactory<IdcTagGatewayFilterFactory.Config> {
// 配置参数名
public static final String IDC_KEY = "idc";
public IdcTagGatewayFilterFactory() {
super(Config.class);
}
// 配置参数顺序(供yml使用)
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList(IDC_KEY);
}
// 过滤器逻辑:添加机房标记请求头
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
// 从配置中获取机房值,添加到请求头
var modifiedRequest = exchange.getRequest().mutate()
.header("X-Idc-Tag", config.getIdc())
.build();
return chain.filter(exchange.mutate().request(modifiedRequest).build());
};
}
// 配置类
public static class Config {
private String idc;
public String getIdc() {
return idc;
}
public void setIdc(String idc) {
this.idc = idc;
}
}
}
// yml配置使用
/*
spring:
cloud:
gateway:
routes:
- id: order-service
uri: lb://order-service
filters:
- IdcTag=shanghai # 自定义过滤器,参数为上海机房
*/
2. GlobalFilter(全局过滤器)
场景:全局跨机房调用监控
java
运行
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class IdcMonitorGlobalFilter implements GlobalFilter, Ordered {
// 本地机房标识(可从配置中心读取)
private static final String LOCAL_IDC = "shanghai";
@Override
public Mono<Void> filter(ServerWebExchange exchange, org.springframework.cloud.gateway.filter.GatewayFilterChain chain) {
// 前置处理:记录请求开始时间
long startTime = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 后置处理:计算耗时 + 判断是否跨机房
long cost = System.currentTimeMillis() - startTime;
String targetIdc = exchange.getRequest().getHeaders().getFirst("X-Idc-Tag");
if (targetIdc != null && !LOCAL_IDC.equals(targetIdc)) {
// 跨机房调用,记录日志/告警
System.out.printf("跨机房调用:本地=%s, 目标=%s, 耗时=%dms%n",
LOCAL_IDC, targetIdc, cost);
}
}));
}
// 执行顺序:最后执行(LOWEST_PRECEDENCE)
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
五、异常处理工具类
1. ErrorWebExceptionHandler(自定义异常响应)
场景:统一网关异常返回格式(JSON)
java
运行
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.HashMap;
import java.util.Map;
@Component
@Order(-1) // 优先级高于默认异常处理器
public class CustomErrorWebExceptionHandler implements ErrorWebExceptionHandler {
private final ErrorAttributes errorAttributes;
private final ServerCodecConfigurer serverCodecConfigurer;
private final ApplicationContext applicationContext;
// 构造器注入依赖
public CustomErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ServerCodecConfigurer serverCodecConfigurer,
ApplicationContext applicationContext) {
this.errorAttributes = errorAttributes;
this.serverCodecConfigurer = serverCodecConfigurer;
this.applicationContext = applicationContext;
}
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
// 构建统一异常响应体
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 500);
errorResponse.put("msg", "网关处理异常:" + ex.getMessage());
errorResponse.put("timestamp", System.currentTimeMillis());
errorResponse.put("path", exchange.getRequest().getPath());
// 构建JSON响应
return RouterFunctions.route(RequestPredicates.all(), request ->
ServerResponse.status(500)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorResponse))
).route(exchange)
.flatMap(handler -> handler.handle(exchange))
.then(Mono.defer(() -> Mono.error(ex)));
}
}
2. GatewayException(自定义异常)
场景:自定义路由异常并抛出
java
运行
import org.springframework.cloud.gateway.support.GatewayException;
import org.springframework.web.server.ServerWebExchange;
// 自定义异常
public class IdcRouteNotFoundException extends GatewayException {
public IdcRouteNotFoundException(String message) {
super(message);
}
}
// 使用示例
public Mono<Void> checkIdcRoute(ServerWebExchange exchange, GatewayFilterChain chain) {
String idc = exchange.getRequest().getHeaders().getFirst("X-Idc");
if (idc == null || idc.isEmpty()) {
// 抛出自定义异常(会被CustomErrorWebExceptionHandler捕获)
return Mono.error(new IdcRouteNotFoundException("未传递机房标识X-Idc"));
}
return chain.filter(exchange);
}
六、其他核心工具类
FilteringWebHandler(扩展过滤器链)
场景:自定义过滤器链执行逻辑
java
运行
import org.springframework.cloud.gateway.handler.FilteringWebHandler;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.WebHandler;
import java.util.List;
@Configuration
public class CustomWebHandlerConfig {
// 自定义FilteringWebHandler,添加额外全局过滤器
@Bean
public WebHandler customWebHandler(List<GlobalFilter> globalFilters) {
// 添加自定义全局过滤器到链首
GlobalFilter firstFilter = (exchange, chain) -> {
System.out.println("自定义过滤器链:第一个执行");
return chain.filter(exchange);
};
globalFilters.add(0, firstFilter);
// 创建自定义FilteringWebHandler
FilteringWebHandler handler = new FilteringWebHandler(globalFilters);
return handler;
}
}
关键说明
- 依赖准备:确保项目引入核心依赖
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.1.5</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
- 响应式编程约束 :所有操作避免使用
block(),遵循 Reactor 异步规则; - 资源释放 :操作
DataBuffer后必须调用DataBufferUtils.release(); - 配置生效 :自定义
RoutePredicateFactory/GatewayFilterFactory需添加@Component,且类名后缀必须为RoutePredicateFactory/GatewayFilterFactory。