我的假客户给出了纯文本/文本响应。如何更改为application/java? 我无法将 json 响应转换为 pojo。我认为这是因为 API 返回 Content-type: plain/text 而不是 application/json 的 JSON。如何将响应标头更改为 application/json 而不是 plaint/text?
客户端.feign
@FeignClient(value = "${app.api.name}", url = "${app.api.url}")
public interface MozambiqueheApi {
@GetMapping("/bridge?" + "auth=" + "${app.api.token}" + "&player={playerName}" + "&platform={playerPlatform}")
@Headers("Content-Type: application/json")
ResponseEntity<TestPojo> getInfoByPlayer(@PathVariable String playerName, @PathVariable Platforms playerPlatform);
控制器.主控制器
@RestController
public class MainController {
private Feign feign;
public MainController() {
this.feign= Feign.builder()
.requestInterceptor(new HeaderTestRequestInterceptor())
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.contract(new SpringMvcContract())
.target(Feign.class, "https://api.test.re");
}
@GetMapping(value = "/")
public ResponseEntity<TestPojo> getMain() {
return feign.getInfoByPlayer("name", Platforms.PC);
}
}
modifier.headertestrequest拦截器
public class HeaderTestRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("Content-Type", "application/json");
}
}
API 的 Json 响应
{
"global": {
"name": "name",
"uid": 1234546897956,
"avatar": "",
"platform": "PC",
"level": 23,
"toNextLevelPercent": 62,
"internalUpdateCount": 22,
"bans": {
"isActive": false,
"remainingSeconds": 0,
"last_banReason": "NONE"
}
}
}
模型.testpojo
public class TestPojo {
public static class Global {
private String name;
public Global() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private Global global;
public TestPojo() {
}
public Global getGlobal() {
return global;
}
public void setGlobal(Global global) {
this.global = global;
}
}
我遇到同样的问题已经快两年了。由于 feign.ResponseInterceptor 中的 Javadoc 告诉我们
可以配置零个或一个响应拦截器以用于以下目的 作为验证或修改响应标头
但是传入 ResponseInterceptor 的 feign.Response#headers 是 UnmodifyingMap
@Override
public Object aroundDecode(InvocationContext invocationContext) throws IOException {
Response source = invocationContext.response();
var headers = new HashMap<>(source.headers());
//do what u want with headers
Response fixedResponse = Response.builder()
.headers(headers)
.body(source.body())
.build();
return invocationContext.decoder().decode(fixedResponse, invocationContext.returnType());
}
但最大的缺点是原始 InvocableContext#proceed 中需要重复的 try/catch 代码:
public Object proceed() {
try {
return decoder.decode(response, returnType);
} catch (final FeignException e) {
throw e;
} catch (final RuntimeException e) {
throw new DecodeException(response.status(), e.getMessage(), response.request(), e);
} catch (IOException e) {
throw errorReading(response.request(), response, e);
}
}
顺便说一句,我选择了第一个。