如何在Java中将字符串转换为SOAPMessage?

28

我想知道是否有一种方法可以将字符串转换为SOAPMessage?

假设我有一个如下的字符串:

String send = "<soap:Envelope xmlns:mrns0=\"http://sdp.SOMETHING.com/mapping/TSO\" xmlns:sdp=\"http://sdp.SOMETHING.com.tr/mapping/generated\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
        + "<soap:Header>"
        + "<sdp:token>"
        + "<sdp:sessionId>" + sessionId + "</sdp:sessionId>"
        + "</sdp:token>"
        + "<sdp:transaction-list>"
        + "<sdp:transaction-id>" + 11 + "</sdp:transaction-id>"
        + "</sdp:transaction-list>"
        + "</soap:Header>"
        + "<soap:Body>"
        + "<sdp:SendSMSInput>"
        + "<sdp:EXPIRY_DATE>" + extime + "</sdp:EXPIRY_DATE>"
        + "<sdp:MESSAGE_CLASS>0</sdp:MESSAGE_CLASS>"
        + "<sdp:S_DATE>" + time + "</sdp:S_DATE>"
        + "<sdp:SHORT_NUMBER>1905</sdp:SHORT_NUMBER>"
        + "<sdp:SRC_MSISDN>" + numSend + "</sdp:SRC_MSISDN>"
        + "<sdp:TO_RECEIVERS>"
        + "<sdp:msisdn>" + numSend + "</sdp:msisdn>"
        + "</sdp:TO_RECEIVERS>"
        + "<sdp:MESSAGE_BODY>"
        + "<sdp:message>Message body here.</sdp:message>"
        + "</sdp:MESSAGE_BODY>"
        + "</sdp:SendSMSInput>"
        + "</soap:Body>"
        + "</soap:Envelope>";

如何将字符串转换?


1
你可以解析它。或者一开始就将其构建为消息。 - Dave Newton
6个回答

52
将字符串转换为输入流,然后将其读入SOAP消息工厂。
InputStream is = new ByteArrayInputStream(send.getBytes());
SOAPMessage request = MessageFactory.newInstance().createMessage(null, is);

你可以在这里阅读如何实现。


非常感谢。还有一个问题:当我创建SOAPMessageRequest时,它会自动创建头和正文。我需要更改字符串的某些部分吗? - Ali Yucel Akgul
已完成,先生!但是我对应该删除哪部分感到困惑。 - Ali Yucel Akgul

4
这对我有效:

SOAPMessage sm = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage(new MimeHeaders(), is);

3

我已经测试过使用SAXSource作为数据源,将SOAPMessage进行解析比接受答案中所用的内部SAAJ解析实现要快大约50%:

SOAPMessage message = messageFactory.createMessage();
message.getSOAPPart().setContent(new SAXSource(new InputSource(new StringReader(send))));

以下是对不同XML解析源及其工厂缓存影响的基准测试:

/*
Benchmark (jdk1.8.0_202 32-bit)                                       Mode  Cnt     Score     Error  Units
SoapMessageBenchmark.testCreateMessage                               thrpt  100  4156,685 ? 215,571  ops/s
SoapMessageBenchmark.testCreateMessageWithMessageFactoryNotCached    thrpt  100  3709,299 ? 115,495  ops/s
SoapMessageBenchmark.testSetContentDom                               thrpt  100  5935,972 ? 215,389  ops/s
SoapMessageBenchmark.testSetContentDomWithDocumentBuilderNotCached   thrpt  100  3433,539 ? 218,889  ops/s
SoapMessageBenchmark.testSetContentSax                               thrpt  100  6693,179 ? 319,581  ops/s
SoapMessageBenchmark.testSetContentSaxAndExtractContentAsDocument    thrpt  100  4109,924 ? 229,987  ops/s
SoapMessageBenchmark.testSetContentStax                              thrpt  100  5126,822 ? 249,648  ops/s
SoapMessageBenchmark.testSetContentStaxWithXmlInputFactoryNotCached  thrpt  100  4630,860 ? 235,773  ops/s
*/

package org.sample;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Timeout;
import org.openjdk.jmh.annotations.Warmup;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stax.StAXSource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 100, timeUnit = TimeUnit.MILLISECONDS)
@Timeout(time = 10)
public class SoapMessageBenchmark {

    private static MessageFactory messageFactory;
    private static DocumentBuilder documentBuilder;
    private static XMLInputFactory xmlInputFactory;

    static {
        try {
            documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
            xmlInputFactory = XMLInputFactory.newInstance();
        } catch (SOAPException | ParserConfigurationException e) {
            throw new IllegalStateException(e);
        }
    }

