如何将 Spring RestTemplate 中的自动编组自定义为 produce/modify XML headers(编码,DOCTYPE)

How to customize automatic marshaling in Spring RestTemplate to produce/modify XML headers (encoding, DOCTYPE)

我想了解如何影响 Spring 自动 封送 Java object 到 XML 的方式通过 RestTemplate 发送 POST 请求。特别是,如何配置 XML headers (encoding, DOCTYPE, ...).

中的内容

有很多问题与主题密切相关 (Include DOCTYPE for Spring Jaxb2Marshaller, How to add DOCTYPE and xml processing instructions when marshalling with JAXB?, , ),但其中 none 似乎对这里有所帮助。

我知道我可以先将 object 编组为 XML 字符串,然后再发送 XML 字符串。但是,我想使用自动编组,因为它看起来更优雅和适当。

我有一个class喜欢

@XmlRootElement(name = "MyRequest")
public class MyRequest {
    @XmlAttribute(required = true)
    String field1;
    @XmlAttribute(required = true)
    String field2;
    ...
}

发送 HTTP POST 请求的代码如下:

final MyRequest requestBody = new MyRequest("VALUE1", "VALUE2");

final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_XML, MediaType.ALL));
final HttpEntity<MyRequest> requestHttpEntity = new HttpEntity<>(requestBody, headers);

return restTemplate.postForEntity(url, requestHttpEntity, MyResponse.class);

当我拦截发送的内容时,它是这样的:

POST /webservice HTTP/1.1
Accept: application/xml, */*
Content-Type: application/xml
Host: example.com:8080
Content-Length: ...

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MyRequest field1="VALUE1" field2="VALUE2">
</MyRequest>

我想收到的是

POST ...

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE MyRequest SYSTEM "MyRequest.dtd">
<MyRequest field1="VALUE1" field2="VALUE2">
</MyRequest>

问题:如何在不完全避免 Spring RestTemplate 的自动行为的情况下自定义封送处理? 我想更改 encoding,删除standalone 属性(它来自哪里?)并添加 <!DOCTYPE> 元素。

您可以将 RestTemplate 使用的 XML 转换器替换为自定义转换器:

RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
for (int i = 0; i != converters.size(); i++) {
    if (converters.get(i) instanceof Jaxb2RootElementHttpMessageConverter) {
        Jaxb2RootElementHttpMessageConverter xmlConverter = new Jaxb2RootElementHttpMessageConverter(){
            @Override
            protected void customizeMarshaller(Marshaller marshaller) {
                marshaller.setProperty( "com.sun.xml.internal.bind.xmlHeaders", "<!DOCTYPE MyRequest SYSTEM \"MyRequest.dtd\">");
                // add other customizations
            }
        };
        converters.set(i, xmlConverter);
        break;
    }
}

将整个事情包装在一个用@Bean @Qualified 注释的方法中,并使用它在你需要的任何地方自动装配 RestTemplate,如果你有很多地方可以将它注入