CXF客户端请求服务流程

本文主要解析了在使用CXF客户端调用SOAP协议服务时的请求流程,重点介绍了第7、9、12、16号拦截器的作用。这些拦截器包括MessageSenderInterceptor、StaxOutInterceptor、BareOutInterceptor以及MessageSenderInterceptor的MessageSenderEndingInterceptor,它们在请求过程中扮演了关键角色。
摘要由CSDN通过智能技术生成
CXF(使用版本2.7.6)对Web服务封装度已经非常高了,你只需要像正常写代码一样,附加几个额外的注解直接发布,服务端差不多就完成了;对于客户端更简单,只需要知道Web服务的URL地址和接口,就能如调用本地代码一样,几乎感觉不到与本地代码有什么区别。这就是封装的威力,虽然高度封装简化了我们对Web服务的使用,但也间接地阻挡了我们对其深入了解。本文就将源码层面来分析CXF其内部是如何完成客户端对Web服务的调用封装的,但并不包含服务端对服务请求的处理过程,如有需要可参看上篇,CXF中Web服务请求处理流程。

以SOAP协议服务为例,当我们使用代码调用Web服务时,一般情况如下:

JaxWsProxyFactoryBean factoryBean = new JaxWsProxyFactoryBean();
String address = "...";//Web服务发布地址
factoryBean.setAddress(address);
factoryBean.setServiceClass(HelloService.class);//Web服务接口
HelloService helloService = factoryBean.create(HelloService.class);
helloService.sayHello("xtayfjpk");

最重要的当然是factoryBean.create()方法了,从代码表面上看,只知道其返回了一个实现了HelloService接口类实例,但它具体到底是什么呢?这当然就得去看看源码了:


public <ProxyServiceType> ProxyServiceType create(Class<ProxyServiceType> serviceClass) {
	setServiceClass(serviceClass);
	//看上去很简单啊,别急,操作都是create()方法中呢
	return serviceClass.cast(create());
}

public synchronized Object create() {
	ClassLoaderHolder orig = null;
	try {
		if (getBus() != null) {
			ClassLoader loader = getBus().getExtension(ClassLoader.class);
			if (loader != null) {
				orig = ClassLoaderUtils.setThreadContextClassloader(loader);
			}
		}
		//配置this,即JaxWsProxyFactoryBean对象
		configureObject();
		
		if (properties == null) {
			properties = new HashMap<String, Object>();
		}

		if (username != null) {
			AuthorizationPolicy authPolicy = new AuthorizationPolicy();
			authPolicy.setUserName(username);
			authPolicy.setPassword(password);
			properties.put(AuthorizationPolicy.class.getName(), authPolicy);
		}
		
		//为clientFactoryBean与ServiceFactory设置features
		initFeatures();
		clientFactoryBean.setProperties(properties);

		if (bus != null) {
			clientFactoryBean.setBus(bus);
		}

		if (dataBinding != null) {
			clientFactoryBean.setDataBinding(dataBinding);
		}

		//由工厂类创建出Client对象,实现类为ClientImpl,并且创建出了Endpoint、Service对象
		Client c = clientFactoryBean.create();
		//将各种拦截器设置进Client中
		if (getInInterceptors() != null) {
			c.getInInterceptors().addAll(getInInterceptors());
		}
		if (getOutInterceptors() != null) {
			c.getOutInterceptors().addAll(getOutInterceptors());
		}
		if (getInFaultInterceptors() != null) {
			c.getInFaultInterceptors().addAll(getInFaultInterceptors());
		}
		if (getOutFaultInterceptors() != null) {
			c.getOutFaultInterceptors().addAll(getOutFaultInterceptors());
		}
		
		//创建客户端代理对象
		ClientProxy handler = clientClientProxy(c);
		//获取代理需要实现的接口,包含Web服务接口与java.io.Closeable
		Class<?> classes[] = getImplementingClasses();
		
		//这里是最关键代码,使用JDK提供的Proxy类创建出一个代理对象,该代理对象实现了Web服务接口与java.io.Closeable接口
		//而调用处理器(InvocationHandler)对象就是刚创建的ClientProxy对象
		Object obj = Proxy.newProxyInstance(clientFactoryBean.getServiceClass().getClassLoader(),
											classes,
											handler);

		this.getServiceFactory().sendEvent(FactoryBeanListener.Event.PROXY_CREATED,
										   classes, handler, obj);
		return obj;
	} finally {
		if (orig != null) {
			orig.reset();
		}
	}
}

因为调用处理器为ClientProxy,则客户端所有的Web服务调用都是调用ClientProxy的invoke方法,Web服务返回值就是invoke方法返回值,如下:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	//省略...
	MethodDispatcher dispatcher = (MethodDispatcher)endpoint.getService().get(MethodDispatcher.class
																				  .getName());
	BindingOperationInfo oi = dispatcher.getBindingOperation(method, endpoint);
	//省略...

	Object[] params = args;
	if (null == params) {
		params = new Object[0];
	}
	
	//进行同步调用
	Object o = invokeSync(method, oi, params);
	//call a virtual method passing the object.  This causes the IBM JDK
	//to keep the "this" pointer references and thus "this" doesn't get 
	//finalized in the midst of an invoke operation
	return adjustObject(o); 
}

通过create()方法,可以知道在创建ClientProxy时传入了Client对象,而在invokeSync(method, oi, params);中主要就是调用了Client的invoke方法,其invoke方法经过多个重的invoke方法调用,最后调用的是doInvoke()方法:


private Object[] doInvoke(ClientCallback callback,
              
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值