【问题标题】:How to send a SOAP request using WebServiceTemplate?如何使用 WebServiceTemplate 发送 SOAP 请求?
【发布时间】:2016-03-25 21:29:16
【问题描述】:

我正在尝试向 SOAP 网络服务发送请求。我阅读了this tutorial 并准备了以下代码。但是,我将向多个 SOAP Web 服务发送不同的请求,而本教程只关注一个请求。如何使用WebserviceTemplate 发送 SOAP 请求?

WebServiceTemplate

    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());

【问题讨论】:

  • 您是否有充分的理由手动执行此操作?如果您有服务 wdsl 文件,则可以生成 Web 服务代理。 Here 是关于如何在 Eclipse 中执行此操作的说明。
  • @Pétur 问题是我没有 wsdl,我还要向多个基于 SOAP 的 Web 服务发送 SOAP 请求。

标签: java spring web-services soap jaxb


【解决方案1】:

你可以使用下面的代码,你不需要在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();
        }

【讨论】:

  • 如果我没有设置 unmarshaller,我会得到 'java.lang.IllegalStateException: No unmarshaller registered。检查 WebServiceTemplate 的配置。您可以使用 'webServiceTemplate.setUnmarshaller(marshaller);' 传递此异常
  • 放什么来代替PACKAGE?
  • @HerilMuratovic 我改用setPackagesToScan。文档说:Set the packages to search for classes with JAXB2 annotations in the classpath. This is using a Spring-bases search and therefore analogous to Spring's component-scan feature
【解决方案2】:

要将不同的 SOAP 请求发送到不同的 SOAP 服务,您只需让 WebServiceTemplate 了解它必须处理的所有请求和响应。

为每个请求和响应创建一个 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;
    }
}

(@XmlRootElement 是因为我们在下面使用 JAXB 编组器;有关更多信息,请参阅 Jaxb 参考)。

模板的设置是这样完成的:

    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”是 Request/Responses 类所在包的名称,以便 jaxb 可以找到它们。

然后你只需实例化你想要执行调用的类的请求,像这样:

    // 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);

同样,您可以将响应对象转换为上面定义的 JAXB 类。

【讨论】:

  • 我使用了代码,但它返回以下原因:javax.xml.bind.JAXBException:“my.project.flights.wegolo”不包含 ObjectFactory.class 或 jaxb.in​​dex
【解决方案3】:

这是您应该寻找的示例

Soap 与REST 不同,有很多限制,它遵循一些标准,在您获得网络调用之前必须满足这些标准,

但与 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";

这段代码是用Android 编写的,所以你可以忽略其中的一部分,但我仍然保留它的答案,以便来自 android 背景的人可以很好地利用它

在浏览器中打开 [WSDL][1] 并检查对调用服务器上的远程方法很重要的事情。

1 您将看到一个属性targetNamespace,其值为Namespace,在这种情况下您将使用Namespacehttp://www.w3schools.com/webservices/

2 现在你需要方法的名称这个WSDL有四个方法每个都是int属性s:element,值是方法的名称在这种情况下四个方法是FahrenheitToCelsiusFahrenheitToCelsiusResponseCelsiusToFahrenheit , CelsiusToFahrenheitResponse

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);
    }
}

【讨论】:

  • 似乎没有使用 Spring 框架的 WebServiceTemplate 对吗?我有兴趣了解 Spring 框架的 SOAP 支持
  • 你在使用soap:soap:2.3.1 库来调用soap
  • @Jack,如果可能,请提供 WSDL url,我会更新答案以便您查看
  • 问题是,我没有 WSDL。
【解决方案4】:

假设您的 SoapMessage 是可编组的

要将相同的消息发送到多个端点,您只需要循环发送代码和请求处理程序。

类似这样的:

{
    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.
}

此代码使用 Spring WebServiceTemplate

【讨论】:

    【解决方案5】:

    如果您必须发送带有身份验证的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;
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-19
      • 2013-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多