1. CXF框架
1.1 什么是CXF框架
Apache CXF 是一个开源的 Services 框架,CXF 帮助您来构建和开发 Services 这些 Services 可以支持多种协议,
比如:SOAP、POST/HTTP、RESTful HTTP CXF 大大简化了 Service可以天然地和 Spring 进行无缝集成。
CXF框架是一个实现SOA思想的一个框架
- CXF 是 Celtrix (ESB框架)和 XFire(webserivice) 合并而成,并且捐给了Apache
- CXF的核心是org.apache.cxf.Bus(总线),类似于Spring的 ApplicationContext
- CXF默认是依赖于Spring的
- Apache CXF 发行包中的jar,如果全部放到lib中,需要 JDK1.6 及以上,否则会报JAX-WS版本不一致的问题
- CXF 内置了Jetty服务器 ,它是servlet容器,好比tomcat
1.2 为什么使用CXF框架
- 与Spring、Servlet做了无缝对接,CXF框架里面集成了Servlet容器Jetty
- 支持注解的方式来发布WebService
- 能够显示一个WebService的服务列表
- 能够添加拦截器:输入拦截器、输出拦截器 :
输入日志信息拦截器、输出日志拦截器、用户权限认证的拦截器
1.3 怎么使用
1.3.1 添加所需的JAR包
所有的jar包一览
其他必备的包,日志等jar包
- asm-3.3.jar :spring aop 的一个依赖包,字节码包,通过这个包来进行一些反射的调用
- com.springsource.org.apache.commons.httpclient-3.1.0.jar
- commons-codec-1.3.jar
- commons-logging-1.1.1.jar
CXF框架所需的包
- cxf-2.4.2.jar
- neethi-3.0.1.jar
- wsdl4j-1.6.2.jar
- xmlschema-core-2.0.jar
- Jetty的jar包CXF框架需要依赖Jetty
- jetty-continuation-7.4.5.v20110725.jar
- jetty-http-7.4.5.v20110725.jar
- jetty-io-7.4.5.v20110725.jar
- jetty-security-7.4.5.v20110725.jar
- jetty-server-7.4.5.v20110725.jar
- jetty-util-7.4.5.v20110725.jar
1.3.2 编写发布的服务接口的类
需求: 想要根据输入的排名返回对应的编程语言.
CodeLanguage.java<接口>:
package com.service.cxf;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
/**
* 编程语言排行的接口
*
*/
@WebService(serviceName="CodeLanguageService")
public interface CodeLanguage {
public @WebResult(name="codeName")String getCodeRank(@WebParam(name="codeRank")int num);
}
CodeLanguageImpl.java实现类:
package com.service.cxf;
/**
* 实现类
*/
public class CodeLanguageImpl implements CodeLanguage {
public String getCodeRank(int num){
String language = null;
switch(num){
case 1: language = "Java";break;
case 2: language = "C";break;
case 3: language = "C++";break;
case 4: language = "C#";break;
case 5: language = "Python";break;
default: language = "others";
}
return language;
}
}
1.3.3 使用CXF框架的类来发布服务
通过cxf框架发布webservice
ServerFactoryBean
- 不设置注解也可以发布webservice服务, 不支持注解
- 不支持拦截器的添加
JaxWsServerFactoryBean(常用)
- 支持注解
- 可以添加拦截器
- webservice 访问流程:
- 检测本地代理描述的wsdl是否与服务端的wsdl一致 ,俗称为握手
通过soap协议实现通信 ,采用的是post请求 , 数据封装在满足soap规约的xml中 - 返回数据 同样采用的是soap通信, 数据封装在满足soap规约的xml中
- 检测本地代理描述的wsdl是否与服务端的wsdl一致 ,俗称为握手
TestCXFPublish.java发布的方法:
public static void main(String[] args) {
//1. 创建服务类的对象
CodeLanguage cl = new CodeLanguageImpl();
String address = "http://127.0.0.1:6969/ws/CodeLanguageService";
//2. 创建发布服务的对象 JaxWsServerFactoryBean
JaxWsServerFactoryBean js = new JaxWsServerFactoryBean();
//2.1 设置发布的地址
js.setAddress(address);
//2.2 设置发布的服务对象
js.setServiceBean(cl);
//2.3 设置发布的服务接口类型,对外提供该服务的接口的引用
js.setServiceClass(CodeLanguage.class);
//3. 创建WebService服务,并发布
js.create();
System.out.println("WSDL:"+address+"?WSDL");
//http://127.0.0.1:6969/ws/CodeLanguageService?WSDL
}
1.3.4 客户端调用
- 创建一个temp文件夹,使用CMD打开
解析WSDL文件生成本地代理及其源码
wsimport -s . -d ./ -p com.client.wxf http://127.0.0.1:6969/ws/CodeLanguageService?WSDL
打包
jar -cvf cxf.jar ./
WSDL释义
<?xml version="1.0" ?>
<wsdl:definitions name="CodeLanguageService"
targetNamespace="http://cxf.service.com/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://cxf.service.com/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<!-- tns 类型的描述 -->
<wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="http://cxf.service.com/"
version="1.0" xmlns:tns="http://cxf.service.com/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="getCodeRank" type="tns:getCodeRank"></xs:element>
<xs:element name="getCodeRankResponse" type="tns:getCodeRankResponse"></xs:element>
<xs:complexType name="getCodeRank">
<xs:sequence>
<xs:element name="codeRank" type="xs:int"></xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="getCodeRankResponse">
<xs:sequence>
<xs:element minOccurs="0" name="codeName" type="xs:string"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<!-- 描述参数及其类型 -->
<wsdl:message name="getCodeRankResponse">
<wsdl:part element="tns:getCodeRankResponse" name="parameters">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getCodeRank">
<wsdl:part element="tns:getCodeRank" name="parameters">
</wsdl:part>
</wsdl:message>
<!-- 暴露出去的方法的描述,以及对应的描述类型 tns-->
<wsdl:portType name="CodeLanguage">
<wsdl:operation name="getCodeRank">
<wsdl:input message="tns:getCodeRank" name="getCodeRank">
</wsdl:input>
<wsdl:output message="tns:getCodeRankResponse" name="getCodeRankResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="CodeLanguageServiceSoapBinding" type="tns:CodeLanguage">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"></soap:binding>
<!-- 暴露出去的方法soap格式的描述 -->
<wsdl:operation name="getCodeRank">
<soap:operation soapAction="" style="document"></soap:operation>
<!-- 方法的WSDL参数描述 -->
<wsdl:input name="getCodeRank">
<soap:body use="literal"></soap:body>
</wsdl:input>
<!-- 方法的WSDL返回值描述 -->
<wsdl:output name="getCodeRankResponse">
<soap:body use="literal"></soap:body>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<!-- 暴露出去的服务类的描述 -->
<wsdl:service name="CodeLanguageService">
<wsdl:port binding="tns:CodeLanguageServiceSoapBinding"
name="CodeLanguagePort">
<soap:address location="http://127.0.0.1:6969/ws/CodeLanguageService"></soap:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
- 打包的 cxf.jar
- com.client.wxf
- CodeLanguage.class
- CodeLanguageService.class
- GetCodeRank.class
- GetCodeRankResponse.class
- ObjectFactory.class
- package-info.class
以上JAR包中我们需要的是
1. CodeLanguage.class :
wsimport解析后生成的代理的接口,和我们本地的CodeLanguage名字一样,但不能混淆.
2. CodeLanguageService.class :
WSDL包装好的服务接口,调用getCodeLanguagePost()返回CodeLanguage服务对象
- 客户端调用服务接口的方法
public static void main(String[] args) {
CodeLanguageService cls = new CodeLanguageService();
CodeLanguage cl = cls.getCodeLanguagePort();
String rank = cl.getCodeRank(1);
System.out.println("rank:"+rank);//rank:Java
}