Spring Web Service 简明教程

转载 2015年06月03日 18:17:24
     通过学习Spring WebServices Peoject里的Get started文档,能够学习到大部分sws(spring web service)的使用。
http://docs.spring.io/spring-ws/sites/2.0/reference/html/index.html

      但是总体来说上面这篇教程的内容细节较多,因此在开始接触的时候会有点消化不了。而网上搜出来的文章往往夹杂着大量无关的代码。因此这里我总结了一个尽量简化的版本,希望能够用于初学快速打通。

      首先,在引入了相关的jar包(见附录)后,编写web.xml
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"  
  4.          version="2.4">  
  5. <servlet>  
  6.   <servlet-name>spring-ws</servlet-name>  
  7.   <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>  
  8.   <init-param>  
  9.       <param-name>transformWsdlLocations</param-name>  
  10.       <param-value>true</param-value>  
  11.   </init-param>  
  12. </servlet>  
  13. <servlet-mapping>  
  14.   <servlet-name>spring-ws</servlet-name>  
  15.   <url-pattern>/*</url-pattern>  
  16. </servlet-mapping>  
  17. </web-app>  

      说明:配置一个Servlet - MessageDispatcherServlet,用于对webservice的请求进行接收和转发。和普通的Servlet性质相似。至于参数transformWsdlLocations的作用,过后会讲到。

      注意:这里的<servlet-name>spring-ws</servlet-name>是有用处的,sws所需的spring配置文件的名字必须用xxx-servlet.xml的格式,xxx就是servlet-name的值,即常规下名字为spring-ws-servlet.xml,而且该文件由框架自动寻找,默认位置与web.xml同级目录。


      然后,需要定义一个实体类,作为web service请求的传递参数,这里就用User吧,包含id和name两个属性,以及getter,setter方法。
Java代码  收藏代码
  1. package com.zchen;  
  2.   
  3. import javax.xml.bind.annotation.XmlRootElement;  
  4.   
  5. /** 
  6.  * @author Zhouce Chen 
  7.  * @version May 19, 2014 
  8.  */  
  9. @XmlRootElement(name = "user")  
  10. public class User {  
  11.     private int id;  
  12.     private String name;  
  13.     public User() {  
  14.     }  
  15.     public User(int id, String name) {  
  16.         this.id = id;  
  17.         this.name = name;  
  18.     }  
  19.     public int getId() {  
  20.         return id;  
  21.     }  
  22.     public void setId(int id) {  
  23.         this.id = id;  
  24.     }  
  25.     public String getName() {  
  26.         return name;  
  27.     }  
  28.     public void setName(String name) {  
  29.         this.name = name;  
  30.     }  
  31.    @Override  
  32.     public String toString() {  
  33.         return "Id: " + id + ", Name: " + name;  
  34.     }  
  35. }  

      说明:由于User将作为传递的参数,因此需要一个能够在Object和XML间做转换的工具。这里我们依然使用Spring自己的解决方案—— spring-oxm包,oxm包是spring提供的抽象接口,底层实现交给第三方库,而我们今天选择的实现是jdk自己的jaxb2。而类中仅要做的是:在类名前加上@XmlRootElement,这个类就得到了受jaxb2转换的资格。
Java代码  收藏代码
  1. User user = new User();  
  2. user.setId(1);  
  3. user.setName("zchen");  

转换为:
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <user>  
  3. <id>1</id>  
  4. <name>zchen</name>  
  5. </user>  

      注意 真实的XML字符串没有换行,这里效果仅用做演示
      当然jaxb2的接入需要配置在上文提到的spring-ws-servlet.xml
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:sws="http://www.springframework.org/schema/web-services"  
  5.        xmlns:oxm="http://www.springframework.org/schema/oxm"  
  6.        xmlns:context="http://www.springframework.org/schema/context"  
  7.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  8.        http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
  9.   
  10.     <oxm:jaxb2-marshaller id="jaxbMarshallerBean">  
  11.         <oxm:class-to-be-bound name="com.zchen.User" />  
  12.     </oxm:jaxb2-marshaller>  
  13.   
  14. </beans>  

      说明:将User类通过class-to-be-bound参数受jaxb2-marshaller管理, marshaller就是用来做转换的工具,转换的API为marshal()和unmarshal()(demo中未直接使用这两个API)。

      然后,由于我们将user作为参数传递,所以必须定义一个严格的xml规范定义文件,命名为user.xsd,暂放在/WEB-INF/目录下。
