当HTTP请求的返回状态为401时,如何解析Java中的响应正文

我正在使用Spring RestTemplate和Jackson 的RESTful JSON API 。在某些情况下,我们可能会收到Status

401带有自定义JSON主体的(未经授权)响应,该响应由API制造商定义,如下所示:

{

"code": 123,

"message": "Reason for the error"

}

我们需要解析主体,并code在业务逻辑中使用该属性。

这是我们需要解析为的错误响应Java对象:

public class CustomError {

@JsonProperty

private Integer code;

@JsonProperty

private String message;

public Integer getCode() {

return code;

}

public String getMessage() {

return message;

}

}

还有一个自定义错误处理程序可以做到这一点:

public class CustomErrorHandler extends DefaultResponseErrorHandler {

private RestTemplate restTemplate;

private ObjectMapper objectMapper;

private MappingJacksonHttpMessageConverter messageConverter;

@Override

public boolean hasError(ClientHttpResponse response) throws IOException {

return super.hasError(response);

}

@Override

public void handleError(final ClientHttpResponse response) throws IOException {

try {

CustomError error =

(CustomError) messageConverter.read(CustomError.class, response);

throw new CustomErrorIOException(error, error.getMessage());

} catch (Exception e) {

// parsing failed, resort to default behavior

super.handleError(response);

}

}

}

错误处理程序失败,并HttpMessageNotReadableException在try块中显示:

“无法读取JSON:由于服务器身份验证,在流模式下无法重试”

这就是我发送请求的方式:

restTemplate.postForObject(url, pojoInstance, responseClass);

如果使用普通的旧客户端客户端程序(如Postman)执行相同的请求,则将收到预期的JSON响应。因此,我认为问题可能出在Spring的ClientHttpResponse实现中,在401状态下,它不允许访问响应主体。

是否确实可以解析响应主体?

根据我的调查,RestTemplate该类使用ClientHttpResponse,进而创建sun.net.www.protocol.http.HttpURLConnection提供输入流的。在这里,输入流被忽略,并IOException抛出:

在流模式下,由于服务器身份验证而无法重试

因此,HttpURLConnection的实现导致了此问题。

可以避免这个问题吗?也许我们应该使用一种替代实现,在出现错误状态代码的情况下,它不忽略响应主体?您能推荐任何其他选择吗?

回答:

尝试以下方法而无需自定义处理程序。这个想法是从HttpStatusCodeException获取作为字符串的响应,然后可以将其转换为对象。对于转换,我使用了Jackson的ObjectMapper:

        try {

restTemplate.postForObject(url, pojoInstance, responseClass);

} catch (HttpStatusCodeException e) {

if (e.getStatusCode() == HttpStatus.UNAUTHORIZED) {

String responseString = e.getResponseBodyAsString();

ObjectMapper mapper = new ObjectMapper();

CustomError result = mapper.readValue(responseString,

CustomError.class);

}

}

使用另一家工厂也可能会有所帮助,因为默认工厂中存在一个与您的问题相关的错误(请参见下面的评论):

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

以上是 当HTTP请求的返回状态为401时,如何解析Java中的响应正文 的全部内容, 来源链接: utcz.com/qa/434708.html

回到顶部