`

Spring ws 小示例

阅读更多
一、简介
  Spring Web Service 致力于开发契约优先的SOAP web Service,可以灵活利用很多方式处理XML内容;契约优先指的是我们在开始编写一个Web Service时,先编写WSDL,或者是XSD文件后动态生成WSDL,而不是先编写java code,然后根据代码生成WSDL。主要的特点有:
  1.强大的Mapping功能:你可以基于message内容、SOAP Action header 或者Xpath 表达式将接收到的XML请求映射到任意的Object。
  2.支持大量的XML API:不仅仅可以用JAXP APIS 如DOM,SAX,Stax,也可以用 JDOM,dom4j,XOM,甚至直接用编组技术(marshalling technologies,能直接将xml内容转变成java object)操作xml。
  3.灵活的XML编组:Spring Web Services 建立在spring framework 的oxm模块,支持JAXB1和JAXB2、Castor、XMLBeans、JiBX以及XStream。
  4.支持消息安全机制:Spring WS的安全机制允许你签名SOAP消息,加密和解密,也可以追加认证。

二、示例说明
  本示例参照Spring-ws-refenrenc中讲解的例子,实现一个hoiday预定功能,并在此基础上做了一些扩展,采用JAXB2直接将请求Object转变成消息发送,预定成功后返回姓名以及预定号码,并直接将返回结果转变成Object。

三、示例开始,首先编辑XSD
  Spring-WS 不推荐直接编写wsdl文件,我们可以编写相对简单的XSD文件,然后生成对应的wsdl文件。
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:hr="http://fengyilin.com/hr/schemas" elementFormDefault="qualified"
	targetNamespace="http://fengyilin.com/hr/schemas">
	<xs:element name="HolidayRequest">
		<xs:complexType>
			<xs:all>                           (4)
				<xs:element name="Holiday" type="hr:HolidayType" />     (1)
				<xs:element name="Employee" type="hr:EmployeeType" />         			</xs:all>
		</xs:complexType>
	</xs:element>
	<xs:element name="HolidayResponse">
		<xs:complexType>
			<xs:sequence>           (5)
				<xs:element name="name" type="xs:string" />
				<xs:element name="number" type="xs:integer" /> (3)
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	<xs:complexType name="HolidayType">
		<xs:sequence>
			<xs:element name="StartDate" type="xs:date" />    (2)
			<xs:element name="EndDate" type="xs:date" />      (2)
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="EmployeeType">
		<xs:sequence>
			<xs:element name="FirstName" type="xs:string" />   (3)
			<xs:element name="LastName" type="xs:string" />
		</xs:sequence>
	</xs:complexType>
</xs:schema>

(1) 引用我们自己定义的命名空间下的数据类型
(2)采用xsd:date data type,包含年、月、日
(3)xsd:string、xsd:integer定义对应的属性
(4)xsd:all 表明属性<Holiday/>和<Employee/>的顺序是随意
(5)xsd:sequence 表明属性顺序要保持一致
四、生成wsdl
1.创建动态web工程SpringWebService
2.编辑web.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://xmlns.jcp.org/xml/ns/javaee"
	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
	id="WebApp_ID" version="3.1">
	<display-name>SpringWebService</display-name>

	<servlet>
		<servlet-name>spring-ws</servlet-name>
		<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
		</init-param>
		<init-param>
			<param-name>transformWsdlLocations</param-name>
			<param-value>true</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
		<async-supported>true</async-supported>
	</servlet>
	<servlet-mapping>
		<servlet-name>spring-ws</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>log4jConfigLocation</param-name>
		<param-value>/resources/log4j/log4j.properties</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
	</listener>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
</web-app>



与SpringMvc工程相比,这里只是把DispatcherServlet换成了MessageDispatcherServlet。把transformWsdlLoactions属性设置成true,启动location 转换功能,从而将相对路径动态的转换成绝对路径。
3.编辑context配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:sws="http://www.springframework.org/schema/web-services"
	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/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<context:component-scan base-package="test.spring.ws.service" /> (1)
	<sws:annotation-driven />                                    (2)
	<sws:dynamic-wsdl id="holiday"                          (3)
		portTypeName="HumanResource"             (4)
		locationUri="/holidayService/"                    (5)
		targetNamespace="http://fengyilin.com/hr/definitions">   (6)
		<sws:xsd location="/resources/xsd/hr.xsd" />        (7)
	</sws:dynamic-wsdl>
</beans>

(1)指定类扫描路径
(2)标明采用注解驱动
(3)id属性表明了WSDL可以被获取到的URL,这里id是holiday,标明WSDL文件在servlet context中是 holiday.wsdl.完整的获取路径是:http://host:port/工程名/(locationUri)/holiday.wsdl,对应到本示例就是http://localhost:8080/SpringWebService/holidayService/holiday.wsdl;dynamic-wsdl标明在程序执行中动态生成wsdl
(4)指定WSDL的port type是HumanResource
(5)指定了一个相对路径,因为在web.xml中设置了transformWsdlLocations的值为true,所以此处能用相对路径标明wsdl service的访问路径。
(6)指定了WDSL自己的命名空间,如果不设置,wsdl使用和XSD schema相同的命名空间
(7)指定了用来生成wsdl的xsd文件的位置
4.应用启动后,访问对应的url,生成wsdl文件,内容如下
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:sch="http://fengyilin.com/hr/schemas" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://fengyilin.com/hr/definitions" targetNamespace="http://fengyilin.com/hr/definitions">
	<wsdl:types>
		<xs:schema xmlns:hr="http://fengyilin.com/hr/schemas"
			xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
			targetNamespace="http://fengyilin.com/hr/schemas">
			<xs:element name="HolidayRequest">
				<xs:complexType>
					<xs:all>
						<xs:element name="Holiday" type="hr:HolidayType" />
						<xs:element name="Employee" type="hr:EmployeeType" />
					</xs:all>
				</xs:complexType>
			</xs:element>
			<xs:element name="HolidayResponse">
				<xs:complexType>
					<xs:sequence>
						<xs:element name="name" type="xs:string" />
						<xs:element name="number" type="xs:integer" />
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:complexType name="HolidayType">
				<xs:sequence>
					<xs:element name="StartDate" type="xs:date" />
					<xs:element name="EndDate" type="xs:date" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="EmployeeType">
				<xs:sequence>
					<xs:element name="FirstName" type="xs:string" />
					<xs:element name="LastName" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
		</xs:schema>
	</wsdl:types>
	<wsdl:message name="HolidayRequest">
		<wsdl:part element="sch:HolidayRequest" name="HolidayRequest"></wsdl:part>
	</wsdl:message>
	<wsdl:message name="HolidayResponse">
		<wsdl:part element="sch:HolidayResponse" name="HolidayResponse"></wsdl:part>
	</wsdl:message>
	<wsdl:portType name="HumanResource">
		<wsdl:operation name="Holiday">
			<wsdl:input message="tns:HolidayRequest" name="HolidayRequest"></wsdl:input>
			<wsdl:output message="tns:HolidayResponse" name="HolidayResponse"></wsdl:output>
		</wsdl:operation>
	</wsdl:portType>
	<wsdl:binding name="HumanResourceSoap11" type="tns:HumanResource">
		<soap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="Holiday">
			<soap:operation soapAction="" />
			<wsdl:input name="HolidayRequest">
				<soap:body use="literal" />
			</wsdl:input>
			<wsdl:output name="HolidayResponse">
				<soap:body use="literal" />
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	<wsdl:service name="HumanResourceService">
		<wsdl:port binding="tns:HumanResourceSoap11" name="HumanResourceSoap11">
			<soap:address location="http://localhost:8080/SpringWebService/holidayService" />
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>


*尽管在运行时从XSDs直接生成WSDL十分便利,采用这种方式会有以下几个问题:
(1)随着Spring-ws版本升级,根据相同的XSD生成的WSDL有可能会发生变化。
(2)即便是只生成一次,然后将wsdl缓存起来,但是因为生成过程也会造成请求变慢。
所以推荐做法是:在development阶段,用<dynamic-wsdl>来动态生成,当发布应用时,利用浏览器将wsdl download下来,然后再用<static-wsdl>,这样就可以保证WSDL保持不变

即把上文的servlet-context.xml中关于sws的部分改为如下内容
<sws:static-wsdl id="holiday" location="/resources/wsdl/holiday.wsdl"/>


五、实现Endpoint
因为采用了JAXB2的组装技术,所以没有了xml的操作,Endpoint实现相当简单
package test.spring.ws.service.endpoint;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;

import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.filter.Filters;
import org.jdom2.xpath.XPathExpression;
import org.jdom2.xpath.XPathFactory;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.xml.xpath.Jaxp13XPathTemplate;
import org.springframework.xml.xpath.XPathOperations;

import test.spring.ws.entity.HolidayRequest;
import test.spring.ws.entity.HolidayResponse;
import test.spring.ws.service.HumanResourceService;

@Endpoint
public class HolidayEndpoint {
	private static final String NAMESPACE_URI = "http://fengyilin.com/hr/schemas";

	private HumanResourceService humanResourceService;

	@Autowired
	public HolidayEndpoint(HumanResourceService humanResourceService) throws JDOMException {
		this.humanResourceService = humanResourceService;
	}

	@PayloadRoot(namespace = NAMESPACE_URI, localPart = "HolidayRequest") (1)
	@ResponsePayload     (2)
	public HolidayResponse handleHolidayRequest(@RequestPayload HolidayRequest request) throws Exception {   (3)

		humanResourceService.bookHoliday(request.getHoliday().getStartDate(), request.getHoliday().getEndDate(),
				request.getEmployee().getFirstName());

		HolidayResponse response = new HolidayResponse();
		response.setName(request.getEmployee().getFirstName()+"_"+request.getEmployee().getLastName());
		response.setNumber((int) (100*Math.random()));
		return response;
	}
}


(1)因为SOAP协议和transport无关的,所以Spring-ws不支持通过HTTP请求的URL来Mapping消息到Endpoint,而是通过消息的内容,包括消息的命名空间,消息本地名称,所以PayloadRoot注解中的属性一定要正确,并且和客户端调用时保持一致。
(2)ResponsePayload注解表示有内容返回给客户端
(3)HolidayResponse和HolidayRequest是利用JAXB注解注释的类,可以利用xsd文件直接生成。(此处为了理解xsd到java class直接的转换,我手工写了这两个类,以及它们依赖的类),如何自动生成,可以参照http://fengyilin.iteye.com/admin/blogs/2344183

以上就是服务端的主要代码,下面简单看下客户端调用
/*
 * Copyright 2007 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package test.spring.ws.client;

import java.io.IOException;
import java.util.Date;

import javax.xml.transform.Source;

import org.springframework.core.io.ClassPathResource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.util.ClassUtils;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.xml.transform.ResourceSource;
import org.springframework.xml.transform.StringResult;

import test.spring.ws.entity.EmployeeType;
import test.spring.ws.entity.HolidayRequest;
import test.spring.ws.entity.HolidayResponse;
import test.spring.ws.entity.HolidayType;
import test.spring.ws.jaxb2.JaxbUtil;

public class HolidayClient {

	private final WebServiceTemplate webServiceTemplate = new WebServiceTemplate();

	// send to the configured default URI
	public void sendAndReceive() throws Exception {
		Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
		marshaller.setPackagesToScan(new String[] { ClassUtils.getPackageName(HolidayRequest.class) });
		marshaller.afterPropertiesSet();
		WebServiceTemplate msbServiceTemplate = new WebServiceTemplate(marshaller);  -- (1)
		HolidayRequest request = new HolidayRequest();
		EmployeeType employee = new EmployeeType();
		employee.setFirstName("cc");
		employee.setLastName("dd");
		request.setEmployee(employee);

		HolidayType holiday = new HolidayType();
		holiday.setEndDate(new Date());
		holiday.setStartDate(new Date());

		request.setHoliday(holiday);
		msbServiceTemplate.setDefaultUri("http://localhost:8080/SpringWebService/services");
		HolidayResponse response = (HolidayResponse) msbServiceTemplate.marshalSendAndReceive(request);--(2)
		
		
		System.out.println("-------");
		System.out.println(response);
		System.out.println("-------");
	}

	public static void main(String[] args) throws Exception {
		HolidayClient client = new HolidayClient();
		client.sendAndReceive();
	}
}


(1)采用编组技术,直接将Java Object转换成消息内容发送
(2)返回结果直接组装成java 对象

完整的工程目录如下:



工程的具体代码请参考附件
  • 大小: 175.7 KB
分享到:
评论

相关推荐

    Spring Integration + Spring WS 整合

    Spring Integration + Spring WS 整合 在 Java 领域中,Spring Integration 和 Spring WS 是两个常用的框架,它们分别负责集成系统和 Web 服务。今天,我们将探讨如何将这两个框架整合在一起,实现一个完整的 Web ...

    spring-ws开发/调用webservice示例代码

    本示例代码将展示如何利用Spring-WS进行Web服务的开发和调用,涉及到的关键技术包括XSD(XML Schema Definition)用于定义数据结构,WSDL(Web Service Description Language)用于描述服务接口,以及JAXB(Java ...

    Spring-WS示例

    **Spring-WS 示例详解** Spring-WS 是一个基于 Java 的轻量级 Web 服务框架,它专注于 SOAP(Simple Object Access Protocol)消息处理。这个框架使开发者能够创建和消费符合 W3C 标准的 SOAP 消息,同时利用 ...

    spring web service 官网示例 基于spring-ws

    原来的jax-ws不知道为什么总是不成功,最后放弃,换成这个。具体过程可以参考官网:http://docs.spring.io/spring-ws/site/reference/html/tutorial.html

    JAX-WS + Spring 实现webService示例

    **JAX-WS + Spring 实现Web Service示例** 在现代企业级应用开发中,Web Service作为一种跨平台、跨语言的通信方式,被广泛用于不同系统间的交互。本示例将详细阐述如何利用Java API for XML Web Services (JAX-WS)...

    spring-ws源码,例子,及reference

    本资源包含三个主要部分:Spring-WS的源码、示例项目以及官方参考文档,对深入理解和使用Spring-WS非常有帮助。 **Spring-WS源码**: 源码是学习任何框架的最佳途径,因为它揭示了框架内部的工作原理。Spring-WS的...

    JAX-WS + Spring 实现webService示例.docx

    这是一个简单的JAX-WS示例,用于演示如何通过Spring进行依赖注入。我们创建一个名为`HelloWorldWS`的Web服务接口,其中包含一个方法`getHelloWorld()`,该方法调用`HelloWorldBo`业务对象的方法。 ```java package ...

    spring-ws:Spring WS教程

    **Spring WS:构建Web服务** Spring Web Services ...请参考`spring-ws-master`中的示例代码,动手实践以加深理解。如果你在学习过程中遇到问题,可以在相关的博客文章下留言或在GitHub上提交问题。祝你学习顺利!

    springcloud getway 示例 包含 网关 http websocket 两种转发包含网关JWT鉴权包含Clie

    EurekaApplication Eureka也可以不用 gateway可直接转发外部的服务 PtGatewayApplication ... UserApplication 模拟WebSocket服务 PtGateClientTests 模拟WebSocket请求服务 ... 导入之后 maven跑完即可完整运行

    Webservice入门教程_用CXF编写基于Spring的WebService示例代码.zip

    Apache CXF是一个开源的、功能丰富的Web服务框架,它支持多种协议和标准,如SOAP、RESTful、WS-*等。Spring框架则是一个广泛使用的Java企业级应用开发框架,它简化了配置和依赖注入,使开发者能够更专注于业务逻辑。...

    spring-ws:Spring ws 示例

    如何使用 maven 创建 Spring-ws 项目: mvn archetype:create -DarchetypeGroupId=org.springframework.ws -DarchetypeArtifactId=spring-ws-archetype -DarchetypeVersion=2.1.4.RELEASE -DgroupId=...

    Spring-ws搭建WebService服务端demo

    在本文中,我们将深入探讨如何使用Spring框架与Spring-WS模块构建一个Web Service服务端的示例。Spring-WS是一个基于XML的Web Service框架,它提供了创建SOAP Web Service的简单方式。结合Maven进行项目管理,我们...

    spring集成ibatis示例-websphere5.1选型webservice

    2. **Web服务实现**: 使用Spring的`WebServiceTemplate`或JAX-WS来创建和消费Web服务。定义服务接口和实现,然后通过`@WebService`注解标记它们。例如: ```java @WebService public interface UserService { ...

    spring-ws-reference-1.5.9

    本章通过示例介绍如何使用 Spring-WS 构建一个简单的 Web 服务应用。 ##### 3.2 消息 - **Holiday**:表示假期请求的信息。 - **Employee**:员工信息。 - **HolidayRequest**:员工提交的假期申请。 ##### 3.3 ...

    使用 Spring-WS 完成的 Web Service (SOAP)

    在标签"源码"下,我们可以看到博主可能分享了有关 Spring-WS 的源码示例。通过阅读源码,我们可以更好地理解 Spring-WS 内部的工作原理,以及如何根据自己的需求定制和扩展框架。 **7. 工具支持** 在开发过程中,...

    CXF结合Spring开发WebServices示例工程

    "CXF结合Spring开发WebServices示例工程"包含了服务端和客户端的代码示例。服务端代码演示了如何定义服务接口,实现服务逻辑,并将其配置到Spring中。客户端代码展示了如何创建CXF客户端代理,并使用它来调用服务端...

    xFire+spring webService 示例

    Spring还包含了对Web服务的支持,通过Spring-WS和Spring-Integration等模块,可以在Spring应用中方便地使用和管理Web服务。 在"xFire+Spring WebService"的集成中,你可以使用Spring来配置和管理xFire,这样就可以...

    spring-ws-security-soap-example:显示如何在Spring中设置安全的SOAP Web服务的示例

    Spring Web Services WS-Security示例 设置各种协议的样本 SOAP Web服务。 支持WS-Security的两种实现,即和 。 对于每种认证方法,每种认证方法都有一个不同的终结点: 不安全。 普通密码。 摘要密码。 签名...

    Spring4+WebSocket小示例

    通过这个小示例,我们可以看到Spring4如何轻松地与WebSocket结合,为我们的Web应用带来实时通信能力。这只是一个基础的实现,实际项目中可能还需要考虑安全性、负载均衡、消息队列等更复杂的需求。

Global site tag (gtag.js) - Google Analytics