给出REST服务调用
http://acme.com/app/widget/123
返回:
<widget>
<id>123</id>
<name>Foo</name>
<manufacturer>Acme</manufacturer>
</widget>
此客户端代码有效:
RestTemplate restTemplate = new RestTemplate();
XStreamMarshaller xStreamMarshaller = new XStreamMarshaller();
xStreamMarshaller.getXStream().processAnnotations(
new Class[] {
Widget.class,
ErrorMessage.class
});
HttpMessageConverter<?> marshallingConverter = new MarshallingHttpMessageConverter(
xStreamMarshaller, xStreamMarshaller);
List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>();
converters.add(marshallingConverter);
restTemplate.setMessageConverters(converters);
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 123L);
但是,调用http://acme.com/app/widget/456会返回:
<error>
<message>Widget 456 does not exist</message>
<timestamp>Wed, 12 Mar 2014 10:34:37 GMT</timestamp>
</error>
但是此客户端代码抛出异常:
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
org.springframework.web.client.HttpClientErrorException: 404 Not Found
我试过了:
try {
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
}
catch (HttpClientErrorException e) {
ErrorMessage errorMessage = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", ErrorMessage.class, 456L);
// etc...
}
第二次调用只是抛出了另一个HttpClientErrorException,而且它感觉没有两次调用该服务。
有没有办法调用服务一次,并在成功时将响应解析为Widget,而在找不到时则解析ErrorMessage?
答案 0 :(得分:9)
根据我的评论,我检查了HttpClientErrorException
JavaDoc,它同时支持设置/获取statusText
以及responseBody
。但是它们是可选的,RestTemplate可能不会填充它们 - 你需要尝试类似的东西:
try {
Widget w = restTemplate.getForObject(
"http://acme.com/app/widget/{id}", Widget.class, 456L);
}
catch (HttpClientErrorException e) {
String responseBody = e.getResponseBodyAsString();
String statusText = e.getStatusText();
// log or process either of these...
// you'll probably have to unmarshall the XML manually (only 2 fields so easy)
}
如果它们都是空/ null,那么您可能必须扩展所涉及的RestTemplate类并自己填充这些字段和/或在Spring网站上引发Jira问题。
答案 1 :(得分:5)
如果您愿意,也可以从错误响应正文中创建对象:
ObjectMapper om = new ObjectMapper();
String errorResponse = ex.getResponseBodyAsString();
MyClass obj = om.readValue(errorResponse, MyClass.class);
答案 2 :(得分:2)
由于您已经捕获了HttpClientErrorException对象,它应该允许您轻松提取有关错误的有用信息并将其传递给调用者。
例如:
try{
<call to rest endpoint using RestTemplate>
} catch(HttpClientErrorException e){
HttpStatus statusCode = e.getStatusCode();
String body = e.getResponseBodyAsString();
}
IMO如果需要进一步将错误消息body
反序列化为某个相关对象,可以在catch语句范围之外的某处处理。
答案 3 :(得分:-1)
我也在Spring库中发现了一个令人不安的更改。您曾经能够抛出ResponseStatusException并将其传递给HttpStatus代码和自定义消息,然后捕获HttpClientErrorException并只需打印getMessage()即可查看自定义错误。这不再起作用。为了让我打印自定义错误,我必须将ResponseBody捕获为HttpClientErrorException上的字符串getResponseBodyAsString。然后,我需要将其解析为一个字符串,进行一些漂亮的hokey子字符串操作。这样做会从ResponseBody中剥离信息,并给出我的服务器发送的消息。执行此操作的代码如下:
String message = hce.getResponseBodyAsString();
int start, end;
start = message.lastIndexOf(":", message.lastIndexOf(",")-1) + 2;
end = message.lastIndexOf(",") -1;
message = message.substring(start, end);
System.out.println(message);
当我使用ARC或Postman进行测试时,在我将server.error.include-message = always添加到服务器上的application.properties文件之后,它们可以显示正确的消息。我不确定他们使用哪种方法来提取消息,但是很高兴知道。