You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何转义JAXB生成的XML字符串双引号并解决RestTemplate提交报错

问题:RestTemplate POST XML时触发JAXB解析错误

问题场景

我需要构建XML并通过RestTemplate的POST请求提交,实现代码如下:

final RestTemplate restTemplate1 = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_XML));
messageConverters.add(converter);
restTemplate1.setMessageConverters(messageConverters);

HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("okmAdmin", "admin");
headers.setContentType(MediaType.APPLICATION_XML);

JAXBContext context = null;
context = JAXBContext.newInstance(Folder.class);
Marshaller mar = null;
mar = context.createMarshaller();
mar.setProperty("jaxb.encoding", "Unicode");
mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);

//Print XML String to Console
StringWriter sw = new StringWriter();

Folder folder = new Folder();
folder.setPath("/okm:root/test4");

//Write XML to StringWriter
mar.marshal(folder, sw);

String xmlContent = sw.toString();

System.out.println(xmlContent);

HttpEntity<String> request = new HttpEntity<String>(xmlContent, headers);

ResponseEntity<Folder> response = restTemplate1.postForEntity("http://localhost:8080/OpenKM/services/rest/folder/create", request, Folder.class);

生成的XML内容:

<?xml version="1.0" encoding="Unicode" standalone="yes"?><folder><path>/okm:root/test4</path><permissions>0</permissions><subscribed>false</subscribed><hasChildren>false</hasChildren><style>0</style></folder>

提交时出现错误:

2022-12-05 16:50:21.121 ERROR 15764 --- [nio-8082-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException$BadRequest: 400 : "JAXBException occurred : Unexpected character '"' (code 34) in prolog; expected '<'<EOL> at [row,col {unknown-source}]: [1,1]. "] with root cause

错误原因

不是XML本身的双引号需要转义,而是实现逻辑冲突:
手动用JAXB把对象转成XML字符串后,又配置了MappingJackson2HttpMessageConverter处理XML。Jackson会把传入的XML字符串当成普通字符串处理,自动给整个XML内容包裹双引号,导致服务器收到的请求体开头是"<?xml...,解析时触发"prolog里意外的双引号"错误。

解决方案

方案1:使用JAXB消息转换器,自动处理XML序列化(推荐)

直接用Spring提供的Jaxb2RootElementHttpMessageConverter,无需手动转XML,让框架自动完成对象到XML的转换:

final RestTemplate restTemplate1 = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
// 替换为JAXB专用的XML消息转换器
Jaxb2RootElementHttpMessageConverter jaxbConverter = new Jaxb2RootElementHttpMessageConverter();
jaxbConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_XML));
messageConverters.add(jaxbConverter);
restTemplate1.setMessageConverters(messageConverters);

HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("okmAdmin", "admin");
headers.setContentType(MediaType.APPLICATION_XML);

Folder folder = new Folder();
folder.setPath("/okm:root/test4");

// 直接传入Folder对象,框架自动序列化XML
HttpEntity<Folder> request = new HttpEntity<>(folder, headers);
ResponseEntity<Folder> response = restTemplate1.postForEntity(
    "http://localhost:8080/OpenKM/services/rest/folder/create", 
    request, 
    Folder.class
);

方案2:保留手动XML转换,使用字符串消息转换器

如果必须手动生成XML字符串,就改用StringHttpMessageConverter,让框架直接发送原始字符串,不做额外处理:

final RestTemplate restTemplate1 = new RestTemplate();
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
// 使用字符串转换器,直接发送XML原始内容
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(Charset.forName("Unicode"));
stringConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_XML));
messageConverters.add(stringConverter);
restTemplate1.setMessageConverters(messageConverters);

HttpHeaders headers = new HttpHeaders();
headers.setBasicAuth("okmAdmin", "admin");
headers.setContentType(MediaType.APPLICATION_XML);

JAXBContext context = JAXBContext.newInstance(Folder.class);
Marshaller mar = context.createMarshaller();
mar.setProperty("jaxb.encoding", "Unicode");
mar.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);

StringWriter sw = new StringWriter();
Folder folder = new Folder();
folder.setPath("/okm:root/test4");
mar.marshal(folder, sw);
String xmlContent = sw.toString();

HttpEntity<String> request = new HttpEntity<>(xmlContent, headers);
ResponseEntity<Folder> response = restTemplate1.postForEntity(
    "http://localhost:8080/OpenKM/services/rest/folder/create", 
    request, 
    Folder.class
);

内容的提问来源于stack exchange,提问作者user1999453

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 22:15:28