我想使用 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;
}
请帮助我。谢谢。
您面临的问题是 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
之外的其他操作,您必须调整此解决方案以使其通用。
@Misantorp 答案是调用必须传递操作的 SOAP Web 服务的解决方案。 我使用了相同的建议,可以调用 w3School 的温度转换器。
[链接] https://github.com/suhelm/SPRINGBOOT/tree/main/SOAP_temparature_converter
使用Spring boot时请注意,使用marshalSendAndReceive时必须提供SoapActionCallback。
如果没有SoapActionCall back,将会抛出“Server did not recognize the value of HTTP Header SOAPAction”。