我正在尝试使用自定义过滤器通过Spring Cloud Gateway创建网关代理路由器。以阻塞和强制性的方式覆盖属性时,一切都会按预期进行。
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("https://" + newTargetURLHost + )
使用以下方法获取字符串变量newTargetURLHost:
newTarget = serviceReturnsMono.getServerMapping(id).block().getHost();
我对Webflux还是陌生的,但是上面的代码对我来说已经是代码的味道了。进一步阅读后,这不是使用反应式时的最佳方法。我试图以一种更具功能/反应性的方式进行重写,但未能使反应性流发出所需的值。
Mono.just(serviceReturnsMono.getServerMapping(id))
.flatMap(flat -> flat)
.subscribeOn(Schedulers.immediate())
.map(server -> exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("https://" + server.getHost() ))
.subscribe();
执行以上代码时,交换属性不会发生变异。
我也尝试了以下失败的尝试:
serverMappingMono
.map(serverMapping -> exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("https://" + serverMapping.getHost() ))
.subscribe();
作为测试,当我如下修改代码以进行故障排除时,以下代码确实会发出一个硬编码的字符串,并且交换属性被更改。
.map(server -> exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("https://" + "testHostName" ))
.subscribe();
任何想法或指示都将不胜感激。
更新:过滤器代码如下:
private ReturnsMonoServerMappingService returnsMonoServerMappingService;
@Override
public int getOrder() {
return 10001;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
final String id = exchange.getRequest().getHeaders().getFirst("reference");
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
Mono<ServerMapping> serverMapping = returnsMonoServerMappingService.getServerMapping(id);
serverMapping
.map(server -> exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, URI.create("https://" + server.getHost() )))
.subscribe();
}));
}
}
托马斯的更新解决方案:
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
final String id = exchange.getRequest()
.getHeaders()
.getFirst("reference");
return returnsMonoServerMappingService.getServerMapping(id)
.doOnSuccess(serverMapping -> {
exchange.getAttributes()
.put(GATEWAY_REQUEST_URL_ATTR, URI.create("https://" + server.getHost()
}).then(chain.filter(exchange));
}
我忽略的缺失部分是“ doOnSuccess”,因为returnMonoServerMappingService已经返回了单声道。然后按“ then”将交换链接,以委托给链中的下一个过滤器。
答案 0 :(得分:2)
我正在手机上写这个,所以不能测试它,也不能从内存中写出来,但是我认为应该是这样的。或者至少您了解要点。
我们首先提取ID。然后我们查找服务器映射,如果一切顺利,我们将其作为属性,然后继续过滤链。
从不订阅应用程序,主叫客户端就是订阅者。永远不要阻塞反应性应用程序。
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
final String id = exchange.getRequest()
.getHeaders()
.getFirst("reference");
return returnsMonoServerMappingService.getServerMapping(id)
.doOnSuccess(serverMapping -> {
exchange.getAttributes()
.put(GATEWAY_REQUEST_URL_ATTR, URI.create("https://" + server.getHost()
}).then(chain.filter(exchange));
}