本文主要是介绍Axis2 sample and asynchronize,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
服务端:
接口HelloWorld
public interface HelloWorld {
publicString greeting(String name);
publicString print();
}
接口实现类HelloWorldBean
public class HelloWorldBean implements HelloWorld {
publicString greeting(String name) {
return"你好"+name;
}
publicString print() {
return"我叫林计钦";
}
}
webservice类HelloWorldWebService
/**
* 可能出现Axis2spring bean not found 或者Spring applicationContext not found。
* 解决办法:构建自己的ServiceObjectSupplier,实现接口ServiceObjectSupplier,同时也实现Spring的ApplicationContextAware接口
*/
public class HelloWorldWebService implementsServiceObjectSupplier,ApplicationContextAware {
privatestatic ApplicationContext ctx;
publicObject getServiceObject(AxisService axisService) throws AxisFault {
ParameterspringBeanName = axisService.getParameter("SpringBeanName");
StringbeanName = ((String) springBeanName.getValue()).trim();
if(beanName != null) {
if(ctx == null)
thrownew AxisFault("applicationContext is NULL! ");
if(ctx.getBean(beanName) == null)
thrownew AxisFault("Axis2 Can't find Spring Bean: " + beanName);
returnctx.getBean(beanName);
}else {
thrownewAxisFault(Messages.getMessage("paramIsNotSpecified","SERVICE_SPRING_BEANNAME"));
}
}
publicvoid setApplicationContext(ApplicationContext ctx)throws BeansException {
this.ctx= ctx;
}
}
配置web.xml文件
<?xml version="1.0"encoding="UTF-8"?>
<web-app>
<!--添加spring监听器-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!--加载spring的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<!--注册axis2的servlet-->
<servlet>
<servlet-name>AxisServlet</servlet-name>
<servlet-class>
org.apache.axis2.transport.http.AxisServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
applicationContext.xml
<beans>
<beanid="applicationContext" class="org.apache.axis2.extensions.spring.receivers.ApplicationContextHolder"/>
<beanid="helloWorld"class="com.ljq.service.HelloWorldBean"></bean>
</beans>
在WEB-INF\services\axis\META-INF\目录下配置services.xml
<?xml version="1.0"encoding="UTF-8"?>
<service name="hwWebService">
<description>axis2与spring集成案例</description>
<!--通过ServiceObjectSupplier参数指定SpringServletContextObjectSupplier类来获得Spring的ApplicationContext对象-->
<parametername="ServiceObjectSupplier">
org.apache.axis2.extensions.spring.receivers.SpringAppContextAwareObjectSupplier
</parameter>
<!--SpringBeanName固定的不能改helloWorld是spring中注册的实现类得id-->
<parametername="SpringBeanName">helloWorld</parameter>
<!--
在这里最值得注意的是<messageReceivers>元素,该元素用于设置处理WebService方法的处理器。
例如,getGreeting方法有一个返回值,因此,需要使用可处理输入输出的RPCMessageReceiver类,
而update方法没有返回值,因此,需要使用只能处理输入的RPCInOnlyMessageReceiver类。
-->
<messageReceivers>
<messageReceivermep="http://www.w3.org/2004/08/wsdl/in-only" class="org.apache.axis2.rpc.receivers.RPCInOnlyMessageReceiver"/>
<messageReceivermep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
</service>
或者如下配置
<serviceGroup>
<service name="hwWebService">
<description>Spring POJO Axis2 Service Sample</description>
<parametername="ServiceClass">com.zzy.HelloWorld</parameter>
<parameter name="ServiceObjectSupplier">
org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier
</parameter>
<parametername="SpringBeanName">helloWorld</parameter>
<messageReceivers>
<messageReceivermep="http://www.w3.org/2004/08/wsdl/in-out" class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
</messageReceivers>
</service>
</serviceGroup>
通过http://localhost:8083/axis2spring/services/hwWebService?wsdl访问
客户端:
public class HelloWorldRPCClient {
public staticvoid main(String[] args1) throws AxisFault {
EndpointReference targetEPR = newEndpointReference("http://localhost:8083/axis2spring/services/hwWebService");
RPCServiceClient serviceClient = new RPCServiceClient();
Options options =serviceClient.getOptions();
options.setTo(targetEPR);
QNameopGreeting = new QName("http://zzy.com", "greeting");
Object[]opGreetingArgs = new Object[] { };
Class[]returnTypes = new Class[] { String.class };
Object[]response = serviceClient.invokeBlocking(opGreeting,opGreetingArgs,returnTypes);
Stringresult = (String) response[0];
}
}
或者通过wsdl2java生成Stub
public class HelloWorldRPCClient {
public static voidmain(String[] args) throws Exception{
//初始化Stub
HelloWorldStubstub = new HelloWorldStub();
//初始化SimpleMethod方法。
stub.Greetingrequest = new HelloWorldStub.Greeting();
//调用Greeting的setName方法。
request.setName("zt");
//
System.out.println(stub.Greeting(request).get_return());
}
}
SendSmsServiceStub stub = newSendSmsServiceStub("http://221.236.6.218:5080/isag/North/SMS/SendSms");
SendSmsServiceStub.SendSms req = newSendSmsServiceStub.SendSms();
ServiceClient client = stub._getServiceClient() ;
Options option = client.getOptions();
option.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED,false); //修改HTTP头
// 创建头
SendSmsServiceStub.RequestSOAPHeader header = newSendSmsServiceStub.RequestSOAPHeader();
SendSmsServiceStub.RequestSOAPHeaderE headerE = newSendSmsServiceStub.RequestSOAPHeaderE();
headerE.setRequestSOAPHeader(header);
OMFactory fac = OMAbstractFactory.getOMFactory();
client.addHeader(headerE.getOMElement(newQName("RequestSOAPHeader","http://www.chinatelecom.com.cn/schema/ctcc/common/v2_1"),fac)); // 将头添加给SOAP
最初在将Web 服务实现作为一种应用程序开发方法引入时,它仅支持使用同步调用来进行请求-响应交互(本文中的同步 是指在同一个执行线程中处理请求和响应)。但是随着越来越多的应用程序采用Web 服务来公开功能,并且将客户端应用程序设计为与Web 服务交互,纯粹的同步调用已被视为瓶颈。这是因为,由于服务实现中的各种原因,有些Web 服务实现要花相当长的时间才能响应请求。例如,如果某个Web 服务在某个时点需要人工介入或批处理,该Web 服务可能要花数天时间才能获得结果。这些延迟还导致某些传输机制超时。
同步方式来调用WebService。也就是说,如果被调用的WebService方法长时间不返回,客户端将一直被阻塞,直到该方法返回为止。
随着Web 服务开发的发展,最终有些SOAP 堆栈尝试在同步功能之上模拟异步调用。尽管那些努力有点异步调用的感觉,但它们无法提供完整和真正的功能。ApacheSoftware Foundation 推出的开放源代码Web 服务引擎Apache Axis2 为异步Web 服务调用和实现提供了一流的支持。Axis2具有两种在客户端提供异步性的机制和一种在服务器端提供异步性的机制。下面更详细地研究一下如何使用这些机制实现异步通信。
客户端异步
客户端异步允许在两个不同的线程中处理请求和响应消息。可以采用两种方法在客户端实现这种异步,下面几个部分将对此进行描述。
非阻塞API
可以为客户机提供一个非阻塞API,使其能够将请求移交给SOAP 引擎并继续做其他工作。存在一个客户机提供的回调对象,SOAP引擎会在从服务器接收到响应后通知该对象。对于具有GUI 的交互式应用程序,此方法非常有用。
Axis2 客户机API 提供了用于常用消息交换模式(MessageExchange Pattern,MEP)的方法。下面使用IN-OUT 交互来演示异步支持。
当您使用ServiceClient API 时,您将使用sendReceive(OMElement) 或该方法的变体来实现同步调用。但是,sendReceiveNonBlocking(OMElement,Callback) 提供了初步级别的Axis2 客户机API 异步性,如清单1 所示,调用IN-OUT Web 服务而不阻塞客户机
// First create the payload of the message.
OMElement payload = getPayload(); // add your payloadhere
// Create an instance of service client.
ServiceClient serviceClient = new ServiceClient();
// Create an options object to pass parameters to serviceclient.
Options options = new Options();
// Set the location of the Web service.
options.setTo(new EndpointReference
("http://www.sample-web-service.com/StockQuote/getQuote"));
serviceClient.setOptions(options);
// Create a callback object.
Callback callback = new MyCallback();
// Do an async invocation.
serviceClient.sendReceiveNonBlocking(payload, callback);
// Continue doing other work without waiting until theresponse comes.
当客户机使用非阻塞API 调用Web 服务时,它需要向Axis2 ServiceClient API 传递一个回调对象。在响应消息到达时,Axis2引擎将此响应消息移交给该回调对象。然后该回调对象就可以代表客户机处理此响应,或者将其移交给客户机。
下面研究一下应该如何实现Callback。该回调接口具有两个方法:
*onComplete(AsyncResult) 方法,在接收到响应后调用
* AsyncResult 对象方法,它封装结果SOAP 信封和消息上下文
客户机可以扩展Callback 接口以在此方法中处理响应。另一方面,onError(Exception)方法在调用期间出错的情况下被调用。请在清单2 中详细观察这一点。
class MyCallbackextends Callback {
public voidonComplete(AsyncResult result) {
// Get theresponse SOAP envelope from the result.
SOAPEnvelopeenvelope = result.getResponseEnvelope();
// ProcessSOAP envelope.
}
public voidonError(Exception e) {
// Write herewhat you want to do in case of an error.
}
}
还可以将Callback 类用作轮询机制。客户机可以通过调用Callback.isComplete() 方法连续轮询某个响应。当存在多个Callback 实例等待响应,或者存在一个中央控制器监视响应并更新正在运行的应用程序时,这是非常方便的。因此,Callback类可同时用作回调机制或在异步调用期间用作轮询机制。
传输级别的异步
第二种方法是使用传输级别的异步。可以在Web 服务调用中使用的所有传输都可大致归类为两种类型的调用:
* 单向传输提供一个发送或接收消息的通道。
* 双向传输可以使用同一个通道发送和接收消息。
简单邮件传输协议(SimpleMail Transfer Protocol,SMTP)是单向传输的示例,而HTTP 则是双向传输。使用单个HTTP 通道即可与Web 服务进行请求-响应交互,而使用SMTP 则需要两个通道。
客户机具有用于请求-响应交互的不同选项。最容易的方法是使用诸如HTTP 之类的双向传输。但是此方法不使用传输级别的异步。客户机还可以使用两个单向传输或两个双向传输。例如,可以使用一个SMTP 通道发送消息,并使用另一个SMTP 通道接收响应消息。同时,可以使用一个HTTP 通道发送请求,在发送消息之后关闭它,并使用另一个HTTP 通道接收响应。但是要使此方法正常工作,应该存在消息相关性机制。ApacheAxis2 使用WS-Addressing 规范实现消息相关性。下面是处理不同传输的方式。
首先,使用任何传输通道发送请求,并使用一个具有同类型传输的不同通道接收响应。Axis2客户机可以使用useSeparateListener 标志,以通知其使用单独侦听器来接收响应消息的意图。换句话说,在启用此标志后,您将要求Axis2 引擎对此调用使用两个不同的传输通道。ServiceClientAPI 是Axis2 中最容易使用的客户机API,它具有一个用于设置此值的方法setUseSeparateListener(boolean)。清单 3 演示了如何使用 useSeparateListenerAPI 来调用Web 服务。
try {
// first createthe payload of the message
OMElement payload= getPayload(); // add your payload here
// create aninstance of service client
ServiceClientserviceClient = new ServiceClient();
// create anoptions object to pass parameters to service client
Options options =new Options();
// set thelocation of the web service
options.setTo(newEndpointReference
("http://www.sample-web-service.com/StockQuote/getQuote"));
// inform Axis2engine that you need to use a different channel for the response
options.setUseSeparateListener(true);
serviceClient.setOptions(options);
// invoke theservice
serviceClient.sendReceive(getPayload());
} catch (AxisFaultaxisFault) {
axisFault.printStackTrace();
}
此时,您要求Axis2 引擎准备一个传输侦听器,其类型与用于发送请求的传输类型相同;您还要求它接收响应。所使用的正确传输是由端点引用值推断出来的。此示例尝试将消息发送到http://www.sample-web-service.com/StockQuote/getQuote,并且此调用中使用了两个 HTTP 传输。可以使用sendReceive 或sendReceiveNonBlocking 方法来调用该Web 服务。
服务器端异步
当SOAP 引擎收到SOAP 请求时,通常的方法是处理请求并在同一个线程中发送消息。但是此方法并非始终有用。例如,当处理请求要花相当长的时间时,传输通道可能会超时。或者,对于处理大量流量的系统,有时在该持续时间内占用资源也许不是很好的选择。因此,理想的选择是通知客户机服务器收到了消息,并在稍后使用一个不同的传输通道发送应答。
Axis2 采用一个消息接收器,后者负责处理MEP 并将消息移交给请求处理逻辑或服务实现。在同步调用期间,消息接收器调用服务实现类中的适当方法(假设服务实现是用Java? 语言编写的),然后在同一个线程中发送响应。但是在异步调用期间,此消息接收器启动一个新线程来调用服务并向客户机发送通知。新线程负责将响应发送到客户机,并从服务实现类中取得响应。这就是Axis2 中的服务器端异步的工作方式。下面研究一下如何将其用于您的Web 服务。
可以采用两种基本方法创建服务:
* 编写 Web 服务描述语言(WebServices Description Language,WSDL),然后生成服务实现类的代码并填充它。
* 编写服务实现类,编写services.xml,并在Axis2 中部署它。
Services.xml 包含有关正在部署的 Web 服务的元数据。它列出服务实现类、公开的方法和任何应该传递给Web 服务的参数。
如果从上述“WSDL-代码-生成”方法开始,您可以要求代码生成器启用对服务的异步调用。然后代码生成器将生成一个异步消息接收器来调用服务。在运行WSDL2Java 脚本以从给定的WSDL 文件生成Java 代码时,还要使用-a 选项来指示该脚本生成异步代码。如果使用第二种方法,即代码优先(code-first) 方法,则应该为services.xml 中的IN-OUT 调用关联org.apache.axis2.async.AsyncMessageReceiver。必须将 IN-OUT MEP 关联到org.apache.axis2.async.AsyncMessageReceiver,如清单 4 所示。
清单4. 将消息接收器与IN-OUT MEP 变量相关联
<messageReceivers>
// othermessage receivers
<messageReceivermep="http://www.w3.org/2004/08/wsdl/in-out" class=
"org.apache.axis2.async.AsyncMessageReceiver"/>
</messageReceivers>
要使服务器端异步正常工作,必须使用WS-Addressing,因为您生成了一个新线程来发送响应,并向客户机许诺服务器将在稍后发送响应。但是如果请求处理要花一些时间,则客户机使用的传输可能超时。因此尝试在同一个通道中执行异步调用可能不够审慎。当客户机向异步Web 服务发送请求时,它还必须提到一个有效的replyTo 端点,以便服务器发回响应。
从客户机的角度看,当它调用此异步服务时,比如使用HTTP,它将在同一个传输通道中收到HTTP 202。HTTP202 告诉客户机Web 服务已经收到请求,但是处理还未完成。然后客户机将通过请求消息中放置的replyTo 路径接收响应。
这篇关于Axis2 sample and asynchronize的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!