问题
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