基于CXF的WebServie技术应用
1 概述
面向服务的体系结构(service-oriented architecture,SOA)是一种思想,它将应用程序的不同功能单元通过中立的契约(独立于硬件平台、操作系统、编程语言)联系起来,使各个形式的功能单元更好的集成。WebService是SOA思想的一种较好实现方式,它和普通的web程序一样(如JSP,ASP)采用HTTP协议进行通讯,但是它只用POST方式通讯,它的数据是基于XML格式的,采用SOAP(Simple Object Access Protocol)协议。SOAP协议实际上就是基于XML编码规范的文本协议,它是WebService特有的应用协议。
1.1 WebService体系架构
1.2 CXF说明
JAVA平台上对WebService支持的成熟框架很多,如CXF、AXIS1&2、XFire等,本文使用CXF。
Apache CXF = Celtix + XFire,前身叫 Apache CeltiXfire,已经正式更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,是Apache基金会组织下的一个顶级项目,简化了WebService服务端的创建过程。
CXF实现了JAX-WS2.0规范,并通过了JAX-WS2.0 TCK;
CXF可以和Spring无缝集成;
CXF支持多种传输协议(HTTP, JMS, Corba等);
CXF支持多种Binding数据格式(SOAP,XML,JSON等);
CXF 支持多种DataBinding数据类型(JAXB, Aegis) 。
CXF基于Interceptor的架构,使得整个框架非常易于扩展。本次我主要讨论CXF在HTTP/SOAP模式下的处理机制。
CXF的下载地址为:http://cxf.apache.org/download.html,下载后解压压缩包,从lib中至少要拿出如下jar到应用:
cxf-2.2.5.jar
antlr-2.7.7.jar
commons-codec-1.3.jar
commons-collections-3.2.1.jar
commons-lang-2.4.jar
commons-logging-1.1.1.jar
commons-pool-1.5.2.jar
geronimo-annotation_1.0_spec-1.1.1.jar
geronimo-jaxws_2.1_spec-1.0.jar
geronimo-ws-metadata_2.0_spec-1.1.2.jar
jaxb-api-2.1.jar
xalan-2.7.1.jar
wsdl4j-1.6.2.jar
XmlSchema-1.4.5.jar
2 构建服务端
2.1 Servlet构建的简单服务端
1) 定义webservice接口和实现类
publicinterface IHelloWorld {
public String sayHello(String name);
}
publicclass HelloWorldImpl implements IHelloWorld {
public String sayHello(String name) {
return"Hello " + name + ".";
}
}
2) 定义webservice
publicclass HelloWorldServlet extends CXFNonSpringServlet {
privatestaticfinallongserialVersionUID = 1L;
@Override
protectedvoid loadBus(ServletConfig sc) {
super.loadBus(sc);
Bus bus = getBus();
//如果我们要发布多个WebService,仅仅需要修改WebService的接口定义、发布地址、实现类,然后不断重复下面的代码即可
ServerFactoryBean factory = new ServerFactoryBean();
factory.setBus(bus);
factory.setServiceClass(IHelloWorld.class);
factory.setAddress("/HelloWorld");
factory.setServiceBean(new HelloWorldImpl());
factory.create();
}
}
首先CXF的内部上下文对象Bus,然后我再使用CXF提供的ServerFactoryBean工具类把自己写的一个普通的JavaBean发布成WebService。
ServerFactoryBean需要以下参数:
1) Bus。也就是上面我们所得到的Bus对象。
2) WebService的接口定义,也就是指自己的WebService实现了哪个Java Interface。
3) WebService的发布地址,也就是访问WebService的URL地址。
4) WebService的实现类。
web.xml中配置HelloWorldServlet
<servlet>
<servlet-name> HelloWorldServlet </servlet-name>
<servlet-class> HelloWorldServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWorldServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
启动服务器,访问http://127.0.0.1:8080/CXFDemo/services/?wsdl,可以看到服务列表,http://127.0.0.1:8080/CXFDemo/services/HelloWorld?wsdl就是我们的服务地址。
2.2 java注解的简单服务端
为webservice实现类加上注解
@WebService
public class HelloWorldImpl implements IHelloWorld {
public String sayHello(@WebParam(name = "text") String name) {
return "Hello " + name + ".";
}
}
构建服务端
public class SimpleServer {
public SimpleServer() {
System.out.println("Starting Server");
IHelloWorld helloService = new HelloWorldImpl();
String address = "http://localhost:9000/helloWorld";
Endpoint.publish(address, helloService);
}
public static void main(String[] args) throws InterruptedException {
//System.out.println(System.getProperty("java.endorsed.dirs"));
new SimpleServer();
System.out.println("Server ready...");
Thread.sleep(6000000);
System.out.println("Server exiting");
System.exit(0);
}
}
运行应用程序,访问http://localhost:9000/helloWorld?wsdl,已经发布成功,可以看到服务没有在web服务器中发布,这是因为CXF内置了Jetty应用服务器,可以直接在Jetty上发布。
2.3 结合spring构建web服务
1) 声明实体
@XmlType(name = "User")
@XmlAccessorType(XmlAccessType.FIELD)
publicclass User implements Serializable {
privatestaticfinallongserialVersionUID = 1L;
private String username;
private String password;
public String getUsername() {
returnusername;
}
publicvoid setUsername(String username) {
this.username = username;
}
public String getPassword() {
returnpassword;
}
publicvoid setPassword(String password) {
this.password = password;
}
}
2) 声明接口
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
@WebService
@SOAPBinding(style = Style.RPC)
publicinterface IHelloService {
User saveUser(User user);
User getMaxLongNameUser(User u1, User u2);
}
3) 声明实现
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import org.apache.log4j.Logger;
@WebService
@SOAPBinding(style = Style.RPC)
publicclass HelloServiceImpl implements IHelloService {
privatestatic Logger log = Logger.getRootLogger();
public User saveUser(User user) {
log.debug("saveUser is called!");
return user;
}
public User getMaxLongNameUser(User u1, User u2) {
log.debug("getMaxLongNameUser is called!");
return u1;
}
}
4) spring配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<!-- 还需要引入以下3个关于CXF的资源文件,这三个文件在cxf.jar中 -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="inInter" class="org.apache.cxf.interceptor.LoggingInInterceptor" />
<bean id="outInter" class="org.apache.cxf.interceptor.LoggingOutInterceptor" />
<jaxws:endpoint id="userManager" address="/UserManager"
implementorClass="com.pgw.test.webservice.IHelloService">
<jaxws:implementor>
<bean id="userServiceImpl" class="com.pgw.test.webservice.HelloServiceImpl">
</bean>
</jaxws:implementor>
<!-- 加入拦截器 -->
<jaxws:inInterceptors>
<ref bean="inInter" />
<ref bean="outInter" />
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
5) web.xml配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFService</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
完成上述操作后发布web程序,在浏览器中输入
http://127.0.0.1:8080/CXFDemo/UserManager?wsdl查看服务。另外在部署中可能会遇到JAXB 2.0 API is being loaded from the bootstrap classloader这个错误,这是因为cxf2.2.5需要jaxb-api-2.1.jar支持,而低版本的jdk1.6默认的是jaxb-api-2.0.jar,解决办法如下:
重新构建一个相同类型的项目(不同的项目类型,输出的结果不一样),在项目中打印输出System.getProperty("java.endorsed.dirs"),如果文件系统中不存在输出的目录则创建,把jaxb-api-2.1.jar放置到该目录下,问题解决。
3 构建客户端
3.1 WSDL2Java构建客户端
WSDL2Java位于cxf的bin目录下,可以根据wsdl生成java客户端代码。在命令行中输入 WSDL2JAVA –help 可以获取该指令的帮助。
如下所示:
wsdl2java -frontend jaxws21
-p com.ailk.demo.webservice.client.wsdl2Java
-d D:\workspace\olcom5\CXFDemo\src\ http://localhost:8080/CXFDemo/services/HelloWorld?wsdl
客户端生成后进行调用:
publicclass ClientMain {
publicstaticvoid main(String[] args) {
IHelloWorld helloWorld = new IHelloWorld();
IHelloWorldPortType client = helloWorld.getIHelloWorldPort();
String resultStr = client.sayHello("test");
System.out.println("HelloWorld webService response :" + resultStr);
}
}
3.2 JAX-WS Proxy构建客户端
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import com.ailk.demo.service.IHelloWorld;
publicclass ClientMain {
publicstaticvoid main(String[] args) throws MalformedURLException {
URL wsdlURL = new URL("http://localhost:9000/helloWorld?wsdl");
QName SERVICE_NAME = new QName("http://impl.service.demo.ailk.com/", "HelloWorldImplService");
QName PORT_NAME = new QName("http://impl.service.demo.ailk.com/", "HelloWorldImplPort");
Service service = Service.create(wsdlURL, SERVICE_NAME);
IHelloWorld client = service.getPort(PORT_NAME, IHelloWorld.class);
String result = client.sayHello("test");
System.out.println("HelloWorld webService response :" + result);
}
}
3.3 JaxWsProxyFactoryBean构建客户端
JaxWsProxyFactoryBean简化了Proxy
publicclass ClientMain {
publicstaticvoid main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(IHelloWorld.class);
factory.setAddress("http://localhost:9000/helloWorld?wsdl");
IHelloWorld client = (IHelloWorld) factory.create();
String result = client.sayHello("test");
System.out.println("HelloWorld webService response :" + result);
}
}
3.4 JaxWsClientProxy动态客户端
DynamicClientFactory factory = DynamicClientFactory.newInstance();
Client client = factory.
createClient("http://localhost:8080/CXFDemo/services/HelloWorld?wsdl");
try {
Object[] objs = client.invoke("sayHello",
new Object[] { "test" });
System.out.println("HelloWorld webService response :" + objs[0]);
} catch (Exception e) {
e.printStackTrace();
}
3.5 JaxWsDynamicClientFactory动态客户端
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.ConduitSelector;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.endpoint.UpfrontConduitSelector;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
publicclass ClientMain {
publicstaticvoid main(String[] args) throws Exception {
JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
Client client = dcf.createClient("http://localhost:8080/CXFDemo/services/HelloWorld?wsdl");
// sayHello 为接口中定义的方法名称 test为传递的参数返回一个Object数组
Object[] objects = client.invoke("sayHello", "test");
// 输出调用结果
System.out.println("HelloWorld webService response :" + objects[0]);
// 动态设置Address
Endpoint ep = client.getEndpoint();
ep.getEndpointInfo().setAddress("http://localhost:8080/CXFDemo/services/HelloWorld");
ConduitSelector cs = new UpfrontConduitSelector();
cs.setEndpoint(ep);
client.setConduitSelector(cs);
// 设置连接超时时间、相应超时时间
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(60000);
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setReceiveTimeout(600000);
http.setClient(httpClientPolicy);
objects = client.invoke("sayHello", "test");
// 输出调用结果
System.out.println("HelloWorld webService response :" + objects[0]);
}
}
客户端创建的过程中,生产服务下所有的方法类、参数类、返回值类,耗时比较惊人,建议在实际应用中预先初始化。
在实际的项目应用中,有这样的场景,提供的服务是相同的,但是服务地址会随着业务的需求动态的变化,就需要我们动态的设置服务地址。
相关推荐
2013版的 <基于Apache CXF构建SOA应用> 源码 Apache CXF是一个开放源码的Web服务框架,提供了一个易于使用,用于开发Web Services标准为基础的编程模型。本书主要介绍Apache CXF在构建SOA架构各个方面的应用说明和...
基于Apache CXF构建SOA应用
**基于CXF的Web服务发布及访问** 在Java开发中,Apache CXF是一个广泛使用的开源框架,用于构建和实现Web服务。本教程将详细介绍如何利用CXF发布基于SOAP 1.2的Web服务,以及如何进行客户端调用。首先,我们需要...
在这个基于CXF的Web服务完整例子中,我们将深入探讨CXF的核心概念、配置、以及如何创建和调用Web服务。 1. **CXF框架介绍**:CXF,全称为"Code first eXtended Framework",最初由XFire项目发展而来,后与Apache ...
【标题】基于CXF 2.7.5开发的WebService:SOAP与RESTful详解 【描述】本项目是使用Apache CXF 2.7.5版本实现的WebService服务,包括了SOAP和RESTful两种常见的Web服务接口。Apache CXF是一个开源的Java框架,它为...
本篇文章将深入探讨基于CXF框架实现Web服务的示例,帮助开发者理解并掌握CXF的核心概念和技术。 1. **CXF框架介绍** - CXF全称为"Code first, XSD first", 强调从代码或XML Schema开始构建服务,提供了丰富的API和...
在具体技术实现上,CXF使用了Spring框架,从而使得WebService的开发能够利用Spring的依赖注入、声明式事务等特性,增强了应用的可维护性和扩展性。 总结来说,Apache CXF是一个功能强大的WebService开发框架,它...
【标题】"基于CXF+servlet整合spring接口系统"揭示了这个项目的核心是构建一个集成了Spring、CXF和Servlet的Web服务接口系统。这里主要涉及的技术栈包括Spring框架、CXF作为服务消费和发布的工具,以及Servlet 3.0...
【基于CXF构建SOA例子代码】是一个针对Java开发者的学习资源,主要展示了如何利用Apache CXF框架来构建面向服务架构(Service-Oriented Architecture, SOA)的应用程序。CXF是一个开源项目,它提供了多种方式来创建...
下面将详细阐述基于CXF的Web Service以及与Spring的整合。 **一、CXF Web Service** Apache CXF是一个强大的Web服务框架,它支持SOAP、RESTful等多种服务风格。CXF允许开发者通过Java编程模型创建和消费Web服务,...
### 基于CXF的WebService接口开发及调用步骤详解 #### 一、概述 在当前企业级应用开发中,服务化与微服务架构逐渐成为主流趋势,而WebService作为一种跨语言、跨平台的服务交互方式,在众多场景下仍然发挥着重要...
【基于CXF的Web服务开发】是Web服务领域中一种基于开源框架CXF实现的方式,它为企业级应用程序提供高效、灵活的服务集成方案。CXF是一个强大的、全面的开放源码服务框架,支持多种Web服务标准,包括SOAP、RESTful、...
本文将深入探讨基于Apache CXF实现的Web Service在本地数据交互中的应用,尤其是如何在PC端与Android端之间进行通信。Apache CXF是一个开源框架,专门用于构建和消费Web服务,支持多种协议和标准,如SOAP、RESTful等...
在本篇博文中,我们将深入探讨如何利用Apache CXF库创建和实现基于Web Service的本地数据交互,特别是在PC端的应用。Apache CXF是一个开源框架,它允许开发者构建和部署服务,支持多种Web服务规范,如SOAP、RESTful...
本实例将深入讲解如何使用Apache CXF构建一个基于WebService的应用。首先,我们需要了解CXF的基本概念。CXF包含了服务器端和客户端的API,服务器端API用于实现服务接口并将其暴露为Web服务,客户端API则用于调用这些...
5. **集成其他技术**:CXF可以与Spring框架无缝集成,使得服务的配置和管理更加简单。此外,它还支持WS-Security等Web服务安全标准,为服务提供安全保护。 6. **客户端API**:CXF提供了一种简单易用的客户端API,...