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

 

springboot-ws基础框架搭建步骤:

1.用idea创建spring-boot项目,具体的步骤省略;

2.pom添加webservice依赖:  


   org.springframework.boot
   spring-boot-starter-web-services



   wsdl4j
   wsdl4j

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分别表示请求的对象以及响应的结果对象,可以在配置类中指定该文件的位置:


    
        
            
                
            
        
    
    
        
            
                
            
        
    

  指定位置: 

@Bean
	public XsdSchema countriesSchema() {
		return new SimpleXsdSchema(new ClassPathResource("sso.xsd"));
	}

 

5. 在xsd文件上右键操作,根据xsd生成实体类:

   根据需求定制spingboot-spring-webservice的wsdl_第1张图片

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去做一下转发:

    添加依赖:


   org.tuckey
   urlrewritefilter
   4.0.4

   实现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,下面是一个例子




    
        /ws/countries[\?]+wsdl
        /ws/countries.wsdl
    

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 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 it = body.getChildElements();
            while (it.hasNext()) {
                SOAPBodyElement node = it.next();
                node.setPrefix("");
                Iterator 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 interceptors) {
		interceptors.add(new CustomEndpointInterceptor());
	}

 

你可能感兴趣的:(技术博客)