我正在使用 spring
RestTemplate
与 xml
Web 服务后端进行通信,如下所示:
ResponseEntity<MainDTO> dto = restTemplate.postForObject(url, postData, MainDTO.class);
问题:后端可能会以
MainDTO
响应正常数据,或者以 ErrorDTO
响应失败。但两者都有HTTP 200
。
但我不知道哪个对象会先回来!不管怎样,
restTemplate
要求我之前通过class
类型。
那么,我怎样才能将 xml 解析为正常 bean 或错误 bean?
旁注:我对 Web 服务后端没有任何控制权。
正如您所想,问题在于后端应该返回带有 HTTP 错误代码的错误,这就是它们的用途。
但正如你所说,你无法控制后端,所以你能做的就是首先将其作为字符串获取
ResponseEntity<String> dto = restTemplate.postForObject(url, postData, String.class);
然后你可以尝试使用 Jackson 或 Gson 将字符串响应解析为
MainDTO
(无论你的项目中有什么,你应该这样做,因为我相信 Spring 的 RestTemplate 在内部使用它们中的任何一个)并使用 try/catch 和如果失败,那么你尝试用你的 ErrorDto
来解析它。
更新
哦,我刚读到这是一个
XML
服务,而不是 JSON
,上面的方法仍然有效,但是不要使用 Jackson
或 Gson
,你可以使用 SimpleXML
(http ://simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php#deserialize),它允许您以“简单”的方式反序列化 XML,您只需要使用描述的注释来注释您的模型在他们的教程和示例中。
这个 Spring 的示例 (http://spring.io/guides/gs/consuming-rest-xml-android/) 也可能提供有关如何使用
SimpleXML
的见解。
ResponseErrorHandler
,将错误响应转换为 RuntimeException
。
Http 消息到 POJO 的转换可以通过重新使用 RestTemplate#setMessageConverters
正在使用的 messageConverter 来完成。
这里是一个利用此的示例。
我有同样的问题,所以我有一个描述错误的抽象类。然后我的所有 Json 类都扩展了抽象错误类。因此,响应对象填充了实体数据和我可以轻松检查的错误。
我不是特别喜欢这个解决方案,但当我立即将 Json 对象转换为应用程序数据对象时,感觉还不错。
我尝试了Alfredo 的解决方案,但由于 Object.class 而出现异常:
Method threw 'org.springframework.web.client.HttpClientErrorException' exception.
如果您使用不同的类,它将被强制转换并且您将无法使用实例。
使用以下代码解决了我的问题:
String xml = restTemplate.getForObject(url, String.class, uriVariables);
JAXBContext jaxbContext = JAXBContext.newInstance();
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
StringSource xmlStr = new StringSource(xml);
Object o = jaxbUnmarshaller.unmarshal((Source) xmlStr);
if (o instanceof VonAZRAZRBestaetigungMeldung090098) {
// ...
}
我也遇到了同样的问题,我是这样解决的:
我创建了一个 Response 类,并在其中放置了两个响应对象。 我已经用
记下了所有三门课@XmlRootElement
@XmlAccessorType (XmlAccessType.FIELD)
ResponseEntity <Response> responseEntity = restTemplate.postForEntity (url, request, Response.class);
Object res = responseEntity.getBody ();
if (res! = null) {
if (res instanceof MainDTO) {
...
} else if (res instanceof ErrorDTO) {
...
}
}
希望有用!
在我的例子中,这不起作用,因为 ResponseBody 是由 OpenApi Feign 代码生成的 Map。但可以使用对象映射器将 Map 映射到相应的对象:
ResponseEntity<Object> registerResult = restTestRestTemplate.postForEntity("/register", registerRequest, Object.class);
Assertions.assertEquals(HttpStatus.NOT_ACCEPTABLE, registerResult.getStatusCode());
ObjectMapper objectMapper = new ObjectMapper();
InlineResponse406 inlineResponse406 = objectMapper.convertValue(registerResult.getBody(), InlineResponse406.class);
Assertions.assertNotNull(inlineResponse406);
这是一个测试类的代码,当然,对应其他响应代码也可以创建其他Object。
使用 实例
MyObject1 a=null;
MyObject2 b=null;
ResponseEntity<Object>response=template.exchange(builder.build().encode().toUri(),HttpMethod.GET,entity, Object.class);
if (response.getBody() instanceof MyObject1)
a= (MyObject1) response.getBody();
else if(response.getBody() instanceof MyObject2)
b= (MyObject2) response.getBody();