@(WebService)[WebService, CXF,wsdl, soap,uddi]
Apache CXF是一个开源的,全功能的,容易使用的Web服务框架。CXF是两个项目的结合:由IONA技术公司(现在是Progress的一部分)开发的Celtix和由Codehaus主持的团队开发的XFire,合并是由人们在Apache软件基金会共同完成的。CXF的名字来源于”Celtix”和”XFire”的首字母。
CXF的关键的设计考虑因素包括:
- 前端,如JAX-WS,与核心代码的彻底分离。
- 简单易用,例如,创建客户端和端点不需标注。
- 高性能,最少的计算开销。
- 可嵌入的Web服务组件:例如可以嵌入到Spring Framework和Geronimo中。
——参考《维基百科》
官网:Apache CXF官方网站
Bus是CXF框架的支撑,CXF Bus由spring配置文件构成(cxf.xml),在servlet初始化时,通过SpringBusFactory加载,它为所有终端定义了公共的上下文。它织入了所有运行时的结构组件并提供了一个公共的应用上下文。SpringBusFactory扫描并加载类路径
下的META-INF/cxf目录并从以下文件构建上下文。
META-INF/cxf/cxf.xml
META-INF/cxf/cxf-extension.xml
META-INF/cxf/cxf-property-editors.xml
XML文件是安装CXF类库的一部分。CXF内部使用Spring配置。cxf.xml文件中bus定义如下:
id="cxf" class="org.apache.cxf.bus.CXFBusImpl" />
核心bus组件是CXFBusImpl,该类更多扮演拦截器供应商的角色对于终端出入的请求。这些拦截器一旦应用,即可用于上下文中所有的终端。cxf.xml文件也定义了其他的组件,比如BindingFactoryManager,ConduitFactoryManager等等。这些组件可用于bus的扩展。可以使用getExtension()方法获取这些组件。注册这些组件以用于获取或更新服务终端级别参数如服务绑定,传输协议,中转等等。
CXF提供了前端建模的概念,可以使用不同的前端API创建ws。这些API使用简单工厂bean和JAX-WS实现创建ws。可以创建动态ws客户端。CXF支持的前端主要是JAX-WS。
CXF框架中重要的组件之一是拦截器组件。拦截器拦截客户端和服务器间的消息。在CXF,这通过拦截器链的概念实现。拦截器链是CXF运行时的核心功能。链中的每个拦截器是可配的,用户可以控制他的执行。
框架的核心的是拦截器接口,它定义了两个方法handleMessage和handleFault,都携带Message类型作为参数。
拦截器通常分组成各阶段。每个阶段执行特定的消息处理,每个阶段又被添加到拦截器链中。典型的ws终端有三个连接器链:
Inbound messages chain(入消息链)
Outbound messages chain(出消息链)
Error messages chain(错误消息链)
CXF提供了一些内置拦截器如日志,安全,当然你也可以自定义拦截器。
Service Model主要用于生成wsdl文件的各个元素。建模service,创建各种WSDL元素如操作,绑定,终端,schema等等。
Data binding是ws开发的关键。它意味着java对象和xml元素之间的映射。数据绑定组件执行这一工作。CXF使用JAXB2.1。JAXB使用注解定义java对象和XML之间的映射.如下:
@XmlRootElement(name="processOrder", namespace="http://localhost/orderprocess")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="processOrder", namespace="http://localhost/orderprocess")
public class OrderProcess {
@XmlElement(name="arg0", namespace="")
private order.Order arg0;
//Gettter and Setter
…
}
CXF支持以下形式的绑定:
- SOAP1.1
- SOAP1.2
- CORBA
- Pure XML
CXF支持以下数据传输方式:
- HTTP
- CORBA
- JMS
- LOCAL
该案例是基于CXF和Spring框架以及Maven构建的。
<properties>
<spring.version>4.1.3.RELEASEspring.version>
<cxf.version>2.4.2cxf.version>
<junit.version>4.10junit.version>
properties>
<dependencies>
<dependency>
<groupId>org.apache.cxfgroupId>
<artifactId>cxf-rt-frontend-jaxwsartifactId>
<version>${cxf.version}version>
dependency>
<dependency>
<groupId>org.apache.cxfgroupId>
<artifactId>cxf-rt-transports-httpartifactId>
<version>${cxf.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-txartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
<scope>testscope>
dependency>
dependencies>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>CXFTestdisplay-name>
<welcome-file-list>
<welcome-file>index.jspwelcome-file>
<welcome-file>index.htmlwelcome-file>
welcome-file-list>
<servlet>
<servlet-name>cxfservlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServletservlet-class>
<init-param>
<param-name>config-locationparam-name>
<param-value>classpath:cfx-conf.xmlparam-value>
init-param>
servlet>
<servlet-mapping>
<servlet-name>cxfservlet-name>
<url-pattern>/service/*url-pattern>
servlet-mapping>
web-app>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>CXFTestdisplay-name>
<welcome-file-list>
<welcome-file>index.jspwelcome-file>
<welcome-file>index.htmlwelcome-file>
welcome-file-list>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:cfx-conf.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<servlet>
<servlet-name>cxfservlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServletservlet-class>
servlet>
<servlet-mapping>
<servlet-name>cxfservlet-name>
<url-pattern>/service/*url-pattern>
servlet-mapping>
web-app>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
beans>
PS:CXF的配置文件由于在web.xml中配置了。所以放在类根目录下。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<bean id="helloCXFService" class="com.pc.cxf.server.impl.HelloCXFServiceImpl"/>
<jaxws:server id="cxfService" address="/hello">
<jaxws:serviceBean>
<ref bean="helloCXFService"/>
jaxws:serviceBean>
jaxws:server>
beans>
PS:出现这个页面说明前面的配置都成功了,可以进行生成客户端代码了。
wsdl2java
命令生成的客户端代码调用命令为:wsdl2java -p com.pc.cxf.client http://localhost:8080/CXFDemo/service/hello?wsdl
在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。
此工具位于{cxf_home}/bin
目录下。参数与wsimport有所不同。
它包含以下参数:
- -d
: 指定代码生成的目录。
- -p
: 指定生成的新的包结构。
- (wsdlurl)
: http://server:port/service?wsdl
,必须的参数。
PS:之后的使用方式和《Web Service入门》中一样,这里不再赘述。
wsdl2java
命令生成客户端代码 HelloCXFService.java
PS:需要删除@XmlSeeAlso({ObjectFactory.class})
这条注解,否则会报错。
applicationContext.xml
放在类的根路径下
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:soap="http://cxf.apache.org/bindings/soap"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd">
<jaxws:client id="cfxClient"
address="http://localhost:8080/CXFDemo/service/hello"
serviceClass="com.pc.cxf.client.HelloCXFService"/>
beans>
package com.pc.cxf.client.test;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.pc.cxf.client.HelloCXFService;
/**
* 测试CXF服务
*
* @author Switch
* @data 2016年12月22日
* @version V1.0
*/
public class HelloCXFServiceTest {
ApplicationContext context = null;
@Before
public void init() {
context = new ClassPathXmlApplicationContext("applicationContext.xml");
}
@Test
public void testService() {
// 获取代理对象
HelloCXFService proxy = context.getBean("cfxClient", HelloCXFService.class);
// 调用方法
System.out.println(proxy.helloCXF("Switch"));
System.out.println(proxy.byeCXF());
}
}
GitHub:CXFDemo