Spring 使用JAXB在RestController中接受SOAP消息
我们创建了一个springboot@RestController,它将使用SOAP接受XML请求,但我无法让它工作 示例消息:Spring 使用JAXB在RestController中接受SOAP消息,spring,soap,jaxb,Spring,Soap,Jaxb,我们创建了一个springboot@RestController,它将使用SOAP接受XML请求,但我无法让它工作 示例消息: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<PostPayload xmlns="http://mynamespace/">
<Message>
<Header type="Main" version="1.0" desc="Some header description...">
<Title content="The quick brown fox." />
</Header>
<Content />
<Footer type="Copyright" name="Footer01">Some random content...</Footer>
</Message>
</PostPayload>
</soap:Body>
</soap:Envelope>
消息类
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Message")
public class Message {
@XmlElement(name = "Header", required = true)
private Header header;
@XmlElement(name = "Content", required = true)
private Content content;
@XmlElement(name = "Footer", required = true)
private Footer footer;
// Getters and setters here...
@Override
public String toString() {
// In here, I outputted the values of the header and footer.
}
}
标题类
@XmlRootElement(name = "Header")
@XmlAccessorType(XmlAccessType.FIELD)
public class Header {
@XmlAttribute(name = "type", required = true)
private String type;
@XmlAttribute(name = "version", required = true)
private String version;
@XmlAttribute(name = "desc", required = true)
private String description;
// Getters and setters here...
}
内容类
@XmlRootElement(name = "Content")
@XmlAccessorType(XmlAccessType.FIELD)
public class Content {
}
页脚类
@XmlRootElement(name = "Footer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Footer {
@XmlValue
private String value;
@XmlAttribute(name = "name")
private String name;
@XmlAttribute(name = "type")
private String type;
//Getter and setters here...
}
因此,如果我将soap消息发送到rest服务,它将返回null。rest控制器中的封送器只是检查输出是否与请求相同,这意味着我正确读取了XML。不幸的是,它返回null。有什么想法吗?您不需要用Jaxb序列化请求,因为SpringREST控制器会自动执行此操作。作为函数中的参数的消息类必须是include PostPayload,并且在xml中具有名称空间()。 restcontroller正在检查标题中的内容类型并自动进行转换 此帖子包含更多信息: 工作示例:
package com.mkysoft.restxml.contoller;
import com.mkysoft.restxml.domain.*;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@RestController
@RequestMapping("rest-service")
public class MessageController {
@PostMapping(consumes = MediaType.APPLICATION_XML_VALUE)
public String handler(@RequestBody Envelope envelope) {
System.out.println(envelope);
System.out.println("\n\n\n");
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Envelope.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(envelope, System.out);
} catch (JAXBException ex) {
System.out.println(ex.toString());
}
return "Done!";
}
@GetMapping()
public Envelope gethandler() {
final Envelope envelope = new Envelope();
final Message message = new Message();
final Header header = new Header();
header.setType("type");
header.setDescription("description");
header.setVersion("version");
message.setHeader(header);
message.setContent(new Content());
message.setFooter(new Footer());
final Body body = new Body();
final PostPayload postPayload = new PostPayload();
postPayload.setMessage(message);
//body.setPostPayload(postPayload);
envelope.setBody(body);
return envelope;
}
}
Envelope.java
package com.mkysoft.restxml.domain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Envelope", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
public class Envelope {
@XmlElement(name = "Body", required = true, namespace = "http://schemas.xmlsoap.org/soap/envelope/")
private Body body;
public Body getBody() {
return body;
}
public void setBody(Body body) {
this.body = body;
}
}
Body.java
package com.mkysoft.restxml.domain;
import com.sun.xml.internal.txw2.annotation.XmlNamespace;
import org.apache.cxf.jaxrs.ext.xml.XMLName;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Body", namespace = "http://schemas.xmlsoap.org/soap/envelope/")
public class Body {
@XmlElement(name = "PostPayload", required = true, namespace = "http://mynamespace/")
private PostPayload postPayload;
public PostPayload getPostPayload() {
return postPayload;
}
public void setPostPayload(PostPayload postPayload) {
this.postPayload = postPayload;
}
}
PostPayload.java
package com.mkysoft.restxml.domain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "PostPayload", namespace = "http://mynamespace/")
public class PostPayload {
@XmlElement(name = "Message", required = true, namespace = "http://mynamespace/")
private Message message;
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
}
Message.java
package com.mkysoft.restxml.domain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Message", namespace = "http://mynamespace/")
public class Message {
@XmlElement(name = "Header", required = true, namespace = "http://mynamespace/")
private Header header;
@XmlElement(name = "Content", required = true, namespace = "http://mynamespace/")
private Content content;
@XmlElement(name = "Footer", required = true, namespace = "http://mynamespace/")
private Footer footer;
public Header getHeader() {
return header;
}
public void setHeader(Header header) {
this.header = header;
}
public Content getContent() {
return content;
}
public void setContent(Content content) {
this.content = content;
}
public Footer getFooter() {
return footer;
}
public void setFooter(Footer footer) {
this.footer = footer;
}
@Override
public String toString() {
// In here, I outputted the values of the header and footer.
return null;
}
}
Header.java
package com.mkysoft.restxml.domain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Header", namespace = "http://mynamespace/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Header {
@XmlAttribute(name = "type", required = true)
private String type;
@XmlAttribute(name = "version", required = true)
private String version;
@XmlAttribute(name = "desc", required = true)
private String description;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Footer.java
package com.mkysoft.restxml.domain;
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "Footer", namespace = "http://mynamespace/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Footer {
@XmlValue
private String value;
@XmlAttribute(name = "name")
private String name;
@XmlAttribute(name = "type")
private String type;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
Content.java
package com.mkysoft.restxml.domain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Content", namespace = "http://mynamespace/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Content {
}
谢谢mkysoft。我知道Spring默认使用JAXB,RestController中的封送器只是为了检查它是否正确读取XML,但它只是返回null。我已经更新了帖子以反映消息类和子类。你的类没有名称空间属性,PostPayload必须是root。谢谢你mkysoft!谢谢你的帮助。现在,当放置正确的对象映射和名称空间时,它就可以工作了。最后一件事,我注意到它没有得到页脚文本的值,即“一些随机内容…”,即使我放置@XmlValue。您需要所有类的名称空间,我更新了我的答案。我为所有类添加了答案中定义的名称空间,但是,我仍然没有得到页脚文本。这是我从marshaller.marshall(信封,系统,输出)得到的输出;:
package com.mkysoft.restxml.domain;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "Content", namespace = "http://mynamespace/")
@XmlAccessorType(XmlAccessType.FIELD)
public class Content {
}