Xsd代码  收藏代码
  1. <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"  
  2.            targetNamespace="http://mycompany.com/hr/schemas">  
  3.     <xs:element name="user">  
  4.         <xs:complexType>  
  5.             <xs:sequence>  
  6.                 <xs:element name="id" type="xs:int"/>  
  7.                 <xs:element name="name" type="xs:string"/>  
  8.             </xs:sequence>  
  9.         </xs:complexType>  
  10.     </xs:element>  
  11. </xs:schema>    

      说明:user作为一个节点用<xs:element name="user">来定义,user内部又由两个节点组成,因此属于复合类型<xs:complexType>,使用<xs:sequence>包住节点的列表,里层节点定义中name和type分别是属性名和字段类型。

      我们知道在web service中将wsdl路径直接输入在浏览器地址栏,能够显示一个wsdl的xml文件,其中定义了这个web service相关的规则。而这个文件是不受限于web service server端,因此我们先将这个文件给显示出来。

      在spring-ws-servlet.xml中任意位置添加:
Xml代码  收藏代码
  1. <sws:dynamic-wsdl  
  2.           id="user"  
  3.           portTypeName="UserType"  
  4.           locationUri="/userService/">  
  5.         <sws:xsd location="/WEB-INF/user.xsd"/>  
  6.     </sws:dynamic-wsdl>  

      说明:最终配置好的wsdl路径为http://localhost:8080/userService/user.wsdl,其中,/userService/就是locationUri,user.wsdl中的user就是id。portTypeName暂时可以随意设置。<sws:xsd location="/WEB-INF/user.xsd"/>就是之前定义的xsd文件,其中location是从web根目录起的相对路径,也支持"classpath: xxx"形式。

      注意:locationUri默认应设置全路径,http://localhost:8080/userService/,而这里能够设置相对路径,是因为之前在web.xml中添加的参数transformWsdlLocations为true。
 
      此时启动tomcat服务器后,在浏览器地址栏里输入上文wsdl路径,就能展示一份wsdl文件了。

      接下来,我们要真正开始定义web service的server端。依然是编写一个类,UserEndpoint
Java代码  收藏代码
  1. package com.zchen;  
  2.   
  3. import org.springframework.ws.server.endpoint.annotation.Endpoint;  
  4. import org.springframework.ws.server.endpoint.annotation.PayloadRoot;  
  5. import org.springframework.ws.server.endpoint.annotation.RequestPayload;  
  6. import org.springframework.ws.server.endpoint.annotation.ResponsePayload;  
  7.   
  8. /** 
  9.  * @author Zhouce Chen 
  10.  * @version May 19, 2014 
  11.  */  
  12. @Endpoint  
  13. public class UserEndpoint {  
  14.   
  15.     @PayloadRoot(localPart = "user")  
  16.     @ResponsePayload  
  17.     public User handle(@RequestPayload User user) throws Exception {  
  18.         System.out.println(user.getId());  
  19.         System.out.println(user.getName());  
  20.         user.setId(2);  
  21.         user.setName("Hello Spring!");  
  22.         return user;  
  23.     }  
  24. }  

      @Endpoint就是spring web service的server端,@PayloadRoot是终端方法映射的一种实现,也是比较常用的。属性localPart设置了请求参数的根节点,见上文Object转换为的XML。@ResponsePayload表示有返回值,不然只能void。

      接着,需要在spring-ws-servlet.xml中添加配置
Xml代码  收藏代码
  1. <context:component-scan base-package="com.zchen"/>  
  2. <sws:annotation-driven/>  

<component-scan>不必多说,spring的组件扫描(这里笔者付出了沉痛代价,也许以后可以写篇文章说说)
<sws:annotation-driven/>主要就是用来扫描server终端@Endpoint

      至此Server部分的编写就完成了,完整的spring-ws-servlet.xml:
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:sws="http://www.springframework.org/schema/web-services"  
  5.        xmlns:oxm="http://www.springframework.org/schema/oxm"  
  6.        xmlns:context="http://www.springframework.org/schema/context"  
  7.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
  8.        http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
  9.   
  10.     <context:component-scan base-package="com.zchen"/>  
  11.     <sws:annotation-driven/>  
  12.    <sws:dynamic-wsdl id="user" portTypeName="UserType" locationUri="/userService/">  
  13.          <sws:xsd location="/WEB-INF/user.xsd" />  
  14.      </sws:dynamic-wsdl>  
  15.   
  16.     <oxm:jaxb2-marshaller id="jaxbMarshallerBean">  
  17.         <oxm:class-to-be-bound name="com.zchen.User" />  
  18.     </oxm:jaxb2-marshaller>  
  19.   
  20. </beans>  


      接着,就要编写web service client的测试了,出于简单,我们暂时不使用单元测试,单元测试还需要多做一点准备。我们先用一个简单的main方法测试。编写代码如下:
Java代码  收藏代码
  1. package com.zchen;  
  2.   
  3. import org.springframework.oxm.jaxb.Jaxb2Marshaller;  
  4. import org.springframework.ws.client.core.WebServiceTemplate;  
  5.   
  6. /** 
  7.  * @author Zhouce Chen 
  8.  * @version May 21, 2014 
  9.  */  
  10. public class Test {  
  11.     public static void main(String[] args) {  
  12.         Jaxb2Marshaller marshaller = new Jaxb2Marshaller();  
  13.         marshaller.setClassesToBeBound(User.class);  
  14.         WebServiceTemplate template = new WebServiceTemplate(marshaller);  
  15.         User user = new User(1"chenzhouce");  
  16.         User returnUser = (User) template.marshalSendAndReceive("http://127.0.0.1:8080/userService/user.wsdl", user);  
  17.         System.out.println(returnUser);  
  18.     }  
  19. }  

      说明:由于不能依靠spring的依赖注入,只能用原生的new和set。
               #12,创建一个Jaxb2Marshaller,Object与XML的转换工具。
               #13,将User类传递给marshaller管理。(与配置文件中的思路是一致的)。
               #14,创建一个(spring最喜欢玩的)template实例,它可以用来发送请求。
               #15,创建User对象
               #16,一个方法就集成了XML转换和发送,非常方便!前提是#14行一定要将marshaller传递给template。

      这样,一个简单的Spring Web Service的流程就都走通了。事实上Test类中的template在真实使用时,应该要配置在spring配置文件里,以注入的形式在你的业务逻辑里使用,而不应该每次创建一遍。对于这种用法的测试,将在另一篇文章里具体讲解。

PS. 源码上传到Github了,https://github.com/chenzhouce/spring-webservice-demo



附录:

项目是由maven管理的,所以maven的引用添加为:



全部的jar包为:

一个简单的Spring Web Service示例

      刚接触web service,好不容易找到一篇spring-ws的例子,还琢磨了好长一段时间,很多概念性的问题都没弄清楚。只能依葫芦画瓢,照搬过来,稍微修改了一下,使结构更加清晰,原文出自...
  • thinkGhoster
  • thinkGhoster
  • 2008年11月30日 16:53
  • 65619

WebService学习总结九 使用Spring发布WebService

服务端WebService接口使用Spring发布,客户端使用java测试。 服务端: 导入对应的jar包,编写服务接口并实现,和之前方式相同,然后在src下加个配置文件,引入cxf的核心配置。在we...
  • liangwenmail
  • liangwenmail
  • 2016年07月17日 13:42
  • 5345

详解spring+webservice接口(axis1方式)

第一步,添加jar包 axis1实现webservice所需jar包  axis-ant.jar  axis.jar  jaxrpc.jar (加粗的为核心包,简单的发布用这三个即可) commons...
  • zl834205311
  • zl834205311
  • 2017年01月11日 16:57
  • 2275

spring webservice 服务端 demo源码

  • 2014年05月02日 16:42
  • 38KB
  • 下载

WebService学习之旅(三)JAX-WS与Spring整合发布WebService

Spring本身就提供了对JAX-WS的支持,有兴趣的读者可以研究下Spring的Spring-WS项目,项目地址: http://docs.spring.io/spring-ws/sites/1....
  • Rongbo_J
  • Rongbo_J
  • 2016年03月25日 20:43
  • 12172

WebService 四种发布方式总结

WebService 四种发布方式总结 1. CXF方式 CXF与spring搭建webservice是目前最流行的方式,但是传闻cxf与jdk1.5有些不兼容,我没有遇到过,我遇到的问题...
  • zl834205311
  • zl834205311
  • 2016年06月08日 12:03
  • 41990

spring 实现webservice 实例

  • 2016年12月09日 13:38
  • 41.06MB
  • 下载

几种常用的webservice客户端和spring集成的方法

项目需要,这两天系统要调一个webservice的服务,webservice的东西都扔了好几年了,怎么使用都忘得一干二净了。以前都是使用系统现成的框架掉一个方法就行了,现在几乎是从0开始一点一点搭建环...
  • qiuhan
  • qiuhan
  • 2015年10月29日 09:33
  • 4352

spring-ws搭建webservice服务

本文主要介绍如何根据spring提供的spring-ws构建一个简单的webservice服务。 在开始之前,首先需要新建一个maven项目,这里不再赘述如何新建maven web项目。 1、配置po...
  • zyhlwzy
  • zyhlwzy
  • 2017年01月09日 18:28
  • 1594

WebService与Spring整合《三》

问题?WebService与Spring整合过程 前面的的提到了WebService整体开发过程,这里主要是说WebService与Spring的整合过程 一、提出问题 问题:在以往的项目中,...
  • Mr_li13
  • Mr_li13
  • 2016年05月05日 11:18
  • 6400
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring Web Service 简明教程
举报原因:
原因补充:

(最多只允许输入30个字)