我正在使用伪端客户连接到下游服务。
我需要一个要求,当下游服务端点之一返回400(部分成功方案(时,我们的服务需要将其转换为200个成功的响应值。
我正在寻找一种最好的方法。
我们使用错误解码器来处理错误,上面的转换仅适用于一个端点,而不是所有下游端点,并注意到Decode((方法应返回异常。
您需要创建一个自定义的Client
来足够尽早拦截Response
以更改响应状态,而不是调用ErrorDecoder
。最简单的方法是在现有客户端上创建包装器,并创建具有200
状态的新Response
。这是使用feign的ApacheHttpClient
:
public class ClientWrapper extends ApacheHttpClient {
private ApacheHttpClient delegate;
public ClientWrapper(ApacheHttpClient client) {
this.client = client;
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
/* execute the request on the delegate */
Response response = this.client.execute(request, options);
/* check the response code and change */
if (response.status() == 400) {
response = Response.builder(response).status(200).build();
}
return response;
}
}
该自定义客户端可用于您需要的任何假装客户端。
另一种做法是在错误解码器上抛出自定义异常,然后将此自定义转换为Spring Global Exception Handler(使用@RestControllerRadvice(
public class CustomErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
if (response.status() == 400 && response.request().url().contains("/wanttocovert400to200/clientendpoints") {
ResponseData responseData;
ObjectMapper mapper = new ObjectMapper();
try {
responseData = mapper.readValue(response.body().asInputStream(), ResponseData.class);
} catch (Exception e) {
responseData = new ResponseData();
}
return new PartialSuccessException(responseData);
}
return FeignException.errorStatus(methodKey, response);
}}
和以下的例外处理程序
@RestControllerAdvice
public class GlobalControllerExceptionHandler {
@ResponseStatus(HttpStatus.OK)
@ExceptionHandler(PartialSuccessException.class)
public ResponseData handlePartialSuccessException(
PartialSuccessException ex) {
return ex.getResponseData();
}
}
更改微服务响应:
public class CustomFeignClient extends Client.Default {
public CustomFeignClient(
final SSLSocketFactory sslContextFactory, final HostnameVerifier
hostnameVerifier) {
super(sslContextFactory, hostnameVerifier);
}
@Override
public Response execute(final Request request, final Request.Options
options) throws IOException {
Response response = super.execute(request, options);
if (HttpStatus.SC_OK != response.status()) {
response =
Response.builder()
.status(HttpStatus.SC_OK)
.body(InputStream.nullInputStream(), 0)
.headers(response.headers())
.request(response.request())
.build();
}
return response;
}
}
添加假句client:
@Configuration
public class FeignClientConfig {
@Bean
public Client client() {
return new CustomFeignClient(null, null);
}
}