博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAX-WS Provider和Dispatch
阅读量:6878 次
发布时间:2019-06-26

本文共 6600 字,大约阅读时间需要 22 分钟。

  hot3.png

在之前的文章中,涉及到了WebService的搭建。所有的EndPoint均是高度面向对象,面向逻辑了。Server与Client之间交互的消息,均由JAXB转为JAVA类型。如果想对消息的原始数据进行修改,可以使用Handler Chain。

然而,JAXWS也提供了另一种编程方式,Provider和Dispatch,让我们抛开高度抽象的EndPoint和JAXB,抛开了工具wsgen,wsimport,直接面向消息编程。

Provider

介绍

Provider是server端直接面向消息编程的接口。我们先看下Provider接口中的方法:

package javax.xml.ws.Providerpublic interface Provider
 {  public T invoke(T request);}

服务端EndPoint必须实现此接口。Provider就像是HttpServlet,invoke()就像是service()。invoke方法参数是接收的原始消息,返回值是返回的消息。

T是对消息封装的一种泛型。结合Provider的Annotation @ServiceMode,它可以为三种封装类型:

  1. javax.xml.transform.Source 将消息中的Payload封装为XML类型Source。适用于@ServiceMode(value=Service.Mode.PAYLOAD)。

  2. javax.xml.soap.SOAPMessage 将消息整体封装为SOAPMessage。适用于@ServiceMode(value=Service.Mode.MESSAGE)。

  3. javax.activation.DataSource

Provider无法使用wsgen命令生成WSDL文件,所以,只能先用WebService Interface生成WSDL,然后再编写Provider。

下面的例子是基于之前的图书馆系统而修改的,所以复用之前图书馆系统的WSDL文件。

创建Java Web Project

创建一个java web project,取名叫LibraryProvider。然后将之前图书馆系统的WSDL文件复制到新项目的WEB-INF目录下面。

174229_YqL8_254689.jpg

创建Provider

创建java类,LibraryProvider:

