1 Apache CXF 简介
Apache CXF =Celtix + XFire,开始叫 Apache CeltiXfire,后来更名为
Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种
Binding 、DataBinding、Transport
以及各种 Format
的支持,并且可以根据实际项目的需要,采用代码优先(Code First)或者 WSDL
优先(WSDL First)来轻松地实现 Web Services
的发布和使用。Apache CXF已经是一个正式的Apache顶级项目。
Apache CXF 是一个开源的 Services
框架,CXF 帮助您利用 Frontend 编程 API 来构建和开发 Services ,像 JAX-WS 。这些 Services 可以支持多种协议,比如:SOAP、XML/HTTP、RESTful
HTTP 或者 CORBA ,并且可以在多种传输协议上运行,比如:HTTP、JMS
或者 JBI,CXF 大大简化了 Services 的创建,同时它继承了 XFire 传统,一样可以天然地和 Spring 进行无缝集成。
支持多种协议:
a) SOAP1.1,1,2
b) HTTP
c) CORBA(CommonObject Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)
d) 并可以与Spring进行快速无缝的整合
e) 灵活的部署:可以运行有Tomcat,Jboss,Jetty(内置),IBMWS,BeaWS上面。
2 环境搭建
a) JAVA_HOME 需要jdk的支持
b) CXF_HOME
c) CATALINA_HOME
e)
Path=%JAVA_HOME%\bin;%CXF_HOME%\bin;%CATALINA_HOME%\bin;%ANT_HOME%\bin
CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar;.\build\classes
3 cxf第一个DEMO(通过类来发布服务)
1. 创建java项目(cxf-server)
2. 引入所有依赖包
3. 创建服务类(HelloService.java)这里发布SOAP1.2的服务
@WebService
@BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public
class HelloService {
public String sayHello(String name){
return name +
" hello";
}
}
4. 创建具体的发布服务类(CXFHelloServiceServer.java)
public
class CXFHelloServiceServer {
public
static void main(String[] args) {
// 创建服务工厂对象
JaxWsServerFactoryBean sfb = new JaxWsServerFactoryBean();
// 加入输入输出拦截器
sfb.getInInterceptors().add(new LoggingInInterceptor());
sfb.getInInterceptors().add(new LoggingOutInterceptor());
// 指定服务地址
sfb.setAddress("Http://127.0.0.1:6666/hello");
// 设置服务类
sfb.setServiceClass(HelloService.class);
// 设置服务类的实例对象
sfb.setServiceBean(new HelloService());
// 发布服务
sfb.create();
System.out.println("server ready...");
}
}
比较用两个不同的类发布应用:
1,ServerFactoryBean(不需要使用@webservice) 生成的文档不规范,不建议使用
2,JaxWsServerFactoryBean(建议使用此类,需要使用@webservice) 生成的文档也不太规范但可以通过@webservice进行指定
注意:cxf支持可以发布SOAP1.1和SOAP1.2的协议,SOAP1.2的协议中cxf的服务类没有方法时也可以发布成功,不报错。默认发布的是SOAP1.1协议,如果要发布SOAP1.2的协议需要在服务类中使用@bindType注解指定如上面所示。
当使用SOAP1.2时wsimport命令失效,需要使用cxf的wsdl2java
建议:发布服务的时候使用SOAP1.2,客户端调用的时候使用SOAP1.1,因为SOAP1.1的客户端可以调SOAP1.1和SOAP1.2服务端的代码。
4,wsdl2java介绍
在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就和wsimport差不多,但wsdl2java既可以生成SOAP1.1也可以生成SOAP1.2
此工具位于cxf_home/bin目录下。参数与wsimport有所不同。
它包含以下参数:
a) -d参数,指定代码生成的目录。
b) -p参数,指定生成的新的包结构。
需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。
5.通过wsimport/wsdl2java(SOAP1.1)命令生成客户端代码
打开windows命令操作界面,进入到f:/wsCode目录下,输入命令:wsdl2java –d
. –pcom.test.helloService http://127.0.0.1:6666/hello?wsdl,将生产的代码复制到创建的客户端项目(cxf-client)中。
6. 调用webservice,创建类(HelloServiceClient.java)客户端代码如下:
public
static void main(String[] args) {
HelloServiceService hss = new HelloServiceService();
HelloService hs =hss.getHelloServicePort();
String result = hs.sayHello("小明");
System.out.println(result);
}
4 通过接口来发布服务
1.创建服务接口(HI.java)
@WebService//注意注解加在接口上
public
interface HI {
public String sayHi(String name);
}
2.创建接口实现类(HIImpl.java)
public
class HIImpl implements HI {
@Override
public String sayHi(String name) {
// TODO Auto-generatedmethod stub
return name +
"hello";
}
}
3.创建发布服务类(CXFHIInterServer.java)
public
static void main(String[] args) {
JaxWsServerFactoryBeanjf =
new
JaxWsServerFactoryBean();
jf.setAddress("http://127.0.0.1:5555/hi");
jf.setServiceClass(HI.class);
jf.setServiceBean(new HIImpl());
jf.create();
}
5. 生成客户端代码
打开windows命令操作界面,进入到f:/wsCode目录下,输入命令:wsdl2java –d
. –pcom.test.hiService http://127.0.0.1:5555/hi?wsdl,将生产的代码复制到创建的客户端项目(cxf-client)中。
5.调用webservice,客户端代码如下:
public
class Client {
public
static void main(String[] args) {
HIService hs = new HIService();
HI serviceClass = hs.getHIPort();
System.out.println(serviceClass.sayHi("张三"));
}
}
5 在web项目中创建类的cxf服务
1.创建web项目(cxf-web-server)
2.导入所有包,(apache-cxf-2.4.2\lib)
3.创建服务类,必须指定注解@webService
@WebService//所用的webservice服务类都要要加@webservice,接口的形式加在接口上
public
class HelloService {
public String sayHello(String name){
return name +
" hello";
}
4.这里不能通过发布服务类来发布webservice,需要在项目WebRoot/WEB-INF下创建并配置web.xml,
<!DOCTYPE
web-app PUBLIC
"-//SunMicrosystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
2. 默认情况下需要在WebRoot/WEB-INF下创建cxf的核心配置文件cxf-servlet.xml,并且文件名必须是cxf-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"xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrshttp://cxf.apache.org/schemas/jaxrs.xsd
http://cxf.apache.org/jaxwshttp://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/corehttp://cxf.apache.org/schemas/core.xsd">
<!-- 引入CXF Bean定义如下,早期的版本中使用
-->
<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"/>
<!--
===============配置类的形式webservice服务=================
address:tomcat的host http://ip:port/projectName/service/后面的一端路径
http://ip:port/projectName/service/hello
implementor:指定具体的服务的类
-->
<jaxws:endpoint
id="hello"
address="/hello"implementor="com.rl.cxf.web.server.HelloService">
<jaxws:outInterceptors>
<!-- 输入拦截器,打印输入的消息 -->
<bean
class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:outInterceptors>
<jaxws:inInterceptors>
<bean
class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
3. 修改cxf-servlet.xml的位置和文件名
<?xml
version="1.0"encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"version="2.5">
<!-- 第一种方式修改cxf-servlet.xml文件的名称为cxf-.xml,位置在(src路径下)
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:cxf.xml</param-value>
</context-param>
<servlet>
<servlet-name>cxf</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<!-- 第二种方式修改cxf-servlet.xml文件的名称为cxf-.xml,位置在(src路径下)
-->
<!-- <init-param>
<param-name>config-location</param-name>
<param-value>classpath:cxf.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>-->
</servlet>
<servlet-mapping>
<servlet-name>cxf</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
</web-app>
4. 使用wsdl2java生成客户端代码(和之前的步骤一样)
5. 调用webservice
6 在web项目中创建接口的cxf服务
1. 创建服务接口在接口上加@webservice
@WebService
public
interface ByeInter {
public String sayBye(String name);
}
2. 导入相应的JAR包(apache-cxf-2.4.2\lib)
3. 创建服务接口的实现类
public
class ByeInterImpl implements ByeInter {
@Override
public String sayBye(String name) {
return name +
" bye";
}
}
4. 和在类中发布服务一样,创建并配置web.xml文件
5. 配置cxf-servlet.xml(这里和在类中配置的不一样)
<jaxws:server
address="/bye"
serviceClass="com.rl.web.server.inter.ByeInter">
<!-- 服务接口的实现类 -->
<jaxws:serviceBean>
<bean
class="com.rl.web.server.inter.ByeInterImpl"></bean>
</jaxws:serviceBean>
<jaxws:inInterceptors>
<bean
class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean
class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:server>
6. 使用wsdl2java生成客户端代码
7. 调用webservice
7 使用jquery调用cxf
1, 使用上面再web项目中通过接口发布出来的服务
2, 创建一个web项目(cxf-web-4jquery-client)
3, 创建一个HTML页面并引入jquery.js文件(testjquery.html)
<!DOCTYPE
html PUBLIC
"-//W3C//DTDHTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta
http-equiv="Content-Type"content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script
type="text/javascript"src="js/jquery.js"></script>
<script
type="text/javascript">
$(function(){
$("#mybutton").click(function(){
//获得文本的值
var mytext = $("#mytext").val();
//组装消息体
var data = ‘<?xmlversion="1.0" ?><S:Envelopexmlns:S="http://schemas.xmlsoap.org/soap/envelope/">‘
+‘<S:Body><ns2:sayByexmlns:ns2="http://inter.server.web.rl.com/">‘
+‘<arg0>‘+mytext+‘</arg0>‘
+‘</ns2:sayBye>‘
+‘</S:Body>‘
+‘</S:Envelope>‘;
$.ajax({
url:‘http://localhost:8080/cxf-web-server/service/bye‘,
type:‘post‘,
dataType:‘xml‘,//返回值的数据类型
contentType:‘text/xml;charset=UTF-8‘,//指定发送的数据类型
data:data,//发送的消息体
success:function(responseText){
//解析消息体
var
returnObj =$(responseText).find("return");
alert(returnObj.text());
},
error:function(){
alert(‘systemerror‘);
}
});
});
});
</script>
</head>
<body>
<input
type="text"id="mytext">
<input
type="button"id="mybutton"
value="通过jquery的ajax调用服务">
</body>
</html>