Spring
Web Service是Spring社区基于Spring提供的一个关注于创建”文档驱动”的Web Service的模块, 它的主要目标是方便基于”契约优先”(Contract-First)的SOAP服务的开发. 好像没有多少人讨论, 大多数的话题都是围绕xfire, cxf,
axis/axis2等主流的Web Service框架.尽管是从事这方面的工作, 不过实际开发中还是公司内部开发的一个Web Service模块, 发现与Spring提供的这个模块的构架很像,所以拿出来学习学习.还是先来跑一个类似于Hello Wrold的例子吧.
1,
确定SOAP Body中包含的xml
客户端向服务端发出的xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<HelloRequest xmlns=”http://www.fuxueliang.com/ws/hello” >
Rondy.F
</HelloRequest>
服务端返回的xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<HelloResponse xmlns=”http://www.fuxueliang.com/ws/hello” >
Hello, Rondy.F!
</HelloResponse>
2,
确定WSDL
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
xmlns:wsdl=”http://schemas.xmlsoap.org/wsdl/”
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:schema=”http://www.fuxueliang.com/ws/hello”
xmlns:tns="http://www.fuxueliang.com/ws/hello/definitions"
targetNamespace="http://www.fuxueliang.com/ws/hello/definitions">
<wsdl:types>
<schema xmlns="htp://www.w3.org/2001/XMLSchema"
argetNamespace="http://www.fuxueliang.com/ws/hello">
<element name="HelloRequest" type="string" />
<element name="HelloResponse" type="string" />
</schema>
</wsdl:types>
<wsdl:message name="HelloRequest">
<wsdl:part element="schema:HelloRequest" name="HelloRequest" />
</wsdl:message>
<wsdl:message name="HelloResponse">
<wsdl:part element="schema:HelloResponse" name="HelloResponse" />
</wsdl:message>
<wsdl:portType name="HelloPortType">
<wsdl:operation name="Hello">
<wsdl:input message="tns:HelloRequest" name="HelloRequest" />
<wsdl:output message="tns:HelloResponse" name="HelloResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloBinding" type="tns:HelloPortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="Hello">
<soap:operation soapAction="" />
<wsdl:input name="HelloRequest">
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="HelloResponse">
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloService">
<wsdl:port binding="tns:HelloBinding" name="HelloPort">
<soap:address location="http://localhost:8080/springws/webservice" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
3,
创建一个Web项目, 由于Spring Web
Service是基于Spring MVC的, 在web.xml中添加如下servlet, 并在WEB-INF下建立SpringMVC的默认配置文件spring-ws-servlet.xml:
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
4,
创建业务方法及具体实现如下:
/**
* @author Rondy.F
*
*/
public interface HelloService {
String hello(String name);
}
/**
* @author Rondy.F
*
*/
public class HelloServiceImpl implements HelloService {
public String hello(String name) {
return "Hello, " + name + "!";
}
}
5, 实现一个EndPoint来处理接收到的xml及返回xml.当然, Spring Web Service提供了很多抽象的实现, 包括Dom4j, JDom等等.这里我们使用JDK自带的, 需要继承org.springframework.ws.server.endpoint.AbstractDomPayloadEndpoint.
/**
* @author Rondy.F
*
*/
public class HelloEndPoint extends AbstractDomPayloadEndpoint {
/**
* Namespace of both request and response.
*/
public static final String NAMESPACE_URI = "http://www.fuxueliang.com/ws/hello";
/**
* The local name of the expected request.
*/
public static final String HELLO_REQUEST_LOCAL_NAME = "HelloRequest";
/**
* The local name of the created response.
*/
public static final String HELLO_RESPONSE_LOCAL_NAME = "HelloResponse";
private HelloService helloService;
@Override
protected Element invokeInternal(Element requestElement, Document document) throws Exception {
Assert.isTrue(NAMESPACE_URI.equals(requestElement.getNamespaceURI()), "Invalid namespace");
Assert.isTrue(HELLO_REQUEST_LOCAL_NAME.equals(requestElement.getLocalName()), "Invalid local name");
NodeList children = requestElement.getChildNodes();
Text requestText = null;
for (int i = 0; i < children.getLength(); i++) {
if (children.item(i).getNodeType() == Node.TEXT_NODE) {
requestText = (Text) children.item(i);
break;
}
}
if (requestText == null) {
throw new IllegalArgumentException("Could not find request text node");
}
String response = helloService.hello(requestText.getNodeValue());
Element responseElement = document.createElementNS(NAMESPACE_URI, HELLO_RESPONSE_LOCAL_NAME);
Text responseText = document.createTextNode(response);
responseElement.appendChild(responseText);
return responseElement;
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
6,
修改配置文件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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="payloadMapping" class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
<property name="endpointMap">
<map>
<entry key=”{http://www.fuxueliang.com/ws/hello}HelloRequest” />
<ref bean="helloEndpoint" />
</entry>
</map>
</property>
</bean>
<bean id="hello" class="org.springframework.ws.wsdl.wsdl11.SimpleWsdl11Definition">
<property name="wsdl" value="/WEB-INF/hello.wsdl"/>
</bean>
<bean id="helloEndpoint" class="org.rondy.ws.HelloEndPoint">
<property name="helloService" ref="helloService" />
</bean>
<bean id="helloService" class="org.rondy.service.HelloServiceImpl" />
</beans>
注: 其中最主要的bean就是payloadMapping, 它定义了接收到的message与endpoint之间的mapping关系:将SOAP Body中包含的xml的根节点的QName为{http://www.fuxueliang.com/ws/hello}HelloRequest交给helloEndpoint处理.
SimpleWsdl11Definition这个bean则是定义了这个服务的wsdl, 访问地址是:http://localhost:8080/springws/hello.wsdl.
7,
客户端(saaj实现)的代码如下:
/**
*
* @author Rondy.F
*
*/
public class HelloWebServiceClient {
public static final String NAMESPACE_URI = "http://www.fuxueliang.com/ws/hello";
public static final String PREFIX = "tns";
private SOAPConnectionFactory connectionFactory;
private MessageFactory messageFactory;
private URL url;
public HelloWebServiceClient(String url) throws SOAPException, MalformedURLException {
connectionFactory = SOAPConnectionFactory.newInstance();
messageFactory = MessageFactory.newInstance();
this.url = new URL(url);
}
private SOAPMessage createHelloRequest() throws SOAPException {
SOAPMessage message = messageFactory.createMessage();
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
Name helloRequestName = envelope.createName("HelloRequest", PREFIX, NAMESPACE_URI);
SOAPBodyElement helloRequestElement = message.getSOAPBody().addBodyElement(helloRequestName);
helloRequestElement.setValue("Rondy.F");
return message;
}
public void callWebService() throws SOAPException, IOException {
SOAPMessage request = createHelloRequest();
SOAPConnection connection = connectionFactory.createConnection();
SOAPMessage response = connection.call(request, url);
if (!response.getSOAPBody().hasFault()) {
writeHelloResponse(response);
} else {
SOAPFault fault = response.getSOAPBody().getFault();
System.err.println("Received SOAP Fault");
System.err.println("SOAP Fault Code :" + fault.getFaultCode());
System.err.println("SOAP Fault String :" + fault.getFaultString());
}
}
@SuppressWarnings("unchecked")
private void writeHelloResponse(SOAPMessage message) throws SOAPException {
SOAPEnvelope envelope = message.getSOAPPart().getEnvelope();
Name helloResponseName = envelope.createName("HelloResponse", PREFIX, NAMESPACE_URI);
Iterator childElements = message.getSOAPBody().getChildElements(helloResponseName);
SOAPBodyElement helloResponseElement = (SOAPBodyElement) childElements.next();
String value = helloResponseElement.getTextContent();
System.out.println("Hello Response [" + value + "]");
}
public static void main(String[] args) throws Exception {
String url = "http://localhost:8080/springws";
HelloWebServiceClient helloClient = new HelloWebServiceClient(url);
helloClient.callWebService();
}
}
几点看法:
1,
从上面代码可以看出, 比较麻烦的部分就是客户端和服务端对xml处理, 当然一部分原因是由于选择了JDK自带的xml处理器. 在实际运用中可以考虑xml的绑定工具, 如jibx, castor等等.那么可能的EndPoint实现就只需要实现类似下面的方法:
protected HelloResponse invokeInternal(HelloRequest request);
2,
看看wsdl的访问方式, 以.wsdl结尾, 而不是?wsdl, 看起来总是不爽, 看了一下源代码,没有显式改变的方法, 看样子只能自己扩展了.而且上例子中还可以以http://localhost:8080/springws/abcdx/hello.wsdl得到wsdl, 哎...
3,
对于客户端, 直接用HttpClient, post到服务端.
前行的路标:
1,
毫无疑问, Spring总为你想的很全, 从SpringMVC提供的那么多的Controller就可以看出来.这次也不例外,jibx, castor,
xmlBeans, jaxb, xstream全给你准备了
2,
EndPointMapping也提供了很多选择,包括method, 还有注解的方式
这只是对Spring Web
Service学习的一个过程, 有兴趣的可以一起交流一下!后面将根据官方提供的文档来学习一下它所提供的各种功能以及分析一下它的整个流程.
顺便推荐一首歌, 小刚的<<空心>>.
分享到:
相关推荐
在"Spring Hello World"中,我们可能会创建一个`HelloWorld`类,该类依赖于Spring容器来获取并注入一个`MessageService`对象,这样就避免了硬编码依赖。 3. **控制反转(IoC)** 控制反转是DI的另一种表述,指的是...
为了搭建基于Spring MVC框架和IntelliJ IDEA开发环境的Hello World项目,首先要掌握以下知识点: 1. **Spring MVC框架的理解**: - Spring MVC是Spring框架的一部分,用于构建Web应用程序。 - 它提供了一种MVC...
在IT行业中,Spring框架是Java开发领域中极为重要的一个组件,尤其对于企业级应用来说,它的存在极大地...这个基础的例子为后续深入学习Spring的各种特性,如事务管理、AOP、数据访问、Web MVC等,打下了坚实的基础。
在本篇博客“Spring基础:稍显复杂的Spring Hello World”中,我们将深入探讨Spring框架的基础应用,特别是如何创建一个相对复杂的Spring HelloWorld示例。这个示例可能会涉及到依赖注入、配置文件、Bean的生命周期...
在实际开发中,一个简单的示例是创建一个基于J2EE平台的Web Service服务,如helloWorld应用。这个例子体现了开发的便利性、配置的简洁性和与Spring的无缝集成。XFire的流数据处理方式减少了内存消耗,提高了性能。...
这个简单的HelloWorld实例展示了Spring MVC和Hibernate的集成,以及如何进行基本的数据验证。 通过这个实例,你可以了解到如何将Spring MVC用于处理HTTP请求,使用Hibernate进行数据库操作,以及如何结合Spring的...
本文将深入探讨如何在Spring环境中利用JUnit进行"Hello, World!"的测试,同时也涉及到一些源码分析和测试工具的使用。 首先,我们需要理解Spring是如何管理bean的。Spring是一个依赖注入(Dependency Injection,DI...
通过这个"springmvc_helloWorld"项目,你可以学习到Spring MVC的基本架构、控制器的编写、视图的创建以及数据绑定等核心概念。这将为你后续深入学习Spring MVC框架以及开发复杂的Web应用奠定基础。
本篇文章将详细阐述如何使用XFire和Spring来构建一个Web Service的步骤。 首先,我们需要理解Web Service的基本概念。Web Service是一种基于互联网的、平台独立的交互方式,它允许不同系统之间通过XML进行数据交换...
标题 "spring mybatis helloworld" 暗示我们要探讨的是如何在Java环境下使用Spring和MyBatis框架构建一个基础的Hello World应用。Spring是一个全面的、模块化的应用程序框架,而MyBatis则是一个轻量级的持久层框架,...
本示例旨在介绍如何通过`@Component`注解实现一个简单的"HelloWorld"应用,这在Spring 3.1版本中就已经支持。下面我们将深入探讨`@Component`注解及其相关概念。 1. **什么是@Component注解** `@Component`是...
标题 "CXF 2.3 集成Spring3.0入门 HelloWorld" 指向的是一个关于如何在Java项目中使用Apache CXF 2.3版本与Spring 3.0框架进行集成的教程,特别是通过一个简单的"Hello World"应用来演示这个过程。Apache CXF是一个...
本文将通过"Spring的Hello World:理解IoC"这一主题,深入探讨Spring框架中的依赖注入(Dependency Injection,简称DI)概念,也被称为控制反转(Inversion of Control,简称IoC)。 首先,我们需要明白什么是IoC。...