Spring Boot中Java对象转XML并生成标准SOAP信封的问题
Spring Boot生成标准SOAP信封及调整XML输出方案
1. 移除XML声明
在JAXB的Marshaller中设置jaxb.fragment属性为true,即可自动移除XML声明(<?xml version="1.0" encoding="UTF-8"?>)。
2. 定义标准SOAP信封结构
创建对应SOAP规范的JAXB实体类,用来封装业务对象:
SoapEnvelope类
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "Envelope", namespace = "http://schemas.xmlsoap.org/soap/envelope/") @XmlAccessorType(XmlAccessType.FIELD) public class SoapEnvelope { @XmlElement(name = "Header", namespace = "http://schemas.xmlsoap.org/soap/envelope/") private SoapHeader header; @XmlElement(name = "Body", namespace = "http://schemas.xmlsoap.org/soap/envelope/") private SoapBody body; // 生成getter、setter方法 }
SoapHeader类
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; @XmlAccessorType(XmlAccessType.FIELD) public class SoapHeader { // 如需自定义Header内容,添加对应字段;无需则留空即可 }
SoapBody类
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlElement; @XmlAccessorType(XmlAccessType.FIELD) public class SoapBody { @XmlElement(name = "Bookstore", namespace = "http://your-web-namespace") private Bookstore bookstore; // 生成getter、setter方法 }
3. 修正命名空间前缀(替换ns2为web)
在Bookstore实体类所在的包下创建package-info.java,指定业务命名空间及对应前缀:
@XmlSchema( namespace = "http://your-web-namespace", elementFormDefault = XmlNsForm.QUALIFIED, xmlns = { @XmlNs(prefix = "web", namespaceURI = "http://your-web-namespace") } ) package com.your.package.model; // 替换为Bookstore所在的实际包路径 import javax.xml.bind.annotation.XmlNs; import javax.xml.bind.annotation.XmlNsForm; import javax.xml.bind.annotation.XmlSchema;
同时,确保Bookstore类的@XmlRootElement或@XmlType指定的命名空间与上述一致:
@XmlRootElement(name = "Bookstore", namespace = "http://your-web-namespace") public class Bookstore { // 原有字段及JAXB注解 }
4. Controller中整合转换逻辑
修改Controller代码,将业务对象包装到SOAP信封,并配置Marshaller:
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import com.sun.xml.bind.namespacePrefixMapper; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.io.StringWriter; @RestController public class SoapController { private final JAXBContext jaxbContext; // 构造注入JAXBContext,包含SoapEnvelope、Bookstore等类 public SoapController() throws JAXBException { this.jaxbContext = JAXBContext.newInstance(SoapEnvelope.class, Bookstore.class); } @GetMapping("/soap/bookstore") public ResponseEntity<String> generateSoapResponse() throws JAXBException { // 1. 初始化业务对象 Bookstore bookstore = new Bookstore(); // 填充bookstore数据... // 2. 包装到SOAP信封 SoapEnvelope soapEnvelope = new SoapEnvelope(); SoapBody soapBody = new SoapBody(); soapBody.setBookstore(bookstore); soapEnvelope.setBody(soapBody); soapEnvelope.setHeader(new SoapHeader()); // 无需Header可设为null // 3. 配置Marshaller Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); // 移除XML声明 // 指定命名空间前缀映射 marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() { @Override public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { if ("http://schemas.xmlsoap.org/soap/envelope/".equals(namespaceUri)) { return "soap"; } else if ("http://your-web-namespace".equals(namespaceUri)) { return "web"; } return suggestion; } }); // 4. 转换为XML字符串 StringWriter writer = new StringWriter(); marshaller.marshal(soapEnvelope, writer); String soapXml = writer.toString(); // 5. 返回SOAP响应 return ResponseEntity.ok() .contentType(MediaType.TEXT_XML) .body(soapXml); } }
注意事项
- 若使用Spring Boot 3+,需替换
javax.xml.bind相关包为jakarta.xml.bind,并确保引入Jakarta XML Binding依赖。 NamespacePrefixMapper属于JAXB实现类,需确保项目中包含jaxb-impl依赖(Maven可直接引入)。
内容的提问来源于stack exchange,提问作者The Rock
相关产品推荐
相关产品推荐

