Spring boot - 服务器无法识别 HTTP 标头 SOAPAction 的值

问题描述 投票:0回答:3

我想使用 jaxb 来使用肥皂服务。 jaxb 生成的请求是

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
    <SOAP-ENV:Header/>
    <SOAP-ENV:Body>
      <ns2:Add xmlns:ns2="http://tempuri.org/">
         <ns2:intA>10</ns2:intA><ns2:intB>20</ns2:intB>
      </ns2:Add>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

但是响应是如标题所述的肥皂异常。

Caused by: org.springframework.ws.soap.client.SoapFaultClientException: System.Web.Services.Protocols.SoapException: Server did not recognize the value of HTTP Header SOAPAction: .
   at System.Web.Services.Protocols.Soap11ServerProtocolHelper.RouteRequest()
   at System.Web.Services.Protocols.SoapServerProtocol.RouteRequest(SoapServerMessage message)
   at System.Web.Services.Protocols.SoapServerProtocol.Initialize()
   at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)

下面是我的肥皂配置代码。源示例:https://howtodoinjava.com/spring-boot/spring-soap-client-webservicetemplate/

    public class ConsumeSoapApplication {
            public static String wsdlurl = "http://www.dneonline.com/calculator.asmx?wsdl";
            public static void main(String[] args) {
                try {
                    JAXBContext.newInstance(com.dxc.service.soap.service.calc.ObjectFactory.class.getPackage().getName(),
                            com.dxc.service.soap.service.calc.ObjectFactory.class.getClassLoader());
                } catch (JAXBException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                SpringApplication.run(ConsumeSoapApplication.class, args);
            }

            @Bean
            CommandLineRunner lookup(SoapConnector soapConnector) {
                return args -> {
                    Integer a = 10;
                    Integer b = 20;
                    if(args.length>0){
                        a = Integer.parseInt(args[0]);
                        b = Integer.parseInt(args[1]);
                    }

                    Add add = new Add();
                    add.setIntA(a);
                    add.setIntB(b);
                    AddResponse addRes = (AddResponse) soapConnector.callWebService(wsdlurl, add);
                    System.out.println("Got Response As below ========= : ");
                    System.out.println("Added result : "+addRes.getAddResult());
                };
            }
        }

@Configuration
public class SoapConfig {    
    @Bean
        public Jaxb2Marshaller marshaller() {
            try {
                JAXBContext jb = JAXBContext.newInstance(com.dxc.service.soap.service.calc.ObjectFactory.class.getPackage().getName(),
                        com.dxc.service.soap.service.calc.ObjectFactory.class.getClassLoader());
                //Jaxb2Marshaller marshaller = (Jaxb2Marshaller) jb.createMarshaller();
                Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
                marshaller.setPackagesToScan("com.dxc.service.soap.service.calc");
                //marshaller.setContextPath("com.dxc.service.soap.calc");
                return marshaller;
            } catch (JAXBException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }   
            return null;
        }

        @Bean
        public SoapConnector soapConnector(Jaxb2Marshaller marshaller) {
            SoapConnector client = new SoapConnector();
            client.setDefaultUri("http://www.dneonline.com/calculator.asmx");
            client.setMarshaller(marshaller);
            client.setUnmarshaller(marshaller);
            return client;
        }

请帮助我。谢谢。

spring-boot web-services soap jaxb jaxb2-maven-plugin
3个回答
8
投票

您面临的问题是 http://www.dneonline.com/calculator.asmx 上的 Web 服务需要

SOAPAction
标头。由于您没有提供服务,因此该服务不知道如何路由请求。

您正在学习的教程不需要

SOAPAction
标头来进行路由。

如果您查看

Add
操作是如何在 WSDL 中指定的,您将在那里找到
SOAPAction
标头的预期值。该服务提供的所有其他操作都相同。

<wsdl:operation name="Add">                                                           
  <soap:operation soapAction="http://tempuri.org/Add" style="document" />             
  <wsdl:input>                                                                        
    <soap:body use="literal" />                                                       
  </wsdl:input>                                                                       
  <wsdl:output>                                                                       
    <soap:body use="literal" />                                                       
  </wsdl:output>                                                                      
</wsdl:operation>

假设您的

SoapConnector
类与 教程 中的类相同,您可以删除
String url
作为
callWebservice
方法的输入,因为它已经通过
client.setDefaultUri("http://www.dneonline.com/calculator.asmx");
bean 中的
SoapConnector
设置。相反,添加
String soapAction
作为输入参数,为您提供以下

public class SOAPConnector extends WebServiceGatewaySupport {

    public Object callWebService(Object request, String soapAction){
        return getWebServiceTemplate().marshalSendAndReceive(url, new SoapActionCallback(soapAction));
    }
}

然后,删除

wsdlurl
作为
soapConnector.callWebService
的输入(无论如何都是错误的),并为您要使用的操作添加
soapHeader
值,这样就只剩下了这个

@Bean
CommandLineRunner lookup(SoapConnector soapConnector) {
    return args -> {
        Integer a = 10;
        Integer b = 20;
        if(args.length>0){
            a = Integer.parseInt(args[0]);
            b = Integer.parseInt(args[1]);
        }

        Add add = new Add();
        add.setIntA(a);
        add.setIntB(b);
        AddResponse addRes = (AddResponse) soapConnector.callWebService(add, "http://tempuri.org/Add");
        System.out.println("Got Response As below ========= : ");
        System.out.println("Added result : "+addRes.getAddResult());
    };
}

当然,如果您想使用

Add
之外的其他操作,您必须调整此解决方案以使其通用。


1
投票

@Misantorp 答案是调用必须传递操作的 SOAP Web 服务的解决方案。 我使用了相同的建议,可以调用 w3School 的温度转换器。

[链接] https://github.com/suhelm/SPRINGBOOT/tree/main/SOAP_temparature_converter


0
投票

使用Spring boot时请注意,使用marshalSendAndReceive时必须提供SoapActionCallback。

如果没有SoapActionCall back,将会抛出“Server did not recognize the value of HTTP Header SOAPAction”。

© www.soinside.com 2019 - 2024. All rights reserved.