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

允我心安 提交于 2020-01-07 04:38:10

问题


I'd like to find how to influence how Spring automatically marshals Java objects to XML when sending a POST request via RestTemplate. Particularly, how to configure what is in the XML headers (encoding, DOCTYPE, ...).

There are plenty of questions closely touching the topic (Include DOCTYPE for Spring Jaxb2Marshaller, How to add DOCTYPE and xml processing instructions when marshalling with JAXB?, how to add DOCTYPE in jaxb marshaller, How to declare doctype ,xml version and encoding in XML file using DOM parser in java?) but none of them seems to help here.

I am aware that I may marshal the object to XML string first and then send the XML string. However, I'd like to use the automatic marshaling as it seems more elegant and proper.

I have a class like

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

The code sending the HTTP POST request is like:

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);

When I intercept what is sent, it is something like this:

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>

and what I want to receive is

POST ...

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

Question: How can I customize the marshaling without completely avoiding the automagic behavior of Spring RestTemplate? I want to change the encoding, remove the standalone attribute (where does it come from?) and add the <!DOCTYPE> element.


回答1:


You can replace the XML converter that RestTemplate uses with a customized one:

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;
    }
}

Wrap the whole thing in a method annotated with @Bean @Qualified, and use that to autowire the RestTemplate wherever you need it, if you have many places to inject it to



来源:https://stackoverflow.com/questions/47836310/how-to-customize-automatic-marshaling-in-spring-resttemplate-to-produce-modify-x

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!