当大型需求被数个公司分割开来,各公司系统相互交换数据的问题就会接踵而来。毕竟是多家不同的公司的产品,研发开发语言、采用技术框架基本上是百花齐放。怎样让自家系统提供的服务具有跨平台、跨语言、跨各种防火墙,让其他公司的研发用起来没障碍和爽呢?进过前期的技术调研和实践,最终将目光放在了轻量级 webservice 服务上面
1. webservice 服务技术的关键点xml:
做为 webservice 的基本数据表示,特点即容易组织和分析,而且又与开发平台无关。
soap: 做为 webservice 的传输协议,特定能运行在任何传输协议(tcp/udp..)上面,将程序中的对象编码为 xml 的规则,执行远程调用。
wsdl: 做为描述 webservice 的语言,你能很清晰的知道提供的服务是什么、入参、返回的数据,机器和人都很容器进行阅读。
公司自己实现 webservice 服务铁定不现实,如果你公司有一群热爱技术的大牛、有一颗想造轮子的匠心,有老总的支持,还是可以放手一战的。
目前已有的 webservice 开发框架有: axis、axis2、xfire、cxf、jax-ws。
除了 jax-ws 为 jdk 1.6 发布的的 webservice 开发框架以外,其余的都是第三方开源框架。
其中 axis 和 xfire 随着技术更新和发展已经慢慢的谈出了人们的视线,并且官方已经有很长时间没有更新,这里暂且不表。
cxf是apache旗下一个重磅的soa简易框架,它实现了esb(企业服务总线)。
cxf 原型来源与 xfire + client, 就像 struts2 来自 webwork 一样,当让你也能预言到 xfire 的命运会和 webwork 一样,会淡出开发者的视线。
axis2 是 apache 下的一个重量级 webservice 框架,准确说它是一个web services / soap / wsdl 的引擎,是 webservice 框架的集大成者。
axis2 不但能制作和发布webservice,而且可以生成java和其他语言版webservice客户端和服务端代码。这是它的优势所在。
丰满意味着臃肿和庞大,不可避免的导致了axis2的复杂性,听使用过她的人,它所依赖的包数量和大小都是很惊人的,打包部署发布很麻烦。
源于对第三方开源框架的恐惧和颤抖,结合自身公司的业务复杂度,技术团队一致选定 jdk jax-ws 作为公司的 webservice 框架。
我这里的说的无 mvc 框架指的是没有使用任何像 struts/spring mvc/webwork....这些东西,java ee 项目最纯真的 servlet 时代。
在 main 函数中静态方式防部的方式这里就不提了,咱需要 webserver 服务和 web 项目一起启动起来,同呼吸共命运。
<dependency> <groupid>com.sun.xml.ws</groupid> <artifactid>jaxws-rt</artifactid> <version>2.2.10</version> </dependency>
如果是jar包方式的话,
需要如下jar。
完整的项目结构如下:
web.xml配置
注意服务配置文件中的 url-pattern 和 servlet 中的 url-pattern 是一致的。通过上面的4步的操作,启动 web 项目吧,不出什么意外的话,启动 web 容器打印日志是这样。
大体的想法是你得让 spring 知道有这样一个服务实现类。如果你比较传统,可以配置在 spring-***.xml 中,像这样 ... 当然你也可以,使用注解,像这样
服务端编写好之后,使用 jdk 自带的 wsimport 工具生成客户端代理类。
wsimport 只需要指定 url 就能生成 java 调用的客户端,你完全不用去了解这个 webserver 服务是用什么语言编写的。
生成客户端代理类之后,只需要两行代码就能,实现 webserver 服务的调用。
wsimport -s f: http://localhost:5050/cwe/services/sayhi?wsdl
wsimport 常用参数参考
参数 说明
-p 定义客户端生成类的包名称
-s 指定客户端执行类的源文件存放目录
-d 指定客户端执行类的class文件的存放目录
-keep 表示生成客户端执行类的源代码
-b 指定jaxws/jaxb绑定文件或额外的schemas
-extension 使用扩展来支持soap1.2
将代理类放入客户端,调用代码
myfirstwebserviceimplservice service = myfirstwebserviceimplservice; myfirstwebservice implport = service.getmyfirstwebserviceimplport; system.out.println(implport.sayhi("orson"));
其实我一直想尝试,不再客户端添加任何类调用 webserver 服务,很遗憾没能成功。
最接近的的是,在客户端放入服务端的 接口类,代码可以这样写。
url url = new url("http://localhost:5050/cwe/services/sayhi?wsdl"); qname servicename = new qname("http://impl.jws.cwe.rambo.com/", "myfirstwebserviceimplservice"); qname portname = new qname("http://impl.jws.cwe.rambo.com/", "myfirstwebserviceimplport"); service service = service.create(url,servicename); myfirstwebservice serviceport = service.getport(portname,myfirstwebservice.class); system.out.println(serviceport.sayhi("orson"));
自行定义连接地址、服务名称、、端口名称,生成服务实例进行访问,代码完全没有代理类那样清晰。