最近研究了一下spring webservice整合,由于第一次做这个,整合期间遇到了不少问题,在网上查找了好久也没找到完整实现的server和client的demo,有的问题折腾了我好几天,看到spring的官网里面有人提相同的问题,但是都没人给出解决方案,所以就只能慢慢摸索,经过艰辛的探索,终于实现了一个完整的demo,在这里我整理了一下分享给大家,希望能帮助大家解决这方面遇到的问题,由于在下才疏学浅,有的地方可能写得不是很合理,希望大家提出来探讨一下,互相提高。我会尽量把自己遇到的问题体现出来,然后一一解决,废话不多说,开始干活:




第一部分实现spring webservice服务端的开发与部署。




1. 创建一个maven的web项目,完成一些准备工作。

1.1 在pom.xml中加入相关jar包,如下:



1. <project xmlns="http:///POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
2. xsi:schemaLocation="http:///POM/4.0.0 http:///maven-v4_0_0.xsd">  
3. <modelVersion>4.0.0</modelVersion>  
4. <groupId>com.zdsoft.webservice</groupId>  
5. <artifactId>spring-webservice-server</artifactId>  
6. <packaging>war</packaging>  
7. <version>0.0.1-SNAPSHOT</version>  
8. <name>spring-webservice-server Maven Webapp</name>  
9. <url>http://</url>  
10. <dependencies>  
11. <dependency>  
12. <groupId></groupId>  
13. <artifactId>spring-ws-core</artifactId>  
14. <version>2.1.4.RELEASE</version>  
15. </dependency>  
16.   
17. <dependency>  
18. <groupId>log4j</groupId>  
19. <artifactId>log4j</artifactId>  
20. <version>1.2.17</version>  
21. </dependency>  
22. </dependencies>  
23. <build>  
24. <finalName>spring-webservice-server</finalName>  
25. </build>  
26. </project>


1.2 创建log4j.xml文件,配置log4j打印信息,如下:


1. <?xml version="1.0" encoding="UTF-8"?>  
2. <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">  
3. <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"  debug="true">  
4. <appender name="console" class="org.apache.log4j.ConsoleAppender">  
5. <param name="Target" value="System.out" />  
6. <param name="Threshold" value="ALL" />  
7. <layout class="org.apache.log4j.PatternLayout">  
8. <param name="ConversionPattern" value="%d{HH:mm:ss:SSS} %p %l>> %m%n" />  
9. </layout>  
10. </appender>  
11.   
12. <root>  
13. <priority value="ALL" />  
14. <appender-ref ref="console" />  
15. </root>  
16. </log4j:configuration>


1.3 为了能让我们的webservice能和web的容器集成到一起,需要在web.xml里面做一些配置,如下:


1. <!DOCTYPE web-app PUBLIC  
2.  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"  
3. >  
4.   
5. <web-app>  
6. <display-name>Archetype Created Web Application</display-name>  
7.       
8. <servlet>  
9. <servlet-name>spring-ws</servlet-name>  
10. <servlet-class>.transport.http.MessageDispatcherServlet</servlet-class>  
11. <!--Spring-WS配置文件的位置,默认寻找[servlet-name]-servlet.xml文件 -->  
12. <init-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/spring-ws-config.xml</param-value>   
13. </init-param> -->  
14. <init-param>  
15. <param-name>transformWsdlLocations</param-name>  
16. <param-value>true</param-value>  
17. </init-param>  
18. <load-on-startup>1</load-on-startup>  
19. </servlet>  
20. <servlet-mapping>  
21. <servlet-name>spring-ws</servlet-name>  
22. <url-pattern>/service/*</url-pattern>  
23. </servlet-mapping>  
24. <servlet-mapping>  
25. <servlet-name>spring-ws</servlet-name>  
26. <url-pattern>*.wsdl</url-pattern>  
27. </servlet-mapping>  
28. </web-app>

解释上面的配置:

transformWsdlLocations设置成true,就是说当你改变了项目名称或者端口号,你的服务还是可以正常访问的(但是如果你改变了WSDL的访问路径,发布服务的代码也要随之更改的)。



2. 开发webservice核心部分。

2.1 遵循契约优先的方式,我们先完成wsdl文件的编写,文件名:UserService.wsdl,放在WEB-INF/wsdl/下面,内容如下:



1. <span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;"></span><pre code_snippet_id="322977" snippet_file_name="blog_20140502_4_3969132" name="code" class="html"><?xml version="1.0" encoding="UTF-8" standalone="no"?>  
2. <wsdl:definitions   
3. targetNamespace="http://webservice.zdsoft.com/namespace/userservice"  
4. xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"  
5. xmlns:tns="http://webservice.zdsoft.com/namespace/userservice"   
6. xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"  
7. xmlns:xsd="http://www.w3.org/2001/XMLSchema"   
8. name="UserService">  
9. <wsdl:types>  
10. <xsd:schema targetNamespace="http://webservice.zdsoft.com/namespace/userservice">  
11. <!-- xsd part start -->  
12. <xsd:element name="login" type="tns:login" />  
13. <xsd:element name="loginResponse" type="tns:loginResponse" />  
14. <xsd:element name="getUser" type="tns:getUser" />  
15. <xsd:element name="getUserResponse" type="tns:getUserResponse" />  
16. <xsd:complexType name="login">  
17. <xsd:sequence>  
18. <xsd:element name="username" type="xsd:string" />  
19. <xsd:element name="password" type="xsd:string" />  
20. </xsd:sequence>  
21. </xsd:complexType>  
22. <xsd:complexType name="loginResponse">  
23. <xsd:sequence>  
24. <xsd:element name="info" type="xsd:string" />  
25. </xsd:sequence>  
26. </xsd:complexType>  
27.               
28. <xsd:complexType name="getUser">  
29. <xsd:sequence>  
30. <xsd:element name="username" type="xsd:string" />  
31. </xsd:sequence>  
32. </xsd:complexType>  
33. <xsd:complexType name="getUserResponse">  
34. <xsd:sequence>  
35. <xsd:element name="user" type="tns:user" />  
36. </xsd:sequence>  
37. </xsd:complexType>  
38. <xsd:complexType name="user">  
39. <xsd:sequence>  
40. <xsd:element name="username" type="xsd:string" />  
41. <xsd:element name="password" type="xsd:string" />  
42. <xsd:element name="nickname" type="xsd:string" />  
43. </xsd:sequence>  
44. </xsd:complexType>  
45. <!-- xsd part end -->  
46. </xsd:schema>  
47. </wsdl:types>  
48. <wsdl:message name="login">  
49. <wsdl:part element="tns:login" name="parameters" />  
50. </wsdl:message>  
51. <wsdl:message name="loginResponse">  
52. <wsdl:part element="tns:loginResponse" name="parameters" />  
53. </wsdl:message>  
54. <wsdl:message name="getUser">  
55. <wsdl:part element="tns:getUser" name="parameters" />  
56. </wsdl:message>  
57. <wsdl:message name="getUserResponse">  
58. <wsdl:part element="tns:getUserResponse" name="parameters" />  
59. </wsdl:message>  
60. <wsdl:portType name="IUserService">  
61. <wsdl:operation name="login">  
62. <wsdl:input message="tns:login" />  
63. <wsdl:output message="tns:loginResponse" />  
64. </wsdl:operation>  
65. <wsdl:operation name="getUser">  
66. <wsdl:input message="tns:getUser" />  
67. <wsdl:output message="tns:getUserResponse" />  
68. </wsdl:operation>  
69. </wsdl:portType>  
70. <wsdl:binding name="userServiceSOAP" type="tns:IUserService">  
71. <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />  
72. <wsdl:operation name="login">  
73. <wsdl:input><soap:body use="literal" /></wsdl:input>  
74. <wsdl:output><soap:body use="literal" /></wsdl:output>  
75. </wsdl:operation>  
76. <wsdl:operation name="getUser">  
77. <wsdl:input><soap:body use="literal" /></wsdl:input>  
78. <wsdl:output><soap:body use="literal" /></wsdl:output>  
79. </wsdl:operation>  
80. </wsdl:binding>  
81. <wsdl:service name="UserService">  
82. <wsdl:port binding="tns:userServiceSOAP" name="userServicePort">  
83. <soap:address location="http://localhost:8080/spring-webservice-server/service/UserService.wsdl" />  
84. </wsdl:port>  
85. </wsdl:service>  
86. </wsdl:definitions></pre>  
87. <pre></pre>  
88. <pre></pre>  
89. <pre></pre>  
90. <pre></pre>  
91. <pre></pre>  
92. <pre></pre>


PS: 上面xsd part这一段是可以单独写到一个UserService.xsd文件中去的,然后在include到这个wsdl里面来的,这样看着更正规、更清新一些,我没这样写的主要原因是待会用soapUI调试的时候会出现这个xsdl文件import错误,我也不知道是什么原因,不纠结这些工具的问题了,在spring里面可以通过这个xsd文件动态的创建wsdl文件,这样可以省下一些工作了,但我还是希望初学者自己动手写wsdl文件。



2.2 编写spring的配置文件[spring-ws-servlet.xml],该文件放到WEB-INF/下面,内容如下:



1. <beans xmlns="http://www.springframework.org/schema/beans"  
2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
3. xmlns:sws="http://www.springframework.org/schema/web-services"  
4. xmlns:ws="http://www.springframework.org/schema/integration/ws"  
5. xmlns:context="http://www.springframework.org/schema/context"  
6. xsi:schemaLocation="http://www.springframework.org/schema/beans  
7.     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
8.     http://www.springframework.org/schema/context  
9.     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
10.     http://www.springframework.org/schema/web-services  
11.     http://www.springframework.org/schema/web-services/web-services-2.0.xsd  
12. >  
13.   
14. <context:component-scan base-package="com.zdsoft.webservice"/>  
15.       
16. <sws:static-wsdl location="/WEB-INF/wsdl/UserService.wsdl"/>  
17.       
18. <!-- 下面的配置可以动态的生成wsdl文件,我们只需要写一个简单的xsd文件就可以了 -->  
19.     <!--  
20. <sws:dynamic-wsdl id="UserService" portTypeName="IUserService" targetNamespace="http://webservice.zdsoft.com/namespace/userservice"  
21. locationUri="/service" serviceName="UserService" >  
22. <sws:xsd location="/WEB-INF/wsdl/UserService.xsd" />  
23. </sws:dynamic-wsdl>  
24. >  
25. </beans>




2.3 启动我们的tomcat,在浏览器里面输入:http://localhost:8080/spring-webservice-server/service/UserService.wsdl,就可以看到我们wsdl文件了,如下:



spring 项目中有哪些文件服务器 spring web服务器_webservice




2.4 根据wsdl文件生成我们需要的java文件


使用java自带的wsimport命令生成文件,如下:


1. cmd wsimport -d d:/webservice -keep http://localhost:8080/spring-webservice-server/service/UserService.wsdl

spring 项目中有哪些文件服务器 spring web服务器_spring_02


对于上面生成的文件要做以下几点处理:

a. 将IUserService.java文件中带className的属性去掉:



    1. @RequestWrapper(  
    2. "login",   
    3. "http://webservice.zdsoft.com/namespace/userservice",   
    4. "com.zdsoft.webservice.namespace.userservice.Login")


    1. @RequestWrapper(  
    2. "login",   
    3. "http://webservice.zdsoft.com/namespace/userservice")

    1. @XmlAccessorType(XmlAccessType.FIELD)  
    2. @XmlType(name = "login", propOrder = {  
    3. "username",  
    4. "password"  
    5. })  
    6. @XmlRootElement(name="login", namespace="http://webservice.zdsoft.com/namespace/userservice")  
    7. public class Login {


    1. <pre code_snippet_id="322977" snippet_file_name="blog_20140502_9_4134000"></pre>  
    2. <h2><a name="t10"></a></h2>  
    3. <pre></pre>  
    4. <pre></pre>  
    5. <pre></pre>

    2.5 创建UserServiceImpl类,实现IUserService接口,如下:


    1. package com.zdsoft.webservice.service;  
    2.   
    3. import org.apache.log4j.LogManager;  
    4. import org.apache.log4j.Logger;  
    5. import org.springframework.stereotype.Component;  
    6.   
    7. import com.zdsoft.webservice.api.user.IUserService;  
    8. import com.zdsoft.webservice.api.user.User;  
    9.   
    10. /**
    11.  * @author YuYang(zdsoft.yang@)
    12.  *
    13.  * @date 2014年5月2日
    14.  */  
    15. @Component("userService")  
    16. public class UserServiceImpl implements IUserService {  
    17.       
    18. private static final Logger LOG = LogManager.getLogger(UserServiceImpl.class);  
    19.   
    20. public String login(String username, String password) {  
    21. "Entered into UserServiceImpl method.");  
    22.           
    23. "username:" + username);  
    24. "password:" + password);  
    25.           
    26. "login failed.";  
    27.           
    28. if("scott".equals(username) && "tiger".equals(password)) {  
    29. "login success.";  
    30.         }  
    31.           
    32.         LOG.debug(info);  
    33. "Exit from UserServiceImpl method.");  
    34.           
    35. return info;  
    36.     }  
    37.   
    38. public User getUser(String username) {  
    39. "Entered into getUser method.");  
    40.           
    41.         LOG.debug(username);  
    42.           
    43. new User();  
    44. "--nickname");  
    45. "--password");  
    46. "--username");  
    47.           
    48. "Exit from getUser method.");  
    49. return user;  
    50.     }  
    51.   
    52. }


    2.6 创建endpoint类:UserServiceEndpoint,如下:


    1. package com.zdsoft.webservice.endpoint;  
    2.   
    3. import javax.annotation.Resource;  
    4.   
    5. import org.apache.log4j.LogManager;  
    6. import org.apache.log4j.Logger;  
    7. import .server.endpoint.annotation.Endpoint;  
    8. import .server.endpoint.annotation.PayloadRoot;  
    9. import .server.endpoint.annotation.RequestPayload;  
    10. import .server.endpoint.annotation.ResponsePayload;  
    11.   
    12. import com.zdsoft.webservice.api.user.GetUser;  
    13. import com.zdsoft.webservice.api.user.GetUserResponse;  
    14. import com.zdsoft.webservice.api.user.IUserService;  
    15. import com.zdsoft.webservice.api.user.Login;  
    16. import com.zdsoft.webservice.api.user.LoginResponse;  
    17. import com.zdsoft.webservice.api.user.User;  
    18.   
    19. /**
    20.  * @author YuYang(zdsoft.yang@)
    21.  *
    22.  * @date 2014年5月2日
    23.  */  
    24.   
    25. @Endpoint  
    26. public class UserServiceEndpoint {  
    27.       
    28. private static final Logger LOG = LogManager.getLogger(UserServiceEndpoint.class);  
    29.       
    30. //UserService.wsdl声明的命名空间  
    31. public static final String USERVICE_NAMESPACE = "http://webservice.zdsoft.com/namespace/userservice";  
    32.   
    33. @Resource(name="userService")  
    34. private IUserService userService;  
    35.       
    36. @PayloadRoot(namespace = USERVICE_NAMESPACE, localPart = "login")  
    37. @ResponsePayload  
    38. public LoginResponse handelLoginRequest(@RequestPayload Login request) {  
    39. "Entered into handelLoginRequest method.");  
    40.           
    41.         String info = userService.login(request.getUsername(), request.getPassword());  
    42.   
    43. new LoginResponse();  
    44.         response.setInfo(info);  
    45.           
    46. "Exit from handelLoginRequest method.");  
    47. return response;  
    48.     }  
    49.       
    50. @PayloadRoot(namespace = USERVICE_NAMESPACE, localPart = "getUser")  
    51. @ResponsePayload  
    52. public GetUserResponse HandelGetUserRequest(@RequestPayload GetUser request) {  
    53. "Entered into HandelGetUserRequest method.");  
    54.           
    55.         User user = userService.getUser(request.getUsername());  
    56.           
    57. new GetUserResponse();  
    58.         response.setUser(user);  
    59.           
    60. "Exit from  HandelGetUserRequest method.");  
    61. return response;  
    62.     }  
    63. }


    2.7 使用SoapUI工具测试


    a. 下载SoapUI,官网:http://www.soapui.org/, 这个工具使用方法去Google一下。


    b. 测试我们的login方法,如下:


    spring 项目中有哪些文件服务器 spring web服务器_apache_03




    c. 测试我们的getUser方法, 如下:


    spring 项目中有哪些文件服务器 spring web服务器_xml_04