实现一个spring webservice服务端二:建立一个能够访问的webservice

文章中,我学习了spring-ws基本的知识,在文章最后我也实现一个简单的项目,访问能够看到wsdl文件,可是我也遇到了一个问题,没法经过soap UI的测试,通过这一段业余时间的学习,这个问题解决。html

这是上一个学习建立的项目的demo演示连接,打开能够看到生成的wsdl。java

遗留问题

上一次学习遇到的问题是,经过生成的wsdl在soap UI测试的时候,生成的请求参数和我要解析的参数不同,我认为没法解析,web

这是soap ui生成的请求数据spring

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://mycompany.com/hr/webservice">
   <soapenv:Header/>
   <soapenv:Body>
      <web:HolidayRequest>
         <!--You may enter the following 2 items in any order-->
         <web:Holiday>
            <!--You may enter the following 2 items in any order-->
            <web:StartDate>2017-05-05</web:StartDate>
            <web:EndDate>2017-05-05</web:EndDate>
         </web:Holiday>
         <web:EmployeeType>
            <!--You may enter the following 3 items in any order-->
            <web:Number>147</web:Number>
            <web:FirstName>156</web:FirstName>
            <web:LastName>457</web:LastName>
         </web:EmployeeType>
      </web:HolidayRequest>
   </soapenv:Body>
</soapenv:Envelope>

后台解析的代码:segmentfault

startDateExpression = xPathFactory.compile("//tns:StartDate", Filters.element(), null, namespace);
            endDateExpression = xPathFactory.compile("//tns:EndDate", Filters.element(), null, namespace);
            firstNameExpression = xPathFactory.compile("//tns:FirstName", Filters.element(), null, namespace);
            lastNameExpression = xPathFactory.compile("//tns:LastName", Filters.element(), null, namespace);

我认为没法解析是由于两边的表达式不同,没法解析对应的字段,但是通过最近一段学习,发现不少wsdl都不是对应,可是仍然能够正常提供服务,因而我无论两边不同的问题,使用soap ui 测试一下,结果确实接收到了请求,测试结果:app

请求进来了
Booking holiday for [Fri May 05 00:00:00 CST 2017-Fri May 05 00:00:00 CST 2017] for [156 457]

从结果上看,数据都取出来。dom

另外这里有个事情须要解释一下:eclipse

xsd修改了,再也不和上一篇文章中的内容彻底同样,这是修改后的文件:webapp

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://mycompany.com/hr/webservice"
           elementFormDefault="qualified" targetNamespace="http://mycompany.com/hr/webservice">

    <xs:element name="HolidayRequest">
        <xs:complexType>
            <xs:all>
                <xs:element name="Holiday" type="tns:Holiday"/>
                <xs:element name="EmployeeType" type="tns:Employee"/>
            </xs:all>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="Holiday">
        <xs:all>
            <xs:element name="StartDate" type="xs:string"/>
            <xs:element name="EndDate" type="xs:string"/>
        </xs:all>
    </xs:complexType>

    <xs:complexType name="Employee">
        <xs:all>
            <xs:element name="Number" type="xs:integer"/>
            <xs:element name="FirstName" type="xs:string"/>
            <xs:element name="LastName" type="xs:string"/>
        </xs:all>
    </xs:complexType>
</xs:schema>

不知道有没有奇怪人我为何,我把前缀改为了【tns】,缘由是这样的,当我把前缀改为【hr】时:ide

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:hr="http://mycompany.com/hr/webservice"
           elementFormDefault="qualified" targetNamespace="http://mycompany.com/hr/webservice">

    <xs:element name="HolidayRequest">
        <xs:complexType>
            <xs:all>
                <xs:element name="Holiday" type="hr:Holiday"/>
                <xs:element name="EmployeeType" type="hr:Employee"/>
            </xs:all>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="Holiday">
        <xs:all>
            <xs:element name="StartDate" type="xs:string"/>
            <xs:element name="EndDate" type="xs:string"/>
        </xs:all>
    </xs:complexType>

    <xs:complexType name="Employee">
        <xs:all>
            <xs:element name="Number" type="xs:integer"/>
            <xs:element name="FirstName" type="xs:string"/>
            <xs:element name="LastName" type="xs:string"/>
        </xs:all>
    </xs:complexType>
</xs:schema>