    @State(Scope.Benchmark)
    public static class S {
        byte[] bytes = ("<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                                "  <soap:Header>\n" +
                                "    <ResponseHeader xmlns=\"https://www.google.com/apis/ads/publisher/v201905\">\n" +
                                "      <requestId>xxxxxxxxxxxxxxxxxxxx</requestId>\n" +
                                "      <responseTime>1063</responseTime>\n" +
                                "    </ResponseHeader>\n" +
                                "  </soap:Header>\n" +
                                "  <soap:Body>\n" +
                                "    <getAdUnitsByStatementResponse xmlns=\"https://www.google.com/apis/ads/publisher/v201905\">\n" +
                                "      <rval>\n" +
                                "        <totalResultSetSize>1</totalResultSetSize>\n" +
                                "        <startIndex>0</startIndex>\n" +
                                "        <results>\n" +
                                "          <id>2372</id>\n" +
                                "          <name>RootAdUnit</name>\n" +
                                "          <description></description>\n" +
                                "          <targetWindow>TOP</targetWindow>\n" +
                                "          <status>ACTIVE</status>\n" +
                                "          <adUnitCode>1002372</adUnitCode>\n" +
                                "          <inheritedAdSenseSettings>\n" +
                                "            <value>\n" +
                                "              <adSenseEnabled>true</adSenseEnabled>\n" +
                                "              <borderColor>FFFFFF</borderColor>\n" +
                                "              <titleColor>0000FF</titleColor>\n" +
                                "              <backgroundColor>FFFFFF</backgroundColor>\n" +
                                "              <textColor>000000</textColor>\n" +
                                "              <urlColor>008000</urlColor>\n" +
                                "              <adType>TEXT_AND_IMAGE</adType>\n" +
                                "              <borderStyle>DEFAULT</borderStyle>\n" +
                                "              <fontFamily>DEFAULT</fontFamily>\n" +
                                "              <fontSize>DEFAULT</fontSize>\n" +
                                "            </value>\n" +
                                "          </inheritedAdSenseSettings>\n" +
                                "        </results>\n" +
                                "      </rval>\n" +
                                "    </getAdUnitsByStatementResponse>\n" +
                                "  </soap:Body>\n" +
                                "</soap:Envelope>").getBytes();
    }

    @Benchmark
    public SOAPBody testCreateMessage(S s) throws SOAPException, IOException {
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            SOAPMessage message = messageFactory.createMessage(null, inputStream);
            return message.getSOAPBody();
        }
    }

    @Benchmark
    public SOAPBody testCreateMessageWithMessageFactoryNotCached(S s) throws SOAPException, IOException {
        MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            SOAPMessage message = messageFactory.createMessage(null, inputStream);
            return message.getSOAPBody();
        }
    }

    @Benchmark
    public SOAPBody testSetContentDom(S s) throws SOAPException, IOException, SAXException {
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            Document document = documentBuilder.parse(inputStream);
            SOAPMessage message = messageFactory.createMessage();
            message.getSOAPPart().setContent(new DOMSource(document));
            return message.getSOAPBody();
        }
    }

    @Benchmark
    public SOAPBody testSetContentDomWithDocumentBuilderNotCached(S s) throws SOAPException, IOException, SAXException, ParserConfigurationException {
        DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            Document document = documentBuilder.parse(inputStream);
            SOAPMessage message = messageFactory.createMessage();
            message.getSOAPPart().setContent(new DOMSource(document));
            return message.getSOAPBody();
        }
    }

    @Benchmark
    public SOAPBody testSetContentSax(S s) throws SOAPException, IOException {
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            SOAPMessage message = messageFactory.createMessage();
            message.getSOAPPart().setContent(new SAXSource(new InputSource(inputStream)));
            return message.getSOAPBody();
        }
    }

    @Benchmark
    public Document testSetContentSaxAndExtractContentAsDocument(S s) throws SOAPException, IOException {
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            SOAPMessage message = messageFactory.createMessage();
            message.getSOAPPart().setContent(new SAXSource(new InputSource(inputStream)));
            return message.getSOAPBody().extractContentAsDocument();
        }
    }

    @Benchmark
    public SOAPBody testSetContentStax(S s) throws SOAPException, IOException, XMLStreamException {
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            XMLStreamReader xmlStreamReader = new StreamReaderDelegate(xmlInputFactory.createXMLStreamReader(inputStream)) {
                @Override
                public String getVersion() {
                    return "1.1";
                }
            };
            SOAPMessage message = messageFactory.createMessage();
            message.getSOAPPart().setContent(new StAXSource(xmlStreamReader));
            return message.getSOAPBody();
        }
    }

    @Benchmark
    public SOAPBody testSetContentStaxWithXmlInputFactoryNotCached(S s) throws SOAPException, IOException, XMLStreamException {
        XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
        try (InputStream inputStream = new ByteArrayInputStream(s.bytes)) {
            XMLStreamReader xmlStreamReader = new StreamReaderDelegate(xmlInputFactory.createXMLStreamReader(inputStream)) {
                @Override
                public String getVersion() {
                    return "1.1";
                }
            };
            SOAPMessage message = messageFactory.createMessage();
            message.getSOAPPart().setContent(new StAXSource(xmlStreamReader));
            return message.getSOAPBody();
        }
    }

}

