根据需求定制spingboot-spring-webservice的wsdl
springboot-ws基础框架搭建步骤:
1.用idea创建spring-boot项目,具体的步骤省略;
2.pom添加webservice依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
3.添加配置类,这是springboot-ws的核心配置类:
@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 = "sso")
public Wsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("SSOWebServiceSoap");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setTargetNamespace("http://tempuri.org/");
wsdl11Definition.setSchema(countriesSchema);
wsdl11Definition.setCreateSoap11Binding(true);
wsdl11Definition.setCreateSoap12Binding(true);
Properties soapActions = new Properties();
soapActions.setProperty("ApplicationRegister", "http://tempuri.org/ApplicationRegister");
soapActions.setProperty("LoginVerify", "http://tempuri.org/LoginVerify");
wsdl11Definition.setSoapActions(soapActions);
return wsdl11Definition;
}
@Bean
public XsdSchema countriesSchema() {
return new SimpleXsdSchema(new ClassPathResource("sso.xsd"));
}
}
4. 在resource文件夹下创建xsd文件如下,其中ApplicationRegister和ApplicationRegisterResponse分别表示请求的对象以及响应的结果对象,可以在配置类中指定该文件的位置:
<s:schema xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://tempuri.org/"
targetNamespace="http://tempuri.org/" elementFormDefault="qualified">
<s:element name="ApplicationRegister">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="inputdata" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="ApplicationRegisterResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="ApplicationRegisterResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
指定位置:
@Bean
public XsdSchema countriesSchema() {
return new SimpleXsdSchema(new ClassPathResource("sso.xsd"));
}
5. 在xsd文件上右键操作,根据xsd生成实体类:
6. 创建Endpoint类,Endpoint类主要用于描述webservice提供的方法:
@Endpoint
public class SsoEndpointApi {
private static final String NAMESPACE_URI = "http://tempuri.org/";
private SsoEndpointService ssoEndpointService;
/*
*方法说明:系统注册
* */
@PayloadRoot(namespace = NAMESPACE_URI, localPart = "ApplicationRegister")
@ResponsePayload
public ApplicationRegisterResponse applicationRegister(@RequestPayload ApplicationRegister applicationRegister) {
return ssoEndpointService.applicationRegister(applicationRegister);
}
转换注意事项:
1. 将url地址的风格统一,spring-ws发布的webservice默认url是http://xx:xx/xxx.wsdl
,不符合常规的http://xx:xx/xxx?wsdl
格式,我们可以利用urlrewritefilter
去做一下转发:
添加依赖:
<dependency>
<groupId>org.tuckey</groupId>
<artifactId>urlrewritefilter</artifactId>
<version>4.0.4</version>
</dependency>
实现UrlRewriteFilter:
package com.winning.webService.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.tuckey.web.filters.urlrewrite.Conf;
import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import java.io.IOException;
/**
* @author zhanghong
* @since 2018-08-17 16:01
**/
@Component
public class WsdlUrlRewriteFilter extends UrlRewriteFilter {
private static final String CONFIG_LOCATION = "classpath:/urlrewrite.xml";
@Value(CONFIG_LOCATION)
private Resource resource;
@Override
protected void loadUrlRewriter(FilterConfig filterConfig) throws ServletException {
try {
Conf conf = new Conf(filterConfig.getServletContext(), resource.getInputStream(), resource.getFilename(), "");
checkConf(conf);
} catch (IOException ex) {
throw new ServletException("无法读取配置文件: " + CONFIG_LOCATION, ex);
}
}
}
配置转发规则
根据上面的CONFIG_LOCATION
指明的位置,新建配置文件urlrewrite.xml
,下面是一个例子
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"
"http://tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite use-query-string="true">
<rule>
<from>/ws/countries[\?]+wsdl</from>
<to>/ws/countries.wsdl</to>
</rule>
</urlrewrite>
2. springboot-ws 生成wsdl时候,所有的请求默认带上后缀名Request, 所有的响应默认带上后缀名Response,如果不带上,则识别不了,但是如果之前的cxf框架请求后缀不带Request,那么改造的时候需要如下的配置:
自定义MyWsdl11Definition以及依赖的其他相关类:
public class MyWsdl11Definition implements Wsdl11Definition, InitializingBean {
private final InliningXsdSchemaTypesProvider typesProvider = new InliningXsdSchemaTypesProvider();
private final SuffixBasedMessagesProvider messagesProvider = new MySuffixBasedMessagesProvider();
private final SuffixBasedPortTypesProvider portTypesProvider = new MySuffixBasedPortTypesProvider();
private final SoapProvider soapProvider = new SoapProvider();
private final ProviderBasedWsdl4jDefinition delegate = new ProviderBasedWsdl4jDefinition();
private String serviceName;
public MyWsdl11Definition() {
delegate.setTypesProvider(typesProvider);
delegate.setMessagesProvider(messagesProvider);
delegate.setPortTypesProvider(portTypesProvider);
delegate.setBindingsProvider(soapProvider);
delegate.setServicesProvider(soapProvider);
}
public void setTargetNamespace(String targetNamespace) {
delegate.setTargetNamespace(targetNamespace);
}
public void setSchema(XsdSchema schema) {
typesProvider.setSchema(schema);
}
public void setSchemaCollection(XsdSchemaCollection schemaCollection) {
typesProvider.setSchemaCollection(schemaCollection);
}
public void setPortTypeName(String portTypeName) {
portTypesProvider.setPortTypeName(portTypeName);
}
public void setRequestSuffix(String requestSuffix) {
portTypesProvider.setRequestSuffix(requestSuffix);
messagesProvider.setRequestSuffix(requestSuffix);
}
public void setResponseSuffix(String responseSuffix) {
portTypesProvider.setResponseSuffix(responseSuffix);
messagesProvider.setResponseSuffix(responseSuffix);
}
public void setFaultSuffix(String faultSuffix) {
portTypesProvider.setFaultSuffix(faultSuffix);
messagesProvider.setFaultSuffix(faultSuffix);
}
public void setCreateSoap11Binding(boolean createSoap11Binding) {
soapProvider.setCreateSoap11Binding(createSoap11Binding);
}
public void setCreateSoap12Binding(boolean createSoap12Binding) {
soapProvider.setCreateSoap12Binding(createSoap12Binding);
}
public void setSoapActions(Properties soapActions) {
soapProvider.setSoapActions(soapActions);
}
public void setTransportUri(String transportUri) {
soapProvider.setTransportUri(transportUri);
}
public void setLocationUri(String locationUri) {
soapProvider.setLocationUri(locationUri);
}
public void setServiceName(String serviceName) {
soapProvider.setServiceName(serviceName);
this.serviceName = serviceName;
}
@Override
public void afterPropertiesSet() throws Exception {
if (!StringUtils.hasText(delegate.getTargetNamespace()) && typesProvider.getSchemaCollection() != null &&
typesProvider.getSchemaCollection().getXsdSchemas().length > 0) {
XsdSchema schema = typesProvider.getSchemaCollection().getXsdSchemas()[0];
setTargetNamespace(schema.getTargetNamespace());
}
if (!StringUtils.hasText(serviceName) && StringUtils.hasText(portTypesProvider.getPortTypeName())) {
soapProvider.setServiceName(portTypesProvider.getPortTypeName() + "Service");
}
delegate.afterPropertiesSet();
}
@Override
public Source getSource() {
return delegate.getSource();
}
}
public class MySuffixBasedMessagesProvider extends SuffixBasedMessagesProvider {
protected String requestSuffix = DEFAULT_REQUEST_SUFFIX;
public String getRequestSuffix() {
return this.requestSuffix;
}
public void setRequestSuffix(String requestSuffix) {
this.requestSuffix = requestSuffix;
}
@Override
protected boolean isMessageElement(Element element) {
if (isMessageElement0(element)) {
String elementName = getElementName(element);
Assert.hasText(elementName, "Element has no name");
return elementName.endsWith(getResponseSuffix())
|| (getRequestSuffix().isEmpty() ? true : elementName.endsWith(getRequestSuffix()))
|| elementName.endsWith(getFaultSuffix());
}
return false;
}
protected boolean isMessageElement0(Element element) {
return "element".equals(element.getLocalName())
&& "http://www.w3.org/2001/XMLSchema".equals(element.getNamespaceURI());
}
}
public class MySuffixBasedPortTypesProvider extends SuffixBasedPortTypesProvider {
private String requestSuffix = DEFAULT_REQUEST_SUFFIX;
public String getRequestSuffix() {
return requestSuffix;
}
public void setRequestSuffix(String requestSuffix) {
this.requestSuffix = requestSuffix;
}
@Override
protected String getOperationName(Message message) {
String messageName = getMessageName(message);
String result = null;
if (messageName != null) {
if (messageName.endsWith(getResponseSuffix())) {
result = messageName.substring(0, messageName.length() - getResponseSuffix().length());
} else if (messageName.endsWith(getFaultSuffix())) {
result = messageName.substring(0, messageName.length() - getFaultSuffix().length());
} else if (messageName.endsWith(getRequestSuffix())) {
result = messageName.substring(0, messageName.length() - getRequestSuffix().length());
}
}
return result;
}
@Override
protected boolean isInputMessage(Message message) {
String messageName = getMessageName(message);
return messageName != null && !messageName.endsWith(getResponseSuffix());
}
private String getMessageName(Message message) {
return message.getQName().getLocalPart();
}
}
在配置类WebServiceConfig中添加配置:
@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 = "sso")
public Wsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
//DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
MyWsdl11Definition wsdl11Definition = new MyWsdl11Definition();
wsdl11Definition.setPortTypeName("SSOWebServiceSoap");
wsdl11Definition.setLocationUri("/ws");
wsdl11Definition.setRequestSuffix("");
wsdl11Definition.setTargetNamespace("http://tempuri.org/");
wsdl11Definition.setSchema(countriesSchema);
wsdl11Definition.setCreateSoap11Binding(true);
wsdl11Definition.setCreateSoap12Binding(true);
Properties soapActions = new Properties();
soapActions.setProperty("ApplicationRegister", "http://tempuri.org/ApplicationRegister");
soapActions.setProperty("LoginVerify", "http://tempuri.org/LoginVerify");
wsdl11Definition.setSoapActions(soapActions);
return wsdl11Definition;
}
@Bean
public XsdSchema countriesSchema() {
return new SimpleXsdSchema(new ClassPathResource("sso.xsd"));
}
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(new CustomEndpointInterceptor());
}
}
3. 将名称空间前缀更改SOAP-ENV
为soap:
添加
CustomEndpointInterceptor
public class CustomEndpointInterceptor extends EndpointInterceptorAdapter {
private static final String DEFAULT_NS = "xmlns:SOAP-ENV";
private static final String SOAP_ENV_NAMESPACE = "http://schemas.xmlsoap.org/soap/envelope/";
private static final String PREFERRED_PREFIX = "soap";
private static final String HEADER_LOCAL_NAME = "Header";
private static final String BODY_LOCAL_NAME = "Body";
private static final String FAULT_LOCAL_NAME = "Fault";
@Override
public boolean handleResponse(MessageContext messageContext, Object endpoint) throws Exception {
SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
alterSoapEnvelope(soapResponse);
return super.handleResponse(messageContext, endpoint);
}
@Override
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
SaajSoapMessage soapResponse = (SaajSoapMessage) messageContext.getResponse();
alterSoapEnvelope(soapResponse);
return super.handleFault(messageContext, endpoint);
}
private void alterSoapEnvelope(SaajSoapMessage soapResponse) {
try {
SOAPMessage soapMessage = soapResponse.getSaajMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope envelope = soapPart.getEnvelope();
SOAPHeader header = soapMessage.getSOAPHeader();
SOAPBody body = soapMessage.getSOAPBody();
SOAPFault fault = body.getFault();
envelope.removeNamespaceDeclaration(envelope.getPrefix());
envelope.addNamespaceDeclaration(PREFERRED_PREFIX, SOAP_ENV_NAMESPACE);
envelope.setPrefix(PREFERRED_PREFIX);
header.setPrefix(PREFERRED_PREFIX);
body.setPrefix(PREFERRED_PREFIX);
if (fault != null) {
fault.setPrefix(PREFERRED_PREFIX);
}
Iterator<SOAPBodyElement> it = body.getChildElements();
while (it.hasNext()) {
SOAPBodyElement node = it.next();
node.setPrefix("");
Iterator<SOAPBodyElement> it2 = node.getChildElements();
while (it2.hasNext()) {
SOAPBodyElement node2 = it2.next();
node2.setPrefix("");
}
}
soapMessage.saveChanges();
} catch (SOAPException e) {
e.printStackTrace();
}
}
}
在WebServiceConfig中添加该拦截器:
@Override
public void addInterceptors(List<EndpointInterceptor> interceptors) {
interceptors.add(new CustomEndpointInterceptor());
}
推荐阅读
-
硬件选购 根据你的不同需求选择电脑音箱
-
针对根据客户需求进行产品配制的情况的简单策略
-
fiddler抓包小技巧之自动保存抓包数据的实现方法分析【可根据需求过滤】
-
根据公司需求写的一个linux 巡检小脚本
-
iOS14 隐私适配:【定位授权新增了精确和模糊定位 可根据不同的需求设置不同的定位精确度】1、向用户申请临时开启一次精确位置权限的方案(不同场景可定义不同purposeKey)2、高德定位SDK适配
-
php-根据甲方提供的关于项目需求的文档,乙方对项目的基本情况有了较为详细的了解
-
帖,怎么根据设备显示定制的网页_html/css_WEB-ITnose
-
帖,怎么根据设备显示定制的网页_html/css_WEB-ITnose
-
根据需求定制spingboot-spring-webservice的wsdl
-
硬件选购 根据你的不同需求选择电脑音箱