简体   繁体   English

如何使用 WebServiceTemplate 发送 SOAP 请求?

[英]How to send a SOAP request using WebServiceTemplate?

I am trying to send a request to a SOAP webservice.我正在尝试向 SOAP 网络服务发送请求。 I readthis tutorial and prepared the following code.我阅读了本教程并准备了以下代码。 However, I am going to send different requests to multiple SOAP webservices, whereas the tutorial focused on one request.但是,我将向多个 SOAP Web 服务发送不同的请求,而本教程只关注一个请求。 How can I send SOAP request using WebserviceTemplate ?如何使用WebserviceTemplate发送 SOAP 请求?

WebServiceTemplate Web服务模板

    SoapMessage soapMsg = new SoapMessage();
    soapMsg.setUsername("Requester");
    soapMsg.setPassword("Pass");
    soapMsg.setLanguageCode("EN");
    Request request = new Request();
    request.setDeparture("FDH");
    request.setDestination("HAM");
    Date date = new Date();
    SimpleDateFormat frm2 = new SimpleDateFormat("yyyy-MM-dd");
    request.setDepartureDate(frm2.parse(frm2.format(date)));
    request.setNumADT(1);
    request.setNumCHD(0);
    request.setNumInf(0);
    request.setCurrencyCode("EUR");
    request.setWaitForResult(true);
    request.setNearByDepartures(true);
    request.setNearByDestinations(true);
    request.setRronly(false);
    request.setMetaSearch(false);
    soapMsg.setRequest(request);
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate().  //how to create object and send request!
    Object response = webServiceTemplate.marshalSendAndReceive(
            "https://aaa5.elsyarres.net", soapMsg);
    Response msg = (Response) response;
    System.err.println("size of results of wogolo:"
            + msg.getFlights().getFlight().size());

You can use following code, you do not need to define anything in xml file.你可以使用下面的代码,你不需要在 xml 文件中定义任何东西。

  try {
            SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(
                    MessageFactory.newInstance());
            messageFactory.afterPropertiesSet();

            WebServiceTemplate webServiceTemplate = new WebServiceTemplate(
                    messageFactory);
            Jaxb2Marshaller marshaller = new Jaxb2Marshaller();

            marshaller.setContextPath("PACKAGE");
            marshaller.afterPropertiesSet();

            webServiceTemplate.setMarshaller(marshaller);
            webServiceTemplate.afterPropertiesSet();

            Response response = (Response) webServiceTemplate
                    .marshalSendAndReceive(
                            "address",
                            searchFlights);

            Response msg = (Response) response;
        } catch (Exception s) {
            s.printStackTrace();
        }

To send different SOAP requests to different SOAP services, you just need to make your WebServiceTemplate aware of all requests and responses it will have to process.要将不同的 SOAP 请求发送到不同的 SOAP 服务,您只需让 WebServiceTemplate 知道它必须处理的所有请求和响应。

Create a Java class for each request and response like so:为每个请求和响应创建一个 Java 类,如下所示:

package models;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;

@XmlRootElement
public class FlyRequest implements Serializable {

    private boolean nearByDeparture;

    public FlyRequest() {}

    public boolean isNearByDeparture() {
        return nearByDeparture;
    }

    public void setNearByDeparture(boolean nearByDeparture) {
        this.nearByDeparture = nearByDeparture;
    }
}

(The @XmlRootElement is because we use JAXB marshaller below; see Jaxb reference for more info). (@XmlRootElement 是因为我们在下面使用 JAXB 编组器;有关更多信息,请参阅 Jaxb 参考)。

The setup of the template is done for example like so:模板的设置是这样完成的:

    SaajSoapMessageFactory messageFactory = new SaajSoapMessageFactory(MessageFactory.newInstance());
    messageFactory.afterPropertiesSet();

    WebServiceTemplate webServiceTemplate = new WebServiceTemplate(messageFactory);
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setContextPath("models");
    marshaller.afterPropertiesSet();

    webServiceTemplate.setMarshaller(marshaller);
    webServiceTemplate.afterPropertiesSet();

"models" is the name of the package where the Request/Responses classes are, so that jaxb can find them. “models”是请求/响应类所在的包的名称,以便 jaxb 可以找到它们。

Then you just instantiate the request of the class you want to perform the call, like so:然后你只需实例化你想要执行调用的类的请求,就像这样:

    // call fly service:
    FlyRequest flyRequest = new FlyRequest();
    flyRequest.setNearByDeparture(false);
    Object flyResponse = webServiceTemplate.marshalSendAndReceive("https://example.net/fly", flyRequest);

    // call purchase service:
    PurchaseRequest purchaseRequest = new PurchaseRequest();
    purchaseRequest.setPrice(100);
    Object purchaseResponse = webServiceTemplate.marshalSendAndReceive("https://example.net/purchase", purchaseRequest);

Similarly, you can cast the response objects into your JAXB classes defined above.同样,您可以将响应对象转换为上面定义的 JAXB 类。

Here is an Example what you should be looking for这是您应该寻找的示例

Soap has a lot of restriction unlike REST , It follows some standards which have to be meet before you get Network call to work,REST不同,Soap 有很多限制,它遵循一些必须满足的标准,才能让网络调用工作,

But unlike Rest , in Soap if you have WSDL URL you can get all the information needed to call the Soap call但与Rest不同,在 Soap 中,如果您有WSDL URL,您可以获得调用 Soap 调用所需的所有信息