非常感谢!我并不太关心性能,只是在进行一些测试自动化,但是能够将文本加载到消息中的能力比各种“addChildElement”要好得多,如果您事先不了解XML结构,那么编写脚本就会很困难! - DraxDomax

0

你可以使用以下方式从文件中读取:

byte[] encoded = Files.readAllBytes(Paths.get("C:/resources/soap/RequestFileReply.xml"));
InputStream bStream = new ByteArrayInputStream(encoded);
SOAPMessage request = MessageFactory.newInstance().createMessage(null, bStream);
SOAPBody body = request.getSOAPBody();

0

改为:

System.out.println(response.getContentDescription());

在获取响应后,请将其替换为以下行:
response.writeTo(System.out);

0

我只是想在Stack Overflow上分享我的代码片段,希望能帮助一些人。

带有注释的SOAP-XML字符串

static boolean OMIT_XML_DECLARATION = true;
static String soapXML = "<env:Envelope xmlns:env=\"http://www.w3.org/2003/05/soap-envelope\">"
            + "<env:Body> "
            + "<product version=\"11.1.2.4.0\">  <!-- Data XML -->"
            + "<name>API Gateway</name> <company>Oracle</company> <description>SOA Security and Management</description>"
            + "</product> </env:Body> </env:Envelope>";

将SOAP-XML字符串转换为SOAP消息对象。
public SOAPMessage getSoapMessage(String xmlData, boolean isToIgnoringComments) throws Exception {
    if (isToIgnoringComments) {
        Document doc = getDocument(xmlData); // SOAP MSG removing comment elements
        xmlData = toStringDocument(doc);
    }
    
    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(xmlData.getBytes());
    MimeHeaders mimeHeaders = new MimeHeaders();
    SOAPMessage message = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL).createMessage(mimeHeaders, byteArrayInputStream);
    return message;
}
public static Document getDocument(String xmlData) throws Exception {
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    dbFactory.setNamespaceAware(true);
    dbFactory.setIgnoringComments(true);
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        InputSource ips = new org.xml.sax.InputSource(new StringReader(xmlData));
        Document doc = dBuilder.parse(ips);
    return doc;
}

将SOAP消息对象转换为SOPA XML字符串。
public static String toStringDocument(Document doc) throws TransformerException {
    StringWriter sw = new StringWriter();
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    if (OMIT_XML_DECLARATION) {
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    } else {
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    }
    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

    transformer.transform(new DOMSource(doc), new StreamResult(sw));
    return sw.toString(); // sw.getBuffer().toString();
}

完整示例:

public class SOAPOperations {

    // dependency: groupId:xml-security, artifactId:xmlsec, version:1.3.0
    // dependency: groupId:xalan, artifactId:xalan, version:2.7.1
    public static void main(String[] args) throws Exception {
        
        SOAPOperations obj = new SOAPOperations();
        
        SOAPMessage soapMessage = obj.getSoapMessage(soapXML, true);
        System.out.println("SOAP Message Object:\n"+soapMessage);
        
        String soapMessageStr = obj.getSoapMessage(soapMessage);
        System.out.println("SOAP Message String:\n"+soapMessageStr);
        
        String soapBodyStr = obj.getSoapBody(soapMessage);
        System.out.println("SOAP Body String:\n"+soapBodyStr);
    }

    public String getSoapBody(SOAPMessage soapMessage) throws Exception {
        SOAPBody soapEnv = soapMessage.getSOAPBody();
        Document ownerDocument = soapEnv.extractContentAsDocument();
        String stringDocument = toStringDocument(ownerDocument);
        return stringDocument;
    }
    public String getSoapMessage(SOAPMessage soapMessage) throws Exception {
        SOAPEnvelope soapEnv = soapMessage.getSOAPPart().getEnvelope();
        Document ownerDocument = soapEnv.getOwnerDocument();
        String stringDocument = toStringDocument(ownerDocument);
        return stringDocument;
    }
}

@查看SOAP链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接