如何使用 Spring-WS 发布具有动态 soap:address 位置的 WSDL 定义
How to publish a WSDL definition with dynamic soap:address location using Spring-WS
我想根据保存它们的环境更改 WSDL 的 <soap:address location="..."/>
。例如:
发展:<soap:address location="https://development.xxx.yyy.zz/abc/ws/"/>
测试:<soap:address location="https://testing.xxx.yyy.zz/abc/ws/"/>
生产:<soap:address location="https://production.xxx.yyy.zz/abc/ws/"/>
如果您想使用 WSDL 基础文件并根据环境更改 SOAP 地址位置属性,请使用此 class:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition;
import org.springframework.ws.wsdl.wsdl11.Wsdl11Definition;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class DynamicUrlWsdlDefinition implements Wsdl11Definition, InitializingBean {
private static final String SOAP_ADDRESS_LOCATION_XPATH_EXPRESSION = "/definitions/service/port/address/@location";
private static final String SOAP_ADDRESS_LOCATION_URI_PART_1 = "https://";
private static final String SOAP_ADDRESS_LOCATION_URI_PART_3 = ".xxx.yyy.zz/abc/ws/";
private String wsEnvironment;
private SimpleWsdl11Definition delegate;
public DynamicUrlWsdlDefinition() {
this.setDelegate(new SimpleWsdl11Definition());
}
@Override
public Source getSource() {
try {
final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
final DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
final Document document = documentBuilder.parse(((SAXSource) this.getDelegate().getSource()).getInputSource());
final XPath xPath = XPathFactory.newInstance().newXPath();
final Node locationAttributeNode = (Node) xPath.compile(SOAP_ADDRESS_LOCATION_XPATH_EXPRESSION)
.evaluate(document, XPathConstants.NODE);
locationAttributeNode.setTextContent(SOAP_ADDRESS_LOCATION_URI_PART_1 + this.getWsEnvironment() + SOAP_ADDRESS_LOCATION_URI_PART_3);
return new DOMSource(document);
} catch (Exception e) {
return this.getDelegate().getSource();
}
}
private String getWsEnvironment() {
if (!StringUtils.hasText(wsEnvironment) || "${ws.environment}".equals(wsEnvironment)) {
this.setWsEnvironment("NO_DEFINED");
}
return wsEnvironment;
}
@Override
public void afterPropertiesSet() throws Exception {
this.getDelegate().afterPropertiesSet();
}
public void setWsdl(final Resource wsdlResource) {
this.getDelegate().setWsdl(wsdlResource);
}
private SimpleWsdl11Definition getDelegate() {
return delegate;
}
private void setDelegate(final SimpleWsdl11Definition delegate) {
this.delegate = delegate;
}
public void setWsEnvironment(final String wsEnvironment) {
this.wsEnvironment = wsEnvironment;
}
}
并声明这个 Spring bean:
<bean id="pingoServiceWsdl" class="DynamicUrlWsdlDefinition">
<property name="wsdl" value="classpath:/pingoService.wsdl"/>
<property name="wsEnvironment" value="${ws.environment}"/>
</bean>
我只是有同样的要求,随着时间的推移,我对给定的解决方案不满意。实际上,在我的项目中,我使用的是 spring-boot 2.2.5.RELEASE 并且我管理设置位置 URI 如下:
@Bean(name = "MyServiceWsdl")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema)
{
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("MyServiceSoapBinding");
wsdl11Definition.setTargetNamespace("https://www.kleenxcoder.com/xml/myproject");
wsdl11Definition.setSchema(countriesSchema);
wsdl11Definition.setLocationUri("xxx.xxx.xxxx:8080/service/MyService");
return wsdl11Definition;
}
我想根据保存它们的环境更改 WSDL 的 <soap:address location="..."/>
。例如:
发展:<soap:address location="https://development.xxx.yyy.zz/abc/ws/"/>
测试:<soap:address location="https://testing.xxx.yyy.zz/abc/ws/"/>
生产:<soap:address location="https://production.xxx.yyy.zz/abc/ws/"/>
如果您想使用 WSDL 基础文件并根据环境更改 SOAP 地址位置属性,请使用此 class:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.StringUtils;
import org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition;
import org.springframework.ws.wsdl.wsdl11.Wsdl11Definition;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
public class DynamicUrlWsdlDefinition implements Wsdl11Definition, InitializingBean {
private static final String SOAP_ADDRESS_LOCATION_XPATH_EXPRESSION = "/definitions/service/port/address/@location";
private static final String SOAP_ADDRESS_LOCATION_URI_PART_1 = "https://";
private static final String SOAP_ADDRESS_LOCATION_URI_PART_3 = ".xxx.yyy.zz/abc/ws/";
private String wsEnvironment;
private SimpleWsdl11Definition delegate;
public DynamicUrlWsdlDefinition() {
this.setDelegate(new SimpleWsdl11Definition());
}
@Override
public Source getSource() {
try {
final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
final DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
final Document document = documentBuilder.parse(((SAXSource) this.getDelegate().getSource()).getInputSource());
final XPath xPath = XPathFactory.newInstance().newXPath();
final Node locationAttributeNode = (Node) xPath.compile(SOAP_ADDRESS_LOCATION_XPATH_EXPRESSION)
.evaluate(document, XPathConstants.NODE);
locationAttributeNode.setTextContent(SOAP_ADDRESS_LOCATION_URI_PART_1 + this.getWsEnvironment() + SOAP_ADDRESS_LOCATION_URI_PART_3);
return new DOMSource(document);
} catch (Exception e) {
return this.getDelegate().getSource();
}
}
private String getWsEnvironment() {
if (!StringUtils.hasText(wsEnvironment) || "${ws.environment}".equals(wsEnvironment)) {
this.setWsEnvironment("NO_DEFINED");
}
return wsEnvironment;
}
@Override
public void afterPropertiesSet() throws Exception {
this.getDelegate().afterPropertiesSet();
}
public void setWsdl(final Resource wsdlResource) {
this.getDelegate().setWsdl(wsdlResource);
}
private SimpleWsdl11Definition getDelegate() {
return delegate;
}
private void setDelegate(final SimpleWsdl11Definition delegate) {
this.delegate = delegate;
}
public void setWsEnvironment(final String wsEnvironment) {
this.wsEnvironment = wsEnvironment;
}
}
并声明这个 Spring bean:
<bean id="pingoServiceWsdl" class="DynamicUrlWsdlDefinition">
<property name="wsdl" value="classpath:/pingoService.wsdl"/>
<property name="wsEnvironment" value="${ws.environment}"/>
</bean>
我只是有同样的要求,随着时间的推移,我对给定的解决方案不满意。实际上,在我的项目中,我使用的是 spring-boot 2.2.5.RELEASE 并且我管理设置位置 URI 如下:
@Bean(name = "MyServiceWsdl")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema)
{
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("MyServiceSoapBinding");
wsdl11Definition.setTargetNamespace("https://www.kleenxcoder.com/xml/myproject");
wsdl11Definition.setSchema(countriesSchema);
wsdl11Definition.setLocationUri("xxx.xxx.xxxx:8080/service/MyService");
return wsdl11Definition;
}