Spring云网关的全局异常处理
我正在使用SpringCloudGatewayGreenwich.SR1和SpringBoot2.1.5。我正在尝试为我的下游服务创建一个网关。网关的部分工作是为下游请求提供全局错误页。当下游服务返回HTTP 403响应时,我希望网关提供一个拟合错误页面 我目前正在使用这样的自定义过滤器Spring云网关的全局异常处理,spring,spring-webflux,spring-cloud-gateway,Spring,Spring Webflux,Spring Cloud Gateway,我正在使用SpringCloudGatewayGreenwich.SR1和SpringBoot2.1.5。我正在尝试为我的下游服务创建一个网关。网关的部分工作是为下游请求提供全局错误页。当下游服务返回HTTP 403响应时,我希望网关提供一个拟合错误页面 我目前正在使用这样的自定义过滤器 公共类禁止FilterFactory扩展AbstractGatewayFilterFactory{ @凌驾 公共字符串名称(){ 返回“禁止”; } @凌驾 应用公共网关筛选器(对象o){ return(exc
公共类禁止FilterFactory扩展AbstractGatewayFilterFactory{
@凌驾
公共字符串名称(){
返回“禁止”;
}
@凌驾
应用公共网关筛选器(对象o){
return(exchange,chain)->chain.filter(exchange)。然后(
单声道延迟(()->{
如果(!exchange.getResponse().isCommitted())&&
HttpStatus.FORBIDDEN.equals(exchange.getResponse().getStatusCode()){
返回Mono.error(新的ResponseStatusException(HttpStatus.FORBIDDEN));
}
返回Mono.empty();
}));
}
}
我还在src/main/resources/templates/error/
中设置了一个403.html
文件
问题是网关返回403响应,返回的是一个空正文,而不是html文件的内容。在调试期间,我可以看到DefaultErrorWebExceptionHandler
以Mono
的形式创建了正确的主体,但它从未写入实际响应
有没有其他方法可以让它工作?我通过使用定制的
服务器HttpResponseDecorator
解决了这个问题。代码的关键部分是使用方法覆盖writeWith,以提供自定义正文:
ServerHttpResponseDecorator responseDecorator = new ServerHttpResponseDecorator(exchange.getResponse()) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (shouldServeErrorPage(exchange)) {
exchange.getResponse().getHeaders().setContentLength(-1);
return errorWebExceptionHandler.handle(exchange, new ResponseStatusException(getHttpStatus(exchange)));
} else {
return getDelegate().writeWith(body);
}
}
@Override
public Mono<Void> writeAndFlushWith(
Publisher<? extends Publisher<? extends DataBuffer>> body) {
if (shouldServeErrorPage(exchange)) {
return writeWith(Flux.from(body).flatMapSequential(p -> p));
} else {
return getDelegate().writeAndFlushWith(body);
}
}
private boolean shouldServeErrorPage(ServerWebExchange exchange) {
HttpStatus statusCode = getHttpStatus(exchange);
return statusCode.is5xxServerError() || statusCode.is4xxClientError();
}
};
return chain.filter(exchange.mutate().response(responseDecorator).build());
ServerHttpResponseDecorator responseDecorator=new ServerHttpResponseDecorator(exchange.getResponse()){
@凌驾
public Mono writeWith(Publishermaybe)可能是因为其他内容已写入响应?客户端上的响应为空。此筛选器中返回Mono.error。您是在收到响应后执行此操作的,因此我的问题是。