private final String NAMESPACE = "http://www.w3schools.com/webservices/";
private final String URL = "http://www.w3schools.com/webservices/tempconvert.asmx?WSDL";
private final String SOAP_ACTION = "http://www.w3schools.com/webservices/CelsiusToFahrenheit";
private final String METHOD_NAME = "CelsiusToFahrenheit";

this code was written in Android so you can ignore some part of it but I still kept it in answer so someone from android background can put a good use to it这段代码是用Android编写的,所以你可以忽略它的一部分,但我仍然保留它作为答案,这样来自 Android 背景的人可以很好地利用它

Open [WSDL][1] in browser and check for the things which matter to call a remote method on server.在浏览器中打开[WSDL][1]并检查在服务器上调用远程方法的重要事项。

1 you will see an attribute targetNamespace whose value would be Namespace which you will use in this case Namespace is http://www.w3schools.com/webservices/ 1 您将看到一个属性targetNamespace ,其值为Namespace ,您将在本例中使用Namespacehttp://www.w3schools.com/webservices/

2 Now you require the name of the method this WSDL has four method each of the are int attribute s:element with the value is the name of the Method in this case four methods are FahrenheitToCelsius , FahrenheitToCelsiusResponse , CelsiusToFahrenheit , CelsiusToFahrenheitResponse 2 现在你需要方法的名称,这个WSDL有四个方法,每个方法都是 int 属性s:element ,其值是方法的名称,在这种情况下,四个方法是FahrenheitToCelsiusFahrenheitToCelsiusResponseCelsiusToFahrenheitCelsiusToFahrenheitResponse

3 Now you have to fure out the SOAP Action which is NAMESPACE+METHOD but WSDL also gives information about that as well, look for the tag soap:operation and it's soapAction attribute havs the Soap action as it's value in this case which we want to call is http://www.w3schools.com/webservices/CelsiusToFahrenheit 3 现在你必须解决SOAP Action ,它是NAMESPACE+METHOD但 WSDL 也提供了相关信息,查找标签soap:operation并且它的soapAction属性具有 Soap 操作,因为它在这种情况下是我们想要的值电话是http://www.w3schools.com/webservices/CelsiusToFahrenheit

private class MyTask extends AsyncTask<Void, Void, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog.show();
    }

    @Override
    protected String doInBackground(Void... params) {
        try {
            SoapObject soapObject = new SoapObject(NAMESPACE, METHOD_NAME);

            soapObject.addProperty("Celsius","12");


            SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
            envelope.dotNet = true;
            envelope.setOutputSoapObject(soapObject);
            HttpTransportSE httpTransportSE = new HttpTransportSE(URL);

            httpTransportSE.call(SOAP_ACTION, envelope);
            SoapPrimitive soapPrimitive = (SoapPrimitive)envelope.getResponse();
            Log.d("TAG", "doInBackground: "+soapPrimitive.toString());

            return soapObject.toString();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    @Override
    protected void onPostExecute(String aVoid) {
        super.onPostExecute(aVoid);
        progressDialog.dismiss();
        textView.setText(""+aVoid);
    }
}

Assuming that your SoapMessage is marhsallable假设您的 SoapMessage 是可编组的

To send the same message to multiple endpoints you only need to loop on the sending code and the request handler.要将相同的消息发送到多个端点,您只需循环发送代码和请求处理程序。

Something like this:像这样:

{
    String endpoint = "https://aaa5.elsyarres.net"
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate().
    webServiceTemplate.setDefaultUri(endpoint);
    Object response = webServiceTemplate.marshalSendAndReceive(soapMsg);
    // handle you are response as you are currently doing.
    // Loop changing the endpoint as you need.
}

This code uses the Spring WebServiceTemplate此代码使用 Spring WebServiceTemplate

I tried many options and finally below one worked for me if you have to send soap header with authentication(Provided authentication object created by wsimport) and also need to set soapaction.我尝试了很多选项,如果您必须发送带身份验证的 soap 标头(提供由 wsimport 创建的身份验证对象)并且还需要设置 soapaction,我最后选择了下面一个对我有用的选项。

public Response callWebService(String url, Object request)

{
    Response res = null;
    log.info("The request object is " + request.toString());

    try {
        
        

        res = (Response) getWebServiceTemplate().marshalSendAndReceive(url, request,new WebServiceMessageCallback() {
                 @Override
                  public void doWithMessage(WebServiceMessage message) {
                    try {
                      // get the header from the SOAP message
                      SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();

                      // create the header element
                      ObjectFactory factory = new ObjectFactory();
                      Authentication auth =
                          factory.createAuthentication();
                      auth.setUser("****");
                      auth.setPassword("******");
                     ((SoapMessage) message).setSoapAction(
                                "soapAction");

                      JAXBElement<Authentication> headers =
                          factory.createAuthentication(auth);

                      // create a marshaller
                      JAXBContext context = JAXBContext.newInstance(Authentication.class);
                      Marshaller marshaller = context.createMarshaller();

                      // marshal the headers into the specified result
                      marshaller.marshal(headers, soapHeader.getResult());
                      
                    } catch (Exception e) {
                      log.error("error during marshalling of the SOAP headers", e);
                    }
                  }
                });

        
    } catch (Exception e) {
        e.printStackTrace();
    }
    return res;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM