最近研究了一下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文件了,如下:

2.4 根据wsdl文件生成我们需要的java文件
使用java自带的wsimport命令生成文件,如下:
1. cmd wsimport -d d:/webservice -keep http://localhost:8080/spring-webservice-server/service/UserService.wsdl

对于上面生成的文件要做以下几点处理:
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方法,如下:

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

















