`
mj4d
  • 浏览: 302849 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JAX-WS:异步与Handler机制

阅读更多

前面介绍了如何创建基于JAX-WS的webservice以及传递对象的一些相关内容,下面介绍下异步和Handler机制

1、异步

JAX-WS支持客户端的异步调用。在Server与普通的没多大区别,这里声明一个server服务:

@WebService(serviceName = "asynJaxWsService", endpointInterface = "org.ws.server.ws.chap3.AsynJaxWsService")
public class AsynJaxWsServiceImpl implements AsynJaxWsService {

    @WebMethod
    public @WebResult
    Address asynAddress(String id) {
        Address address = new Address();
        address.setCity("chengdu");
        address.setStreet("xxxx");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return address;
    }

}

 在发布服务后,生产客户端代码需要指定jaxws/bind文件,对于异步的bing.xml如下:

<bindings   
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
	wsdlLocation="http://localhost:8080/service/asynJaxWsService?wsdl"
	xmlns="http://java.sun.com/xml/ns/jaxws">
	<bindings node="wsdl:definitions">
		<enableAsyncMapping>true</enableAsyncMapping>
	</bindings>
</bindings>

然后生产客户端代码命令:

wsimport -p org.sample.ws.client.ws.chap3 -keep http://localhost:8080/service/asynJaxWsService?wsdl -b ./binding.xml

 在生产的客户端代码中提供了两种方式来异步调用:

public Response<AsynAddressResponse> asynAddressAsync(
        @WebParam(name = "arg0", targetNamespace = "")
        String arg0);

public Future<?> asynAddressAsync(
        @WebParam(name = "arg0", targetNamespace = "")
        String arg0,
        @WebParam(name = "asyncHandler", targetNamespace = "")
        AsyncHandler<AsynAddressResponse> asyncHandler);

可通过如下方式调用:

AsynJaxWsService jaxWs = new AsynJaxWsService_Service().getAsynJaxWsServiceImplPort();

jaxWs.asynAddressAsync("123", new AsyncHandler<AsynAddressResponse>() {

    public void handleResponse(Response<AsynAddressResponse> res) {
        try {
            AsynAddressResponse response = res.get();
            Address address = response.getReturn();
            System.out.println(ToStringBuilder.reflectionToString(address, ToStringStyle.SHORT_PREFIX_STYLE));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
});

Response<AsynAddressResponse> response = jaxWs.asynAddressAsync("123");
while (!response.isDone()) {
    System.out.println("not ending....");
}
AsynAddressResponse addressResponse = response.get();
Address address = addressResponse.getReturn();
System.out.println(ToStringBuilder.reflectionToString(address, ToStringStyle.SHORT_PREFIX_STYLE));

 

2、Handler机制

Handler机制(Filter、Interceptor)是很多框架必不可少的东西,甚至是构建在这个概念之上。在JAX-WS中提供了两种Handler机制:Logical Handlers and Protocol Handlers,简单地说前者处理业务上的后者处理访问等header层,更多信息见这里。我们这里要实现的一个简单授权访问的例子,就是基于ProtocolHandler(SOAPHandler),通过header中创建相应的节点来判断用户名或密码达到校验的目录。

首先来看看server端代码,自定义AuthHandler需要实现SOAPHandler:

public class AuthHandler implements SOAPHandler<SOAPMessageContext> {

    public boolean handleMessage(SOAPMessageContext context) {
        boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        if (!isRequest) {

            try {
                SOAPMessage soapMsg = context.getMessage();
                SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
                SOAPHeader soapHeader = soapEnv.getHeader();

                if (soapHeader == null) {
                    soapHeader = soapEnv.addHeader();
                    generateSOAPErrMessage(soapMsg, "No SOAP header.");
                }

                Iterator<?> it = soapHeader.extractHeaderElements(SOAPConstants.URI_SOAP_ACTOR_NEXT);

                if (it == null || !it.hasNext()) {
                    generateSOAPErrMessage(soapMsg, "No header block for next actor.");
                }

                //a simple way to handle authorize:通过nodeName和value来判断
                while (it.hasNext()) {
                    Node node = (Node) it.next();
                    if ("auth".equals(node.getNodeName()) && "aaaaaaaaaaaa".equals(node.getValue()))
                        return true;
                }

                generateSOAPErrMessage(soapMsg, "invalid user");
                //tracking
                soapMsg.writeTo(System.out);

            } catch (SOAPException e) {
                System.err.println(e);
            } catch (IOException e) {
                System.err.println(e);
            }

        }
        return true;//返回true是指向责任链中的下一个事物

    }

    public boolean handleFault(SOAPMessageContext context) {
        return true;
    }

    public void close(MessageContext context) {

    }

    public Set<QName> getHeaders() {
        return null;
    }

    private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
        try {
            SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
            SOAPFault soapFault = soapBody.addFault();
            soapFault.setFaultString(reason);
            throw new SOAPFaultException(soapFault);
        } catch (SOAPException e) {
        }
    }

}

 在handler-chain.xml中声明

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains 
	xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>org.ws.server.ws.chap7.AuthHandler</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
</javaee:handler-chains>

server接口没多大变化,只需要添加@HandlerChain(file = "handler-chain.xml")指定配置文件

@WebService
@HandlerChain(file = "handler-chain.xml")
public class JaxWsHandlerServiceImpl implements JaxWsHandlerService {

    @WebMethod
    public String sayHello() {
        return "Hello, Service";
    }

}

 发布即可完成server端的配置。

接下来看看客户端,通过命令生成客户端代码后,同样需要编写handler,需要处理就是在SOAP消息的Header中添加Node,起name和value分别对应server端的配置:

public class JaxWsClientHandler implements SOAPHandler<SOAPMessageContext> {

    public boolean handleMessage(SOAPMessageContext context) {
        System.out.println("Client : handleMessage()......");

        Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        //if this is a request, true for outbound messages, false for inbound
        if (isRequest) {

            try {
                SOAPMessage soapMsg = context.getMessage();
                SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
                SOAPHeader soapHeader = soapEnv.getHeader();

                //if no header, add one
                if (soapHeader == null) {
                    soapHeader = soapEnv.addHeader();
                }

                //add an node named "auth"
                QName qname = new QName("http://handler.sws.com/", "auth");
                SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(qname);
                
                //set attribute value
                soapHeaderElement.setActor(SOAPConstants.URI_SOAP_ACTOR_NEXT);
                soapHeaderElement.addTextNode("aaaaaaaaaaaa");
                soapMsg.saveChanges();

                //tracking
                soapMsg.writeTo(System.out);

            } catch (SOAPException e) {
                System.err.println(e);
            } catch (IOException e) {
                System.err.println(e);
            }

        }
        return true;
    }

    public boolean handleFault(SOAPMessageContext context) {
        return true;
    }

    public void close(MessageContext context) {

    }

    public Set<QName> getHeaders() {
        return null;
    }

}

其他工作与服务端一样,编写handler-chain.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains 
	xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>org.sample.ws.client.ws.chap7.main.JaxWsClientHandler</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
</javaee:handler-chains>

同时在生成的客户端代理类中需要加入该hander-chain,看起来是这样的:

@WebServiceClient(name = "JaxWsHandlerServiceImplService", targetNamespace = "http://impl.chap7.ws.server.ws.org/", wsdlLocation = "http://localhost:8080/service/jaxWsAuthSrevice?wsdl")
@HandlerChain(file = "handler-chain.xml")
public class JaxWsHandlerServiceImplService
    extends Service

这样就完成了一个简单的实例,按照普通的调用即可:

        JaxWsHandlerServiceImpl service = new JaxWsHandlerServiceImplService().getJaxWsHandlerServiceImplPort();
        System.out.println(service.sayHello());

如果没有auth节点或者value(密码)不对就会抛出异常如:

	at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
	at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111)
	at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
	at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
	at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
	at $Proxy29.sayHello(Unknown Source)
	at org.sample.ws.client.ws.chap7.main.JaxWsHandlerServiceMain.main(JaxWsHandlerServiceMain.java:15)

 

分享到:
评论

相关推荐

    JAX-WS2.1用户指南

    JAX-WS提供了统一的异常处理机制,能够捕获和处理Web服务调用过程中的各种错误。 9. **客户端编程** 通过WSDL,JAX-WS可以自动生成客户端代理类,使得调用Web服务如同调用本地Java方法一样简单。 10. **与Java ...

    jax-ws用户指南 pdf版

    - **有用链接**:包括其他与 JAX-WS 相关的资源链接。 - **发布说明**:概述了当前版本的主要特性和变更记录。 - **安装指南**:指导用户如何正确安装 JAX-WS。 - **运行环境**:说明了在 JDK 6 上运行 JAX-WS 的...

    JAX-WS使用教程(内含jar包)

    3. **异步调用**:JAX-WS支持异步调用Web服务,提高了响应速度和系统效率。 4. **安全性**:JAX-WS提供了一套完整的安全模型,包括基本认证、TLS加密、WS-Security等,保障Web服务的安全性。 **总结** JAX-WS是...

    JAX-RS-messanger-service:使用JAX-RS的消息传递REST服务

    **JAX-RS-messanger-service: 使用JAX-RS构建消息传递REST服务** JAX-RS(Java API for RESTful Web Services)是Java平台上的一个标准,用于创建基于REST(Representational State Transfer)风格的Web服务。REST...

    Java远程通信技术——Axis实战.doc

    JAX-WS 是 JAX-RPC 的下一代标准,它引入了更多的 Web 服务标准,如 JAXB(Java Architecture for XML Binding)用于XML和Java对象之间的绑定,以及 JAX-WS RI(Reference Implementation)作为实现JAX-WS规范的参考...

    webservice,cxf

    拦截器是基于JAX-WS规范的Handler链,开发者可以通过编写自定义的Handler类并将其注册到CXF中,实现对服务请求和响应的透明处理。 最后,"lib"目录下的jar包包含了所有必要的依赖,这些库文件涵盖了CXF、Spring以及...

    webService参考资料

    1. JAX-WS(Java API for XML Web Services):这是Java平台上的Web服务开发框架,用于创建符合SOAP标准的服务。JAX-WS提供了基于注解的编程模型,简化了服务端和客户端的开发。 2. SOAP消息处理:在服务端,开发者...

    Android调用Java WebService的实现方法.zip

    Java WebService通常使用JAX-WS或JAX-RS框架来创建。 在Android中调用Java WebService,主要涉及以下步骤: 1. **创建WebService客户端**:Android应用需要一个客户端代理类来调用WebService。这个代理类通常由...

    JavaEE主要技术

    WS-JAX-RPC (Web Services for Java - Remote Procedure Call) 是一种用于构建 Web 服务的标准 API,基于 SOAP 协议。 - **Endpoint**:表示 Web 服务端点。 - **SOAPMessage**:封装 SOAP 消息。 - **Service**:...

    android 客户端与webservice之间的交互

    7. **异步处理**:考虑到Android应用的UI线程不能被阻塞,通常使用AsyncTask、Handler、Thread或ExecutorService等进行异步网络请求。 总的来说,Android客户端与Java Web编写的Web Service交互涉及网络编程、HTTP...

    Spring中文帮助文档

    2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态语言支持 2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到...

    Spring API

    2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态语言支持 2.6.2. 增强的测试支持 2.6.3. JMX 支持 2.6.4. 将Spring 应用程序上下文部署为JCA adapter 2.6.5. 计划任务 2.6.6. 对Java 5 (Tiger) 支持 2.7. 移植到...

Global site tag (gtag.js) - Google Analytics