@ServiceMode(value=Service.Mode.PAYLOAD)@WebServiceProvider()public class LibraryProvider implements Provider {    private static int currentId = 0;    private static Map
 books= new HashMap
();    private static class Book {        public int getId() {            return id;        }        public void setId(int id) {            this.id = id;        }        public String getName() {            return name;        }        public void setName(String name) {            this.name = name;        }        public String getAuthor() {            return author;        }        public void setAuthor(String author) {            this.author = author;        }        private int id;        private String name;        private String author;    }    @Override    public Source invoke(Source request) {        try {            DOMResult dom = new DOMResult();            Transformer trans = TransformerFactory.newInstance().newTransformer();            trans.transform(request, dom);            Node node = dom.getNode();            Node root = node.getFirstChild();            String operation = root.getLocalName();            if ("addRawBook".equals(operation)) {                return addRawBook(root);            }                        if ("getRawBook".equals(operation)) {                return getRawBook(root);            }            if ("deleteBook".equals(operation)) {                return deleteBook(root);            }                        return request;        } catch(Exception e) {            e.printStackTrace();            throw new RuntimeException("Error in provider endpoint", e);        }    }    private Source addRawBook(Node root) {        String name = root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();        String author = root.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();        Book b = new Book();        b.setName(name);        b.setAuthor(author);        b.setId(++currentId);        books.put(b.getId(), b);        String body =                "
"                +currentId                +"
";        Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));        return source;    }        private Source getRawBook(Node root) {        String idString = root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();        Book b = books.get(Integer.parseInt(idString));        String body =                "
"                +b.toString()                +"
";        Source source = new StreamSource(new ByteArrayInputStream(body.getBytes()));        return source;    }        private Source deleteBook(Node root) {        // 略    }}

sun-jaxws.xml

在WEB-INF下创建sun-jaxws.xml文件:

    

打包部署运行

将project导出为war包library.war,部署到tomcat下。访问 

然后使用wsimport,产生client端的代码。对client端进行调用,查看结果。

异步

关于提供服务端异步执行功能的AsyncProvider,我会另写一篇文章介绍。

Dispatch

介绍

接口Dispatch和Provider相对,用于client端。其功能与Provider一样,提供了面向消息的编程方法。先看下Dispatch提供了哪些方法:

package javax.xml.ws;import java.util.concurrent.Future;public interface Dispatch
 extends BindingProvider {    public T invoke(T msg);    public Response
 invokeAsync(T msg);    public Future
 invokeAsync(T msg, AsyncHandler
 handler);    public void invokeOneWay(T msg);}

T泛型与Provider中的T一样。而方法invoke与Provider中的invoke也相同。Dispatch还提供了另外3个方法:

  1. Response<T> invokeAsync(T msg); 为异步poll的方式, Response是一个Future。

  2. Future<?> invokeAsync(T msg, AsyncHandler<T> handler); 为异步callback方式。Handler会在另一个线程中处理返回的值。

  3. void invokeOneWay(T msg); 处理单向消息。

异步

关于异步,会在另一篇文章中同意描述。

创建client

由于Dispatch摆脱了JAXB,所以不需要调用wsimport命令。只需要一个简单的client程序,就可以调用服务器端的service。我们以图书馆webservice为例。

public class Client {    public static void main(String[] a) throws Exception {        URL url = new URL("http://127.0.0.1:8080/library/service?wsdl");        final QName serviceQName = new QName("http://library.mycompany.com", "LibraryService");        Service service = Service.create(url, serviceQName);                // 创建一个新的port,也可以使用WSDL中已有的port。如果WSDL中已经有此port,则不需要再进行binding。        QName portName = new QName("http://library.mycompany.com", "RandomPort");        service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING,"http://127.0.0.1:8080/library/service");        // 为port创建一个dispatch。所有流向port的消息都将由dispatch处理。        Dispatch sourceDispatch = service.createDispatch(portName, Source.class, Service.Mode.PAYLOAD);            // add book        String body = "
java
xpbug
";        Source result = sourceDispatch.invoke(new StreamSource(new StringReader(body)));        System.out.println(sourceToXMLString(result));        }        private static String sourceToXMLString(Source result) {        String xmlResult = null;        try {            TransformerFactory factory = TransformerFactory.newInstance();            Transformer transformer = factory.newTransformer();            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");            transformer.setOutputProperty(OutputKeys.METHOD, "xml");            OutputStream out = new ByteArrayOutputStream();            StreamResult streamResult = new StreamResult();            streamResult.setOutputStream(out);            transformer.transform(result, streamResult);            xmlResult = streamResult.getOutputStream().toString();        } catch (TransformerException e) {            e.printStackTrace();        }        return xmlResult;    }}

不需要任何额外的命令,依赖,以及部署,便可直接运行上面的程序。

转载于:https://my.oschina.net/xpbug/blog/228285

你可能感兴趣的文章
AutoreleasePool的那些事
查看>>
vue服务器端渲染(SSR)实战
查看>>
「原码 反码 补码 移码」一探究竟(中)
查看>>
CSS 你到底有多少长度单位?
查看>>
Linux Shell脚本系列之二
查看>>
设计模式--代理模式(Proxy Pattern)
查看>>
稀疏数组
查看>>
HTML5 标签 canvas
查看>>
react-router@4.0 使用方法和源码分析
查看>>
Flutter简介
查看>>
组织级敏捷转型的四个阶段
查看>>
「数据游戏」:使用 LSTM 模型预测三天后单股收盘价
查看>>
vuex持久化插件-解决浏览器刷新数据消失问题
查看>>
Vue-cli3 项目在安卓低版本系统和 IE 上白屏问题解决
查看>>
并发-7-同步容器和ConcurrentHashMap
查看>>
小程序白屏问题和内存研究
查看>>
React安装:
查看>>
从0开始搭建微信小程序(前后端)的全过程
查看>>
Code Coverage API plugin 一个新的代码覆盖率插件
查看>>
DTCC 2019 | 深度解码阿里数据库实现 数据库内核——基于HLC的分布式事务实现深度剖析...
查看>>