在 FeignClient 中处理 HTTP 重定向

Mad*_*vap 5 spring netflix-feign

FeignClient 是一个非常漂亮的工具,但不幸的是,如果您需要做一些与 Spring 之神预期稍有不同的事情,那么您就陷入了痛苦的世界。

当前案例:我与外部第三方 REST 服务合作,该服务具有关于 REST 的有趣概念。特别是,如果您向他们发送正确的 JSON,他们会在正文中返回 HTTP 302 和 JSON。

不用说,FeignClient 真的非常不喜欢这种恶作剧。我的界面:

@FeignClient(value = "someClient", configuration = SomeClientDecoderConfiguration.class)
public interface SomeClient {
    @RequestMapping(method = RequestMethod.POST, path = "${someClient.path}",
    produces = MediaType.APPLICATION_JSON_VALUE)
    JsonOrderCreateResponse orderCreate(JsonOrderCreateRequest request, @RequestHeader("Authorization") String authHeader);
}
Run Code Online (Sandbox Code Playgroud)

我已经有了自定义配置和错误解码器,但这些仅适用于 HTTP 4xx 和 5xx。如果系统遇到302,结果是这样的:

http://pastebin.com/raw/cGKWc4yg

我如何才能防止这种情况并强制 FeignClient 像处理 200 一样处理 302?

Mad*_*vap 4

虽然没有办法强制 FeignClient 在没有疯狂的解决方法的情况下正常处理超过 2xx 的任何内容,但有一种方法可以以最小的麻烦来处理它。请注意,您将需要最新版本!我必须在 POM 中输入:

<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-core</artifactId>
    <version>1.5.9</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

那么,该怎么做呢?

在任何方法的假客户端实现中,您都需要返回响应。就是这样。

如果您返回响应,框架将以特殊方式运行 - 如果状态超过 2xx,它不会抛出任何异常,也不会像某些......有天赋的......孩子一样尝试多次重试。换句话说,没有什么恶作剧。耶!

例子:

import feign.Response;

@RequestMapping(method = RequestMethod.POST, path = "${someClient.path}")
Response doThisOrThat(JsonSomeRequest someJson, @RequestHeader("Authorization") String authHeader);
Run Code Online (Sandbox Code Playgroud)

当然,您需要实际手动处理响应(前面提到的最小麻烦):

private JsonSomeResponse resolveResponse(JsonSomeRequest jsonRequest, String accessToken)
{
    Response response = someClient.doThisOrThat(jsonRequest, "Bearer " + accessToken);
    JsonSomeResponse jsonResponse = null;
    String resultBody = "";
    try {
        try (BufferedReader buffer = new BufferedReader(new InputStreamReader(response.body().asInputStream()))) {
            resultBody = buffer.lines().collect(Collectors.joining("\n"));
        }
        jsonResponse = objectMapper.readValue(resultBody, JsonSomeResponse.class);
    } catch (IOException ex) {
        throw new RuntimeException("Failed to process response body.", ex);
    }
    // just an example of using exception
    if (response.status() >= 400) thrown new OmgWeAllAreDeadException();
    return jsonResponse;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以做任何你想做的事情,检查response.status()以抛出你自己的异常,以与200相同的方式处理任何状态代码(如302)的响应(哦,太恐怖了!)等。