Spring Web Service 简明教程
程序员文章站
2022-03-17 16:49:28
...
通过学习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
说明:配置一个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方法。
说明:由于User将作为传递的参数,因此需要一个能够在Object和XML间做转换的工具。这里我们依然使用Spring自己的解决方案—— spring-oxm包,oxm包是spring提供的抽象接口,底层实现交给第三方库,而我们今天选择的实现是jdk自己的jaxb2。而类中仅要做的是:在类名前加上@XmlRootElement,这个类就得到了受jaxb2转换的资格。
转换为:
注意 真实的XML字符串没有换行,这里效果仅用做演示
当然jaxb2的接入需要配置在上文提到的spring-ws-servlet.xml中
说明:将User类通过class-to-be-bound参数受jaxb2-marshaller管理, marshaller就是用来做转换的工具,转换的API为marshal()和unmarshal()(demo中未直接使用这两个API)。
然后,由于我们将user作为参数传递,所以必须定义一个严格的xml规范定义文件,命名为user.xsd,暂放在/WEB-INF/目录下。
说明: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中任意位置添加:
说明:最终配置好的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
@Endpoint就是spring web service的server端,@PayloadRoot是终端方法映射的一种实现,也是比较常用的。属性localPart设置了请求参数的根节点,见上文Object转换为的XML。@ResponsePayload表示有返回值,不然只能void。
接着,需要在spring-ws-servlet.xml中添加配置
<component-scan>不必多说,spring的组件扫描(这里笔者付出了沉痛代价,也许以后可以写篇文章说说)
<sws:annotation-driven/>主要就是用来扫描server终端@Endpoint
至此Server部分的编写就完成了,完整的spring-ws-servlet.xml:
接着,就要编写web service client的测试了,出于简单,我们暂时不使用单元测试,单元测试还需要多做一点准备。我们先用一个简单的main方法测试。编写代码如下:
说明:由于不能依靠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包为:
http://docs.spring.io/spring-ws/sites/2.0/reference/html/index.html
但是总体来说上面这篇教程的内容细节较多,因此在开始接触的时候会有点消化不了。而网上搜出来的文章往往夹杂着大量无关的代码。因此这里我总结了一个尽量简化的版本,希望能够用于初学快速打通。
首先,在引入了相关的jar包(见附录)后,编写web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <servlet> <servlet-name>spring-ws</servlet-name> <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class> <init-param> <param-name>transformWsdlLocations</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>spring-ws</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </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方法。
package com.zchen; import javax.xml.bind.annotation.XmlRootElement; /** * @author Zhouce Chen * @version May 19, 2014 */ @XmlRootElement(name = "user") public class User { private int id; private String name; public User() { } public User(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Id: " + id + ", Name: " + name; } }
说明:由于User将作为传递的参数,因此需要一个能够在Object和XML间做转换的工具。这里我们依然使用Spring自己的解决方案—— spring-oxm包,oxm包是spring提供的抽象接口,底层实现交给第三方库,而我们今天选择的实现是jdk自己的jaxb2。而类中仅要做的是:在类名前加上@XmlRootElement,这个类就得到了受jaxb2转换的资格。
User user = new User(); user.setId(1); user.setName("zchen");
转换为:
<?xml version="1.0" encoding="UTF-8"?> <user> <id>1</id> <name>zchen</name> </user>
注意 真实的XML字符串没有换行,这里效果仅用做演示
当然jaxb2的接入需要配置在上文提到的spring-ws-servlet.xml中
<?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:sws="http://www.springframework.org/schema/web-services" xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 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"> <oxm:jaxb2-marshaller id="jaxbMarshallerBean"> <oxm:class-to-be-bound name="com.zchen.User" /> </oxm:jaxb2-marshaller> </beans>
说明:将User类通过class-to-be-bound参数受jaxb2-marshaller管理, marshaller就是用来做转换的工具,转换的API为marshal()和unmarshal()(demo中未直接使用这两个API)。
然后,由于我们将user作为参数传递,所以必须定义一个严格的xml规范定义文件,命名为user.xsd,暂放在/WEB-INF/目录下。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://mycompany.com/hr/schemas"> <xs:element name="user"> <xs:complexType> <xs:sequence> <xs:element name="id" type="xs:int"/> <xs:element name="name" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </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中任意位置添加:
<sws:dynamic-wsdl id="user" portTypeName="UserType" locationUri="/userService/"> <sws:xsd location="/WEB-INF/user.xsd"/> </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
package com.zchen; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import org.springframework.ws.server.endpoint.annotation.RequestPayload; import org.springframework.ws.server.endpoint.annotation.ResponsePayload; /** * @author Zhouce Chen * @version May 19, 2014 */ @Endpoint public class UserEndpoint { @PayloadRoot(localPart = "user") @ResponsePayload public User handle(@RequestPayload User user) throws Exception { System.out.println(user.getId()); System.out.println(user.getName()); user.setId(2); user.setName("Hello Spring!"); return user; } }
@Endpoint就是spring web service的server端,@PayloadRoot是终端方法映射的一种实现,也是比较常用的。属性localPart设置了请求参数的根节点,见上文Object转换为的XML。@ResponsePayload表示有返回值,不然只能void。
接着,需要在spring-ws-servlet.xml中添加配置
<context:component-scan base-package="com.zchen"/> <sws:annotation-driven/>
<component-scan>不必多说,spring的组件扫描(这里笔者付出了沉痛代价,也许以后可以写篇文章说说)
<sws:annotation-driven/>主要就是用来扫描server终端@Endpoint
至此Server部分的编写就完成了,完整的spring-ws-servlet.xml:
<?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:sws="http://www.springframework.org/schema/web-services" xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 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"> <context:component-scan base-package="com.zchen"/> <sws:annotation-driven/> <sws:dynamic-wsdl id="user" portTypeName="UserType" locationUri="/userService/"> <sws:xsd location="/WEB-INF/user.xsd" /> </sws:dynamic-wsdl> <oxm:jaxb2-marshaller id="jaxbMarshallerBean"> <oxm:class-to-be-bound name="com.zchen.User" /> </oxm:jaxb2-marshaller> </beans>
接着,就要编写web service client的测试了,出于简单,我们暂时不使用单元测试,单元测试还需要多做一点准备。我们先用一个简单的main方法测试。编写代码如下:
package com.zchen; import org.springframework.oxm.jaxb.Jaxb2Marshaller; import org.springframework.ws.client.core.WebServiceTemplate; /** * @author Zhouce Chen * @version May 21, 2014 */ public class Test { public static void main(String[] args) { Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); marshaller.setClassesToBeBound(User.class); WebServiceTemplate template = new WebServiceTemplate(marshaller); User user = new User(1, "chenzhouce"); User returnUser = (User) template.marshalSendAndReceive("http://127.0.0.1:8080/userService/user.wsdl", user); System.out.println(returnUser); } }
说明:由于不能依靠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包为:
上一篇: 设计模式
推荐阅读
-
【Web API系列教程】3.10 — 实战:处理数据(发布App到Azure App Service)
-
[原创] Ubuntu 下 Docker 安装及使用简明教程 - 制作 Spring Boot 应用镜像
-
【从零入门 Web 前端】HTML5 + CSS 简明教程
-
PHP采用XML-RPC构造Web Service实例教程_PHP
-
NuSOAP 调用 Web Service 出现乱码的解决方法:_PHP教程
-
TCPDF简明教程_html/css_WEB-ITnose
-
PHP中使用XML-RPC构造Web Service简单入门_PHP教程
-
PHP采用XML-RPC构造Web Service实例教程
-
TCPDF简明教程_html/css_WEB-ITnose
-
PHP中XML-RPC构造Web Service_PHP教程