如何使用 RestTemplate 实现多种响应类型?

问题描述 投票:0回答:7

我正在使用 spring

RestTemplate
xml
Web 服务后端进行通信,如下所示:

ResponseEntity<MainDTO> dto = restTemplate.postForObject(url, postData, MainDTO.class);

问题:后端可能会以

MainDTO
响应正常数据,或者以
ErrorDTO
响应失败。但两者都有
HTTP 200

但我不知道哪个对象会先回来!不管怎样,

restTemplate
要求我之前通过
class
类型。

那么,我怎样才能将 xml 解析为正常 bean 或错误 bean?

旁注:我对 Web 服务后端没有任何控制权。

java spring spring-rest
7个回答
6
投票

正如您所想,问题在于后端应该返回带有 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
的见解。


3
投票

您可以实现自定义

ResponseErrorHandler
,将错误响应转换为
RuntimeException
。 Http 消息到 POJO 的转换可以通过重新使用
RestTemplate#setMessageConverters
正在使用的 messageConverter 来完成。

这里是一个利用此的示例。


0
投票

我有同样的问题,所以我有一个描述错误的抽象类。然后我的所有 Json 类都扩展了抽象错误类。因此,响应对象填充了实体数据和我可以轻松检查的错误。

我不是特别喜欢这个解决方案,但当我立即将 Json 对象转换为应用程序数据对象时,感觉还不错。


0
投票

我尝试了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) {
    // ...
}

0
投票

我也遇到了同样的问题,我是这样解决的:

我创建了一个 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) {
        ...
    }
}

希望有用!


0
投票

在我的例子中,这不起作用,因为 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。


-3
投票

使用 实例

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();
© www.soinside.com 2019 - 2024. All rights reserved.