Ste*_*ann 6 spring-boot spring-cloud-feign feign
我有一个 API,它将以自定义响应消息的形式返回失败,同时仍然发送 Http 200 响应。例子:
Status: 200
Body: {
"code":404,
"message":"Data not found",
"data":{},
"status":"ERROR"
}
Run Code Online (Sandbox Code Playgroud)
我当前的 ErrorDecoder 实现:
public class ApiFeignErrorDecoder implements ErrorDecoder {
private final Gson gson;
public ApiFeignErrorDecoder(Gson gson) {
this.gson = gson;
}
@Override
public Exception decode(String methodKey, Response response) {
try {
ApiResponse apiResponse = gson.fromJson(response.body().asReader(), BaseApiResponse.class);
ResponseStatus status = apiResponse.getStatus();
switch (status) {
case SUCCESS:
return null;
case FAIL:
return new Exception("Failure message recorded");
case ERROR:
return new Exception("Error message recorded");
default:
return new Exception("No suitable status found.");
}
} catch (IOException e) {
e.printStackTrace();
return new ErrorDecoder.Default().decode(methodKey, response);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是 Feign/Spring 仅当 HttpStatus > 300 时才会切换到 ErrorDecoder。错误解码器的 JavaDocs 也描述了此限制:
“Response.status() 不在 2xx 范围内的错误处理响应被归类为错误,由 ErrorDecoder 处理。也就是说,某些 RPC api 即使在 200 状态下也会返回 Response.body() 中定义的错误。例如,在 DynECT api 中,作业仍在运行的情况会返回 200 状态,并以 json 编码。当发生此类情况时,您应该引发特定于应用程序的异常(可能是可重试的)。
我现在的问题是我到底可以实现什么/如何实现这些,或者是否有一种方法可以扩展 ErrorDecoder 以便我能够处理这些错误消息。我认为我应该能够将它们放入解码器中,甚至实现/覆盖 HttpClient,但我不确定正确/最好的方法是什么。
像SpringDecoderErrorDecoder一样,您可以使用它编写自定义逻辑来处理成功响应。
private class ResponseDecoder extends SpringDecoder {
public ResponseDecoder(ObjectFactory<HttpMessageConverters> messageConverters) {
super(messageConverters);
}
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
try {
ApiResponse apiResponse = gson.fromJson(response.body().asReader(), BaseApiResponse.class);
ResponseStatus status = apiResponse.getStatus();
switch (status) {
case SUCCESS:
return null;
case FAIL:
throw new FeignException(FAIL, "Failure message recorded");
case ERROR:
throw new FeignException(ERROR, "Error message recorded");
default:
throw new FeignException(YOUR_DEFAULT_ERROR_CODE, "No suitable status found.");
}
} catch (IOException e) {
e.printStackTrace();
return null; // return accordingly to your use-case
}
}
}
Run Code Online (Sandbox Code Playgroud)
假客户端接口:
@FeignClient(value = "foo", configuration = FooClientConfig.class)
public interface FooClient {
//Your mappings
}
Run Code Online (Sandbox Code Playgroud)
Feign 客户端自定义配置:
@Configuration
public class FooClientConfig {
@Bean
public Decoder feignDecoder() {
// if you're using gson, add gson converter here instead
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(customObjectMapper());
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
return new ResponseEntityDecoder(new ResponseDecoder(objectFactory));
}
public ObjectMapper customObjectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
//Customize as much as you want
return objectMapper;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15738 次 |
| 最近记录: |