spring webservice (一) 服务器端开发

来源:互联网 发布:tsp问题算法源代码 编辑:程序博客网 时间:2024/05/01 00:18

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

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

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

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

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  2.     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/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://maven.apache.org</url>  
  10.     <dependencies>  
  11.         <dependency>  
  12.             <groupId>org.springframework.ws</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打印信息,如下:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  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里面做一些配置,如下:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <!DOCTYPE web-app PUBLIC  
  2.  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"  
  3.  "http://java.sun.com/dtd/web-app_2_3.dtd" >  
  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>org.springframework.ws.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/下面,内容如下:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  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/下面,内容如下:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  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命令生成文件,如下:
[plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. cmd wsimport -d d:/webservice -keep http://localhost:8080/spring-webservice-server/service/UserService.wsdl  
将所有的java文件复制到我们的项目里面来,如下:

对于上面生成的文件要做以下几点处理:
a. 将IUserService.java文件中带className的属性去掉:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @RequestWrapper(  
  2.             localName = "login",   
  3.             targetNamespace = "http://webservice.zdsoft.com/namespace/userservice",   
  4.             className = "com.zdsoft.webservice.namespace.userservice.Login")  
将上面的改成如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. @RequestWrapper(  
  2.         localName = "login",   
  3.         targetNamespace = "http://webservice.zdsoft.com/namespace/userservice")  
b.在GetUser.java, GetUserResponse.java,Login.java,LoginResponse.java中加上@XmlRootElement,并且指定名称空间,如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  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 {  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  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接口,如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  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@foxmail.com) 
  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.         LOG.info("Entered into UserServiceImpl method.");  
  22.           
  23.         LOG.debug("username:" + username);  
  24.         LOG.debug("password:" + password);  
  25.           
  26.         String info = "login failed.";  
  27.           
  28.         if("scott".equals(username) && "tiger".equals(password)) {  
  29.             info = "login success.";  
  30.         }  
  31.           
  32.         LOG.debug(info);  
  33.         LOG.info("Exit from UserServiceImpl method.");  
  34.           
  35.         return info;  
  36.     }  
  37.   
  38.     public User getUser(String username) {  
  39.         LOG.info("Entered into getUser method.");  
  40.           
  41.         LOG.debug(username);  
  42.           
  43.         User user = new User();  
  44.         user.setNickname(username + "--nickname");  
  45.         user.setPassword(username + "--password");  
  46.         user.setUsername(username + "--username");  
  47.           
  48.         LOG.info("Exit from getUser method.");  
  49.         return user;  
  50.     }  
  51.   
  52. }  

2.6 创建endpoint类:UserServiceEndpoint,如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  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 org.springframework.ws.server.endpoint.annotation.Endpoint;  
  8. import org.springframework.ws.server.endpoint.annotation.PayloadRoot;  
  9. import org.springframework.ws.server.endpoint.annotation.RequestPayload;  
  10. import org.springframework.ws.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@foxmail.com) 
  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.         LOG.info("Entered into handelLoginRequest method.");  
  40.           
  41.         String info = userService.login(request.getUsername(), request.getPassword());  
  42.   
  43.         LoginResponse response = new LoginResponse();  
  44.         response.setInfo(info);  
  45.           
  46.         LOG.info("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.         LOG.info("Entered into HandelGetUserRequest method.");  
  54.           
  55.         User user = userService.getUser(request.getUsername());  
  56.           
  57.         GetUserResponse response = new GetUserResponse();  
  58.         response.setUser(user);  
  59.           
  60.         LOG.info("Exit from  HandelGetUserRequest method.");  
  61.         return response;  
  62.     }  
  63. }  

2.7 使用SoapUI工具测试

a. 下载SoapUI,官网:http://www.soapui.org/, 这个工具使用方法去Google一下。
b. 测试我们的login方法,如下:


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


0 0
原创粉丝点击