扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
引言
在过去数年里,随着万维网联盟(World Wide Web Consortium,W3C)更新了核心规范,并引入了弥补 Web 服务最初缺陷的新规范,Web 服务发生了大量的变化。W3C 的 Web Services Activity 小组所维护的规范以独立于供应商的方式将 Web 服务作为一组 XML 规范进行处理。
同时,Java™ Community Process (JCP) 也在维护自己的规范集,以将 W3C 的建议合并到 Java 语言中。Java APIs for XML(JAX-RPC、JAXB、JAXP、JAXR 和 SAAJ)是一组使用 Java 语言实现 Web 服务规范的接口。
W3C 所维护的当前 Web 服务规范和 JCP 维护的 Java Web 服务 API 处理“网络上”的 Web 服务,以确保平台独立性和语言独立性。遵循 XML 规范或使用 Java API 的开发人员将确保应用程序能够通过任何通信协议在任何平台上与采用任何语言编写的 Web 服务进行通信。Web 服务可扩展任何应用程序的访问范围,是经过验证的对目前基于 Web 的应用程序有价值的集成技术。
但当基于 Web 的应用程序需要跨多个 Web 应用程序容器(如 IBM® WebSphere® Application Server、BEA WebLogic 和 Tomcat 等,这里仅指出三个)部署时,跨网络兼容性不够。对于 Java Web 服务,没有跨多个 Web 应用程序容器实现的标准部署的“web.xml”可用。
如果您希望应用程序支持多个 Web 应用程序容器提供的 Web 服务实现,则 Java Web 服务应用程序的部署可能会成为一项挑战。可以在 Web 应用程序中使用单个 Web 服务实现,如来自 Apache Web 服务项目的 Axis。对于 Web 服务客户机,这个策略通常能跨多个 Web 容器工作,因为客户机代码并不依赖于任何 Web 服务部署描述符。对于 Web 服务提供者(服务器),如果将 Web 服务实现嵌入 Web 应用程序存档(Web Application Archive,war)文件中,可能会导致意外加载器冲突,因此使用供应商的 Web 服务实现是最理想的部署选择。
本文剩下的部分将讨论 Java Web 服务的部署问题,向您展示各种部署描述符实现,并讨论 Java 社区如何开始处理这个问题。
开发跨多个容器部署的单个 Web 服务
对于 Web 应用程序部署,我们希望进行开放性的选择。如果您的客户在 WebSphere 或 WebLogic 等商业 J2EE 实现进行了投资,他们将希望利用其投资的平台。另一方面,如果您的客户希望降低初期投入成本,则可能希望采用 JBoss 或 Apache Tomcat 等开放源代码解决方案。在这两种情况下,如果您希望尽可能提高开发工作的可重用性,则可能无法依赖于可用的供应商特定 IDE。使用 J2EE 应用程序供应商提供的 IDE 进行开发工作可能会限制处理 Java Web 服务时的灵活性,隐藏部署 Web 服务的很多细节。
本文中的示例使用开放源代码社区提供的免费标准的开发工具集来为每个目标 Web 应用程序容器构建 Web 服务部署描述符。所有这些工具均在开发人员中得到了广泛应用,且支持各种开放标准技术。
我们的目标是,获得能够生成可使用 Axis 跨目标 Web 应用程序容器(WebSphere、WebLogic、JBoss 和 Tomcat)部署的 Web 服务的单个项目。相应的 war 文件应该能够在只需很少修改而绝对不需要重新编译源代码的情况下部署到我们的目标 Web 应用程序容器上。
本文并不打算作为有关 Web 服务或 Web 服务部署的教程,而旨在说明 Java Web 服务的一个问题,并阐述将来可以如何处理这个问题。如果您仅使用一个 Web 应用程序容器,而没有打算更改 Web 应用程序容器,则可以跳过有关 Web Services Metadata (JSR-181) 的部分(此 JSR 可能会影响您将来的开发工作)。
Web 服务的描述
为了提供有关我们的部署示例的足够信息,我创建了一个需要为接口使用映射文件的 Web 服务。传统的 Hello World 或 Stock Ticker Web 服务将无法提供足够的信息来说明我们的 Web 服务部署需求。
我们的 Web 服务端点将具有多个方法,这些方法可用于说明部署期间所需的各种文件。我们的示例 Web 服务将返回有关远程应用程序性能的信息。当然,我们的示例实现并不会返回任何实际的信息,它只不过是一个简单的示例,用于说明更为复杂的 Web 服务接口的要求。下面是用于创建我们的 Web 服务端点的接口文件。
清单 1. Web 服务端点接口
public interface StatsService extends java.rmi.Remote { public StatsContainer[] getAllStatistics() throws java.rmi.RemoteException; public StatsContainer[] getStatistics(String category) throws java.rmi.RemoteException; public void resetAllStatistics() throws java.rmi.RemoteException; public void resetStatistics(String category) throws java.rmi.RemoteException; public void clearStatistics() throws java.rmi.RemoteException; public String[] getCategories() throws java.rmi.RemoteException; } |
此接口具有两个不同的返回类型,需要进行映射。第一个类型是 StatsContainer 对象数组,而另一个类型则是 string 对象数组。StatsContainer 是简单容器对象,该对象具有若干基元类型和两个字符串。我们的目标是,从此接口和实现文件入手,使用我们的开放工具集中提供的工具构建所需的部署描述符,以便将 Web 服务部署到目标平台上。我们将描述此过程中的每个步骤以及生成的各个文件。
构建过程的描述
我们的 Web 服务的构建过程中将使用各种自动化工具,这些工具由可利用 Java 自检构建 Web 服务构件的 Web 服务实现提供。对于我们的部署,将使用两种不同的构建工具,因为部署描述符分属两个不同的组:支持 J2EE 1.4 的部署描述符和自定义 Web 服务部署描述符。
J2EE 1.4 Web 服务
为了构建标准 J2EE 1.4 Web 服务所需的构件,我们使用了 Java Web Service Developers Pack (JWSDP v1.5) 所提供的 wscompile 命令。wscompile 命令会创建 Web 服务描述语言(Web Service Description Language,WSDL)文件、Web 服务映射文件和实现文件,以便在 Web 服务和调用的应用程序之间进行封送处理。
为了运行 wscompile 命令,您首先需要编写一个 XML 配置文件,在其中描述您希望 wscompile 执行的操作。在此示例中,我们希望处理我们的服务端点并创建实现所需的 XML 构件和序列化代码。下面是 wscompile 命令所需的配置文件的示例:
清单 2. 示例配置文件
<?xml version="1.0" encoding="UTF-8"?> <configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"> <service name="StatsWS" targetNamespace="http://services.symmetrysolutions.com/stats" typeNamespace="http://types.symmetrysolutions.com/stats" packageName="com.symmetrysolutions.statsws"> <interface name="com.symmetrysolutions.statsws.StatsService" servantName="com.symmetrysolutions.statsws.StatsServiceImpl"/> </service> </configuration> |
在此配置文件中,我们使用 service 元素描述我们的 Web 服务。此元素告知 wscompile 命令以下内容:将与接口关联的命名空间以及与该接口关联的类型。除了命名空间外,service 元素还告知 wscompile 命令为生成的任何源代码使用的包名称以及其将自检的接口的名称。
运行自动化工具并不是部署符合 J2EE 1.4 的 Web 服务的最后一步。根据所使用的 Web 应用程序容器的不同,最后的步骤将有所变化。无论在何种情况下,必须包含的最后一个 Web 服务部署构件都是 webservices.xml 文件。此文件告知 J2EE 1.4 应用程序容器在何处查找 Web 服务描述,以及将什么接口和实现类用于 Web 服务。
Axis Web 服务
Axis Web 服务的构建过程与 J2EE 1.4 Web 服务不同,因为 Axis 具有自己的部署描述符。Axis Web 服务运行时需要 deploy.wsdd 文件提供的信息,以确定服务端点的名称和将其作为 Web 服务发布的方式。deploy.wsdd 文件将发送到 Axis 服务器,Axis 服务器将利用此信息对 Web 服务进行自检,并创建 Web 服务运行时所需的信息。注意:上述过程并不符合 J2EE 1.4 (部署构件),但符合 SOAP 1.1,因此 Axis Web 服务将能够与任何 Web 服务客户机进行互操作。
要构建 Axis Web 服务部署描述符,可以手动进行,也可以使用 Axis WSDL2Java Ant 任务来处理 Web 服务的 WSDL。在我们的示例中,由于我们决定使用 Web 服务端点的接口,因此没有 WSDL 文件。幸运的是,Axis 还提供了一个 Ant 任务来处理接口并输出 WSDL 文件。因此,Axis 构建过程包含两个步骤,如下所述:
构建了 Axis Web 服务后,必须告知 Web 应用程序容器要部署的服务以及如何进行部署,以便进行部署。这是通过将 deploy.wsdd 文件传递给部署 Web 服务的 Axis 管理员任务来完成的。这意味着,在 Web 容器启动后,Axis Web 服务需要进行部署 Web 服务的步骤。有关详细信息,请参见 Tomcat 上的 Axis 部署部分。
部署过程的描述
创建了所需的全部 Web 服务部署描述符后,最后一步是在每个目标平台上部署应用程序。我们将说明为了部署 Web 服务而需要在每个目标 Web 应用程序平台上进行的最后步骤。
IBM WebSphere 和 JBoss 4.0.4
IBM WebSphere 和 JBoss 4.0 均符合 J2EE 1.4,可以使用 Java Web Services Developer Pack (JWSDP v1.5) 或类似工具来生成 JAX-RPC Web 服务构件。唯一还没有为部署生成的 Web 服务构件是 webservices.xml 文件,该文件描述如何将所有组件组合到一起。
在 JBoss 4.0.4 上部署
要在 JBoss 上部署 Web 服务,必须进行以下步骤:(请注意,我们必须使用 JBoss 4.0.4,因为在 JBoss 的早期版本上部署数组类型会出现问题。)
清单 3. 示例 webservices.xml 文件
<?xml version="1.0" encoding="UTF-8"?> <webservices xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd" version="1.1"> <webservice-description> <webservice-description-name>StatsWS</webservice-description-name> <wsdl-file>WEB-INF/wsdl/StatsWS.wsdl</wsdl-file> <jaxrpc-mapping-file>WEB-INF/mapping.xml</jaxrpc-mapping-file> <port-component> <port-component-name>StatsWS</port-component-name> <wsdl-port>StatsServicePort</wsdl-port> <service-endpoint-interface> com.symmetrysolutions.statsws.StatsService </service-endpoint-interface> <service-impl-bean> <!—This servlet is declared in our web.xml file --> <servlet-link>StatsWS</servlet-link> </service-impl-bean> </port-component> </webservice-description> </webservices> |
清单 4. web.xml 中的 Web 服务 Servlet 引用
<!-- This name is declared in the webservices.xml file --> <servlet> <servlet-name>StatsWS</servlet-name> <servlet-class> com.symmetrysolutions.statsws.StatsServiceImpl </servlet-class> </servlet> |
婵犵數濮烽弫鍛婃叏閻戝鈧倹绂掔€n亞鍔﹀銈嗗坊閸嬫捇鏌涢悢閿嬪仴闁糕斁鍋撳銈嗗坊閸嬫挾绱撳鍜冭含妤犵偛鍟灒閻犲洩灏欑粣鐐烘⒑瑜版帒浜伴柛鎾寸洴閹儳煤椤忓應鎷洪梻鍌氱墛閸楁洟宕奸妷銉ф煣濠电姴锕ょ€氼參宕h箛鏃傜瘈濠电姴鍊绘晶娑㈡煕鐎c劌濡介柕鍥у瀵粙濡歌閳ь剚甯¢弻鐔兼寠婢跺﹥娈婚梺鍝勭灱閸犳牠骞冨⿰鍫濈厸闁稿本绋撹ぐ瀣煟鎼淬値娼愭繛鍙壝悾婵堢矙鐠恒劍娈鹃梺鍓插亝濞叉牠鎮″☉銏$厱閻忕偛澧介惌瀣箾閸喐鍊愭慨濠勭帛閹峰懐绮电€n亝鐣伴梻浣规偠閸斿宕¢崘鑼殾闁靛繈鍊曢崘鈧銈嗗姂閸庡崬鐨梻鍌欑劍鐎笛呯矙閹寸姭鍋撳鐓庡籍鐎规洑鍗冲畷鍗炍熼梹鎰泿闂備線娼ч悧鍡涘箠鎼淬垺鍙忔い鎺嗗亾闁宠鍨块崺銉╁幢濡炲墽鍑规繝鐢靛О閸ㄦ椽鏁嬮柧鑽ゅ仦娣囧﹪濡堕崨顔兼闂佺ǹ顑呴崐鍦崲濞戙垹骞㈡俊顖濐嚙绾板秹鏌f惔銏e妞わ妇鏁诲璇差吋閸偅顎囬梻浣告啞閹搁箖宕版惔顭戞晪闁挎繂顦介弫鍡椼€掑顒婂姛闁活厽顨嗙换娑㈠箻閺夋垹鍔伴梺绋款儐閹瑰洭寮婚敐鍛婵炲棙鍔曠壕鎶芥⒑閸濆嫭婀扮紒瀣灴閸╃偤骞嬮敃鈧婵囥亜閺囩偞鍣洪柍璇诧功缁辨捇宕掑▎鎴濆濡炪們鍔岄幊姗€骞嗗畝鍕<闁绘劙娼х粊锕傛煙閸忚偐鏆橀柛鏂跨焸閹偤宕归鐘辩盎闂佸湱鍎ら崹鐢割敂閳哄懏鍊垫慨姗嗗墻濡插綊鏌曢崶褍顏€殿喕绮欐俊姝岊槼闁革絻鍎崇槐鎾存媴缁涘娈┑鈽嗗亝缁诲牆顕f繝姘亜缁炬媽椴搁弲锝夋偡濠婂啰效闁诡喗锕㈤幊鐘活敆閸屾粣绱查梺鍝勵槸閻楀嫰宕濇惔锝囦笉闁绘劗鍎ら悡娑㈡倶閻愯泛袚闁哥姵锕㈤弻鈩冩媴閻熸澘顫掗悗瑙勬礈閸犳牠銆佸鈧幃鈺呮惞椤愩倝鎷婚梻鍌氬€峰ù鍥х暦閸偅鍙忛柟鎯板Г閳锋梻鈧箍鍎遍ˇ顖炲垂閸岀偞鐓㈡俊顖滃皑缁辨岸鏌ㄥ┑鍡╂Ц缂佲偓鐎n偁浜滈柡宥冨妿閳藉绻涢崼鐔虹煉婵﹨娅e☉鐢稿川椤斾勘鈧劕顪冮妶搴′簼婵炶尙鍠栧畷娲焵椤掍降浜滈柟鍝勬娴滈箖姊洪幐搴㈢┛濠碘€虫搐鍗遍柟鐗堟緲缁秹鏌涢锝囩畼妞ゆ挻妞藉铏圭磼濡搫顫岄悗娈垮櫘閸撴瑨鐏冮梺鍛婁緱閸犳岸宕㈤幖浣光拺闁告挻褰冩禍浠嬫煕鐎n亜顏柟顔斤耿閺佸啴宕掑☉姘箞闂佽鍑界紞鍡涘磻閸℃ɑ娅犳い鎺戝€荤壕濂告煕鐏炲墽鈽夌紒妞﹀洦鐓欓柣鐔告緲椤忣參鏌熼悡搴㈣础闁瑰弶鎸冲畷鐔兼濞戞瑦鐝¢梻鍌氬€搁崐椋庣矆娓氣偓楠炴牠顢曢妶鍌氫壕婵ê宕崢瀵糕偓瑙勬礀缂嶅﹪寮婚崱妤婂悑闁告侗鍨界槐閬嶆煟鎼达紕鐣柛搴ㄤ憾钘濆ù鍏兼綑绾捐法鈧箍鍎遍ˇ浼存偂閺囥垺鐓涢柛銉e劚婵$厧顭胯閸ㄤ即婀侀梺缁樓圭粔顕€顢旈崼鐔虹暢闂傚倷鐒︾€笛呮崲閸屾娑樜旈崨顓犲幒闂佸搫娲㈤崹娲偂閸愵亝鍠愭繝濠傜墕缁€鍫熸叏濡寧纭鹃柦鍐枛閺屾洘绻涜鐎氱兘宕戦妸鈺傗拺缂備焦锚婵洦銇勯弴銊ュ籍闁糕斂鍨藉鎾閳ユ枼鍋撻悽鍛婄叆婵犻潧妫楅埀顒傛嚀閳诲秹宕堕妸锝勭盎闂婎偄娲︾粙鎰板箟妤e啯鐓涢悘鐐靛亾缁€瀣偓瑙勬礋娴滃爼銆佸鈧幃銏$附婢跺澶�
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者