基于CXF框架的WebService

Apache CXF = Celtix + Xfire

支持多种协议:
SOAP1.1,SOAP1,2
XML/HTTP
RESTful (REpresentation State Transfer )
CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)

支持多种数据格式:XML , JSON

并可以与Spring进行快速无缝的整合
灵活的部署:可以运行有Tomcat,Jboss,Jetty(内置web服务器),IBMWebSphera,BeaWebLogic上面。

官网的下载路径:http://cxf.apache.org/download.html

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定义如下:
<bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl" />
核心bus组件是CXFBusImpl,该类更多扮演拦截器供应商的角色对于终端出入的请求.
这些拦截器一旦应用,即可用于上下文中所有的终端.cxf.xml文件也定义了其他的组件,比如BindingFactoryManager, ConduitFactoryManager等等.这些组件可用于bus
的扩展.可以使用getExtension()方法这些组件.注册这些组件以用于获取或更新服务终端级别参数如服务绑定,传输协议,中转等等.

Frontend
CXF提供了前端建模的概念,可以使用不同的前端API创建ws.这些API使用简单工厂bean和JAX-WS实现创建ws.可以创建动态ws客户端.CXF支持的前端主要是JAX-WS.

Message and intercetpors:
消息和拦截器
CXF框架中重要的组件之一是拦截器组件.拦截器拦截客户端和服务器间的消息.在CXF,这通过拦截器链的概念实现.拦截器链是CXF运行时的核心功能.链中的每个拦截器是可配的,用户可以控制他的执行.
框架的核心的是拦截器接口,它定义了两个方法handleMessage和handleFault,都携带Message类型作为参数.

拦截器通常分组成各阶段.每个阶段执行特定的消息处理,每个阶段又被添加到拦截器链中,因此,链有时有序的拦截器阶段的列表.典型的ws终端有三个连接器链:
Inbound messages chain(入消息链)
Outbound messages chain(出消息链)
Error messages chain(错误消息链)
内置拦截器如日志,安全,也可以自定义拦截器.

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
	…
}

协议绑定:protocol bindings
CXF支持以下形式的绑定:
SOAP1.1
SOAP1.2
CORBA
Pure XML

数据传输——transport
CXF支持以下数据传输方式:
HTTP
CORBA
JMS
LOCAL


安装CXF的其他支持项目:

MAVEN - 支持发布、运行和测试。

并设置以下环境变量:
JAVA_HOME  
CXF_HOME
MAVEN_HOME

Path 添加
%JAVA_HOME%\bin;%CXF_HOME%\bin;MAVEN_HOME%\bin

CLASSPATH 添加
.;%CXF_HOME%\lib\cxf-manifest.jar;.\build\classes

在配置好以上环境后在命令行模式下进入cxf_home\samples\java_first_pojo
按照README.txt的提示进行操作。
主要是以下三个命令:

  mvn install   (builds the demo)
  mvn -Pserver  (from one command line window)
  mvn -Pclient  (from a second command line window)

先打开一个终端,输入mvn install ,然后出现以下信息的时候表示运行成功。
这里写图片描述

然后输入mvn -Pserver ,运行成功后会出现以下信息:
这里写图片描述

然后新打开一个终端,切换到相应的目录下输入 mvn -Pclient ,然后会在客户端打印如下信息:
这里写图片描述

在服务器端打印如下信息:
这里写图片描述

核心源码片段:
server端

HelloWorldImpl helloworldImpl = new HelloWorldImpl();
        ServerFactoryBean svrFactory = new ServerFactoryBean();
        svrFactory.setServiceClass(HelloWorld.class);
        svrFactory.setAddress("http://localhost:9000/Hello");
        svrFactory.setServiceBean(helloworldImpl);
        //svrFactory.getServiceFactory().setDataBinding(new AegisDatabinding());
        svrFactory.create();

client端

 ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
        if (args != null && args.length > 0 && !"".equals(args[0])) {
            factory.setAddress(args[0]);
        } else {
            factory.setAddress("http://localhost:9000/Hello");
        }
        HelloWorld client = factory.create(HelloWorld.class);
        System.out.println("Invoke sayHi()....");
        System.out.println(client.sayHi(System.getProperty("user.name")));
        System.exit(0);

在Eclipse中开发CXF的JavaSE应用:

CXF发布服务的类:
JaxWsServerFactoryBean
JaxWsServerFactoryBean用于发布一个服务,可以通过默认构造实例此类。
它的方法如下:
setServiceBean(Object) – 设置一个服务对象 - *
setAddress(String url) – 绑定一个地址和端口 - *
create() - 在JavaSE环境下,使用jetty发布WebService. - *
以下是可选方法 :
setServiceClass(Class cls) – 设置服务对象实现的接口类。
JaxRsServerFactoryBean
此类用于发布RESTful风格的webService.
RESTful风格是以普通get,post请求为标准的,并可以请求和响应json数据。

CXF发布服务的类,其实是有两个,另一个是ServerFactoryBean它是JaxWsServerFactoryBean的父类。

server端代码示例:

/*

如果不是使用spring的配置文件发布,可以没有接口文件,但在任何情况下建议拥有接口文件。如果使用spring的配置文件发布,则必须要拥有接口类。

*/

