![](/img/trans.png)
[英]Support both SOAP 1.1 and SOAP 1.2 messages in Spring-WS
[英]spring-ws SOAP — Missing Messages and Binding
我想使用 spring-ws 實現我自己的 SOAP webservcie。 我寫了一個xsd,從中生成了一個Java class。
這是我的網絡服務配置:
@EnableWs
@Configuration
public class WebServiceConfig extends WsConfigurerAdapter {
@Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
@Bean(name = "foo")
public DefaultWsdl11Definition defaultWsdl11DefinitionFoo(){
DefaultWsdl11Definition defaultWsdl11Definition = new DefaultWsdl11Definition();
defaultWsdl11Definition.setPortTypeName("FooPort");
defaultWsdl11Definition.setLocationUri("/ws");
defaultWsdl11Definition.setTargetNamespace("foo");
defaultWsdl11Definition.setSchema(fooSchema());
return defaultWsdl11Definition;
}
@Bean
public XsdSchema fooSchema() {
return new SimpleXsdSchema(new ClassPathResource("foo.xsd"));
}
這是我的 xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="foo" elementFormDefault="qualified">
<xs:complexType name="Foobject">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="population" type="xs:int"/>
</xs:sequence>
</xs:complexType>
這是我的終點:
@Endpoint
public class Fooendpoint {
private static final String NAMESPACE_URI = "foo";
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "bar")
@ResponsePayload
public Foobject getCountry(@RequestPayload Foobject request) {
return new Foobject("string", 0);
}}
最后這是自動生成的 WSDL 網絡服務發布在http://localhost:8080/ws/foo.wsdl
<wsdl:definitions targetNamespace="foo" xmlns:sch="foo" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="foo" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema elementFormDefault="qualified" targetNamespace="foo" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="Foobject">
<xs:sequence>
<xs:element name="name" type="xs:string"/>
<xs:element name="population" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:portType name="FooPort"/>
<wsdl:binding name="FooPortSoap11" type="tns:FooPort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
</wsdl:binding>
<wsdl:service name="FooPortService">
<wsdl:port binding="tns:FooPortSoap11" name="FooPortSoap11">
<soap:address location="http://localhost:8080/ws"/>
</wsdl:port>
</wsdl:service>
在 WSDL 中沒有消息和操作。 我錯過了什么?
更新:我修改了 XSD:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="foo" elementFormDefault="qualified" xmlns:tns="foo">
<xs:element name="fooRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="foo" type="tns:Foobject"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="fooResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="string" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Foobject">
<xs:sequence>
<xs:element name="string" type="xs:string"/>
<xs:element name="int" type="xs:int"/>
</xs:sequence>
</xs:complexType>
WSDL 現在有消息和綁定:
<wsdl:definitions targetNamespace="foo" xmlns:sch="foo" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="foo" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<xs:schema elementFormDefault="qualified" targetNamespace="foo" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="fooRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="foo" type="tns:Foobject"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="fooResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="string" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Foobject">
<xs:sequence>
<xs:element name="string" type="xs:string"/>
<xs:element name="int" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="fooResponse">
<wsdl:part element="tns:fooResponse" name="fooResponse"/>
</wsdl:message>
<wsdl:message name="fooRequest">
<wsdl:part element="tns:fooRequest" name="fooRequest"/>
</wsdl:message>
<wsdl:portType name="FooPort">
<wsdl:operation name="foo">
<wsdl:input message="tns:fooRequest" name="fooRequest"/>
<wsdl:output message="tns:fooResponse" name="fooResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="FooPortSoap11" type="tns:FooPort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="foo">
<soap:operation soapAction=""/>
<wsdl:input name="fooRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="fooResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="FooPortService">
<wsdl:port binding="tns:FooPortSoap11" name="FooPortSoap11">
<soap:address location="http://localhost:8080/ws"/>
</wsdl:port>
</wsdl:service>
但是當我通過 SoapUI 發送請求時,找不到端點:
No endpoint mapping found for [SaajSoapMessage {foo}fooRequest]
對於任何可能需要“解決方案”的人來說,這里有一些(真正的)解決問題的技巧。 問題出在 spring 中的參數匹配算法中。它檢查“parameter instanceof org.w3c.Element”。 如果不是,則沒有匹配項並且不會調用該方法。
順便說一句:如果有人有更好的解決方案,請告訴我。 它一定在某個地方。
所以以防萬一,你有一個:
// No adapter for endpoint [public <CorrectType> <CorrectMethod>(<CorrectArgumentType>)]: Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?
您可以將方法更改為:
public org.w3c.Element correctMethod(org.w3c.Element parameter) {...
現在該方法被調用,您可以對參數進行解組並使用 JAXBContext 對結果進行編組。
對於封送處理,您可以使用這樣的方法:
private <T> T unmarshalParameter(Element element, Class<? extends T> targetClass) {
JAXBContext context = null;
try {
context = JAXBContext.newInstance(targetClass);
return context.createUnmarshaller().unmarshal(element, targetClass).getValue();
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
結果的編組可以像這樣完成:
private <T> Element marshal(T response, String elementName) {
JAXBContext jaxbContext = null;
try {
Document document =
DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
jaxbContext = JAXBContext.newInstance(response.getClass());
DOMResult res = new DOMResult(document);
JAXBElement<?> jaxbElement =
new JAXBElement<>( new QName(NAMESPACE_URI,elementName),
(Class<T>)response.getClass(),
response);
jaxbContext.createMarshaller().marshal(jaxbElement,res);
Element e = (Element)document.getDocumentElement();
return e;
} catch (JAXBException | ParserConfigurationException e) {
throw new RuntimeException(e);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.