而后重启项目生成wsdl,结果以下:

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://mycompany.com/hr/webservice" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://mycompany.com/hr/webservice" targetNamespace="http://mycompany.com/hr/webservice">
<wsdl:types>
<xs:schema xmlns:hr="http://mycompany.com/hr/webservice" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://mycompany.com/hr/webservice">
<xs:element name="HolidayRequest">
<xs:complexType>
<xs:all>
<xs:element name="Holiday" type="hr:Holiday"/>
<xs:element name="EmployeeType" type="hr:Employee"/>
</xs:all>
</xs:complexType>
</xs:element>
<xs:complexType name="Holiday">

还有不少

能够看到,生成的wsdl头部中仍然是:

xmlns:tns="http://mycompany.com/hr/webservice" targetNamespace="http://mycompany.com/hr/webservice"

我查看了一下源码,在设置namespace的代码中:

@Override
    public void afterPropertiesSet() throws WSDLException {
        Assert.notNull(getTargetNamespace(), "'targetNamespace' is required");
        WSDLFactory wsdlFactory = WSDLFactory.newInstance();
        Definition definition = wsdlFactory.newDefinition();
        definition.setTargetNamespace(getTargetNamespace());
        definition.addNamespace(TARGET_NAMESPACE_PREFIX, getTargetNamespace());
        if (importsProvider != null) {
            importsProvider.addImports(definition);
        }
        if (typesProvider != null) {
            typesProvider.addTypes(definition);
        }
        if (messagesProvider != null) {
            messagesProvider.addMessages(definition);
        }
        if (portTypesProvider != null) {
            portTypesProvider.addPortTypes(definition);
        }
        if (bindingsProvider != null) {
            bindingsProvider.addBindings(definition);
        }
        if (servicesProvider != null) {
            servicesProvider.addServices(definition);
        }
        setDefinition(definition);
    }

其中使用一个名为TARGET_NAMESPACE_PREFIX的常量做为前缀,在类中定义以下:

public static final String TARGET_NAMESPACE_PREFIX = "tns";

也就是说,若是你采用的是生成wsdl,而不是本身写的wsdl的话,本身定义的命名空间都是tns前缀,
因此,我也就改为tns了,反正写什么都没什么用,最终都是tns。

实现静态的wsdl访问

spring-ws推荐第一次生成以后,采用静态配置的方式访问wsdl文件,因而新建了一个webservicelearn2项目。

把上一篇文章生成的wsdl文件另存为orders.wsdl,放到web-inf下面,web.xml没有改,pom.xml文件也没有修改,只有spring-ws配置文件改为了下面这个样子:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oxm="http://www.springframework.org/schema/oxm"
       xmlns:sws="http://www.springframework.org/schema/web-services"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/oxm
       http://www.springframework.org/schema/oxm/spring-oxm.xsd
       http://www.springframework.org/schema/web-services
       http://www.springframework.org/schema/web-services/web-services.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
    
    <sws:static-wsdl id="orders" location="/WEB-INF/orders.wsdl"/>

</beans>

按照文档说明,此时访问http://localhost:8089/webserv...就能够访问了。

在这期间,项目clean了一下,从新下载jar包,而后项目就一直出错,启动项目时老是报500错误:

java.lang.ClassNotFoundException: javax.wsdl.extensions.ExtensibilityElement
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at org.eclipse.jetty.webapp.WebAppClassLoader.findClass(WebAppClassLoader.java:550)
    at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:475)
    at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:428)
    at org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition.<init>(DefaultWsdl11Definition.java:56)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)

我知道这是缺jar,缺的是wsdlj jar包,可是spring-ws官方参考文档上说并不须要这个jar,这是官方参考文档
其中关于依赖的配置以下:

<dependencies>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>spring-ws-core</artifactId>
        <version></version>
    </dependency>
    <dependency>
        <groupId>jdom</groupId>
        <artifactId>jdom</artifactId>
        <version>2.0.1</version>
    </dependency>
    <dependency>
        <groupId>jaxen</groupId>
        <artifactId>jaxen</artifactId>
        <version>1.1</version>
    </dependency>
</dependencies>

我一直觉得,个人项目哪里出错了,由于开始的项目是对的,只不太重新下载jar就出错了,确定是我哪里改错了,就这个问题,还咨询了jetbrains idea的技术才支持,最后才发现,spring-ws-core的版本问题形成的;

这是2.1.4版本:
wsdlj jar包必定会下载

这是最新版本:
这是可选下载

也就是说新版本,须要在pom.xml配置wsdlj才能使用,至于为何刚开始是对的,我也没想明白。

到此为止,动态生成也好,静态wsdl也好,都能正常访问,有些东西,看着简单,本身搞起来,老是出错,因此仍是要多动手。

相关文章
相关标签/搜索