package com.cxf.my;

import javax.jws.WebService;

@WebService
public interface HelloWorld {

	String sayHi(String name);
	
}

package com.cxf.my;

import javax.jws.WebService;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

@WebService
public class HelloWorldCXF implements HelloWorld{
	
	@Override
	public String sayHi(String name){
		System.out.println("CXF Server sayHi...");
		return "Hi " + name;
	}
	
	public static void main(String[] args) throws Exception{
		
		JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
		svrFactory.setServiceClass(HelloWorldCXF.class);
        svrFactory.setAddress("http://localhost:9000/helloWorld");
        svrFactory.setServiceBean(new HelloWorldCXF());
        svrFactory.getInInterceptors().add(new LoggingInInterceptor());//信息输入时的拦截器 –请求
        svrFactory.getOutInterceptors().add(new LoggingOutInterceptor());//信息输出时的拦截器-响应
        svrFactory.create();
        
	}
	

}

client端

package com.cxf.my;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class TestClient {

	public static void main(String[] args) {
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.getInInterceptors().add(new LoggingInInterceptor());
        factory.getOutInterceptors().add(new LoggingOutInterceptor());
        factory.setAddress("http://localhost:9000/helloWorld");
        HelloWorld client = factory.create(HelloWorld.class);
        System.out.println(client.sayHi("World"));
	}
	
}


终端运行
wsimport -s . -p com.my.cxf http://localhost:9000/helloWorld?wsdl
然后将生成的代码导入新工程中进行测试:

HelloWorldCXF service = new HelloWorldCXFService().getHelloWorldCXFPort();
		String str = service.sayHi("Rose");
		System.out.println(str);

wsdl2java生成客户代码:
在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。
先让我们了解一下cxf的wsdl2java工具,可以生成一堆客户端调用的代码。
此工具位于cxf_home/bin目录下。参数与wsimport有所不同。
它包含以下参数:
-d参数,指定代码生成的目录。
-p参数,指定生成的新的包结构。
需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。
在命令行执行:
在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。
先让我们了解一下cxf的wsdl2java工具,可以生成一堆客户端调用的代码。
此工具位于cxf_home/bin目录下。参数与wsimport有所不同。
它包含以下参数:
-d参数,指定代码生成的目录。
-p参数,指定生成的新的包结构。
需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。
在命令行执行:
wsdl2java –d . http://127.0.0.1:6666/helloworld?wsdl

使用本JavaScript也可以访问WebServie:
jQuery访问WebService.
1、在本域准备jquery.js (由于jquery对跨域的请求做了限制,所以jquery仅限于在本域中使用。但为了快速解析XML文件,仍然可以使用jquery当成解析xml文件的工具。)。
2、通过js发起ajax请求。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
  <head>
  	<script type="text/javascript" src="<c:url value='/js/jquery-1.6.2.js'/>"></script>
  </head>
  <body>
    <p>用js来控制的客户端</p>
	<button id="all">显示所有</button><br/>
	<hr/>
	Name:<input type="text" id="_name">,Age:<input type="text" id="_age">
	<button id="add">增加一个</button><br/>
	<table id="tb" width="70%" border="1">
		<tr>
			<th>学生姓名</th>
			<th>学生年龄</th>
		</tr>
	</table>
  </body>
  <script type="text/javascript">
  	 $(function(){
  		 var url = "http://localhost:7777/xcxf3_ss/ws/studQuery";
  		 $("#all").click(function(){
  			 //查询时必须向服务器发以下xml文件
  			 var xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'+
  			 		   '<soap:Body><ns2:query xmlns:ns2="http://service.stud.cn/"/>'+
  			 		   '</soap:Body></soap:Envelope>';
  			 $.ajax({
  				 url:url,
  				 type:'post',
  				 dataType:'xml',
  				 contentType:'application/soap+xml;charset=UTF-8',
  				 data:xml,
  				 success:function(data){
					 $("#tb tr:gt(0)").remove();//删除所有列	
					 //遍历data
					 $(data).find("return").each(function(){
						 var name = $(this).find("name").text();
						 var age  = $(this).find("age").text();
						 var tr = $('<tr><td>'+name+'</td><td>'+age+'</td></tr>');
						 tr.appendTo("#tb");
					 });
  				 }
  			 });
  			 //以下是增加
  			 $("#add").click(function(){
  				 var nm = $("#_name").val();
  				 var age = $("#_age").val();
  				 if($.trim(nm)=="" || $.trim(age)==""){
  					alert('姓名和年龄必须输入');	 
  				 }
  				 //以下是保存服务的xml
  				 var xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
  				 		   +'<soap:Body><ns2:add xmlns:ns2="http://service.stud.cn/">'
  				 		   +'<arg0><age>'+age+'</age><name>'+nm+'</name></arg0></ns2:add>'
  				 		   +'</soap:Body></soap:Envelope>';
  				 $.ajax({
  					 url:url,
  					 type:'post',
  					 dataType:'xml',
  					 contentType:'application/soap+xml;charset=UTF-8',
  					 data:xml,
  					 success:function(){
						alert('保存成功');  						 
  					 }
  				 });
  			 });
  		 });
  	 });
  </script>
</html>


Coding Diary

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值