Win*_*ter 6 jaxb spring-boot jackson-dataformat-xml spring-webflux spring-webclient
我的 Spring Boot 应用程序想要使用 Webclient 发出 http 请求(XML 请求正文)并接收 XML 响应。因此,我使用 jackson-dataformat-xml 创建了另一个 Spring Boot 应用程序,并创建了一个端点来接收和返回 XML,如下所示。
spring-boot-version=2.2.5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
@PostMapping(value = "/api",
consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_XML_VALUE)
public ResponseEntity<MyXmlResponse> trip(@RequestBody MyXmlRequest request) throws Exception {
MyXmlResponse response = new MyXmlResponse();
response.setStatus("SUCCESS");
response.setTripID(request.getTripID());
return ResponseEntity.ok().body(response);
}
Run Code Online (Sandbox Code Playgroud)
它工作完美,显然不需要 JaxB 注释,因为我使用 jackson-dataformat-xml。此外,请求 XML 可以不区分大小写。
现在,在我的第一个应用程序中,我想通过 Web 客户端使用此 API。我读到 Spring webflux 还不支持 Jackson-dataformat-xml 。因此我必须使用 Jaxb 注释来注释我的类。
spring-boot-version=2.2.5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
webClient.post()
.uri(URI.create("url-to-api-endpoint"))
.body(Mono.just(myXmlRequest), MyXmlRequest.class)
.exchange()
.doOnSuccess(response -> {
HttpStatus statusCode = response.statusCode();
log.info("Status code of external system request {}", statusCode);
})
.doOnError(onError -> {
log.error("Error on connecting to external system {}", onError.getMessage());
})
.flatMap(response -> response.bodyToMono(MyXmlResponse.class))
.subscribe(this::handleResponse);
Run Code Online (Sandbox Code Playgroud)
上面的代码抛出异常如下
org.springframework.webreactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlRequest
at org.springframework.web.reactive.function.BodyInserters.unsupportedError(BodyInserters.java:391)
Run Code Online (Sandbox Code Playgroud)
我通过使用 XmlRootElement 进行注释解决了这个问题,如下所示
@Getter @Setter @NoArgsConstructor @ToString
@XmlRootElement()
public class MyXmlRequest {
private String attribute1;
}
Run Code Online (Sandbox Code Playgroud)
在下一次尝试时,我收到另一个错误,如下所示
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlResponse
Caused by: org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/xml' not supported for bodyType=com.example.MyXmlResponse
Run Code Online (Sandbox Code Playgroud)
这可以通过使用 XmlRootElement 注释 MyXmlResponse 来解决,如下所示
@Getter @Setter @NoArgsConstructor @ToString
@XmlRootElement()
public class MyXmlResponse {
private String attr1;
private String attr2;
}
Run Code Online (Sandbox Code Playgroud)
这次我得到了如下的 unmarshallException
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.core.codec.DecodingException: Could not unmarshal XML to class com.example.MyXmlResponse; nested exception is javax.xml.bind.UnmarshalException
- with linked exception:
[com.sun.istack.internal.SAXParseException2; lineNumber: 1; columnNumber: 15; unexpected element (uri:"", local:"MyXmlResponse"). Expected elements are <{}myXmlResponse>]
Caused by: org.springframework.core.codec.DecodingException: Could not unmarshal XML to class com.example.MyXmlResponse; nested exception is javax.xml.bind.UnmarshalException
- with linked exception:
Run Code Online (Sandbox Code Playgroud)
我使用传递给注释的附加属性来修复它,如下所示。
@XmlRootElement(name = "MyXmlResponse", namespace = "")
public class MyXmlResponse {
Run Code Online (Sandbox Code Playgroud)
将来,我的 XML 结构将变得极其复杂。我想知道我的做法是否正确。
| 归档时间: |
|
| 查看次数: |
7067 次 |
| 最近记录: |