欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

根据需求定制spingboot-spring-webservice的wsdl

程序员文章站 2022-04-28 11:59:34
...

 

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生成实体类:

   根据需求定制spingboot-spring-webservice的wsdl

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-ENVsoap:

   添加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());
	}