服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

用java web服务打造聊天程序


  web服务是什么或者应该是什么有许多定义,每个或多或少都可以理解。很有趣的事情是最简单的东西往往是最难描述的。眼前就有一个很好的例子:一个web服务是一个可以和外部世界交换文档的实体。这个实体是自我描述的并且拥有一个唯一的特性。

  这个文档内容是xml;严格来说是soap。soap(简单对象存取协议)定义web服务消费和生成的xml文档的内部结构。soap被认为是一个行业标准并且被许多跨平台软件供应商、硬件平台、操作系统或者编程语言广泛地采用。

  每个web服务都有一个地址。这是它的id。这个地址由一个uri(亦称url)定义。一个web服务存在于并且被它的uri标识。这个地址经常被称为一个终端。这个id和内容的安全性毫无关系。本教程的服务存在于http://localhost:6060/chatservice/。

  web服务带有它自己的描述。这告诉你它交换的是什么类型的文档。它说明了服务存在于什么地方(uri地址)。并且它还说明了它可以使用哪个传输协议来交换文档。web服务描述使用的语言是wsdl(web服务定义语言)。一个web服务完全由它的wsdl文档描述。为了和一个独立web服务通讯,你只需要wsdl文档。即使wsdl在它自己的上下文中描述web服务,它还是无法描述多个web服务组合起来所形成的美妙的乐章。

  web服务有一个地址,但是为了访问它,你需要发现它在哪儿。换句话说,你需要一个电话号簿列表web服务。uddi (通用描述、发现和集成)是行业标准的电话号码薄。uddi处理寄存器并且发现web服务。

  综合起来,一个web服务就是和现实世界交换soap文档的一个实体,使用一些uri定位,使用wsdl文档描述并且可以使用uddi注册来列出并发现。 一个真实的示例

  无数类型的文档可以被发送到web服务并来源于web服务。它可以是一个钢厂中的周期的温度报道,它可以是一个地方政府定义的退税请求,或者它可以是一个从一个软件组件到另一个组件的rpc调用的文档风格表现。同样的情况也发生在文档交换方案中。你可以设想单向的消息或者请求-响应消息传送,这里面都需要跟随一个响应文档的请求文档。 web服务大部分当前的用法遵循xml模式上的远程过程调用。这就是为什么开发者可以很容易转到开发web服务,而不要对现有的应用程序做重大的修改,或者之需要付出最小的努力就能创建用于web服务的客户端。web服务框架经常可以隐藏底层体系结构的复杂性。他们通常提供了用于从语言到wsdl和从wsdl到语言生成的工具。展示象web服务这样的语言结构比手工处理xml文档快得多并且容易的多。现在,web服务经常用作一个集成工具,让开发者和系统设计师互连不同的应用程序。

  即使本文中的web服务和它的客户端遵循xml模式上的远程过程调用,但是web服务的应用范围是非常宽广的。近期,有许多基于松散耦合的纯文档交换模式实现。

  一个简单的聊天服务器

  在本文中,我试图创建一个比著名的股票行情服务更具挑战的应用程序,但是仍然简单易读。它是一个聊天服务器应用程序。聊天服务器的功能是非常简单的客户端或者发送新消息并读取它们。

  这个聊天服务器实现是与wasp和web服务完全互不相关的。它可以成功地被编译并且用于任何其他的java环境。这个聊天服务器还描述预存在的业务逻辑。请查看代码来领会。你可以在这里下载用于聊天实现的源代码(而不是web服务,那个还没有写)。

  设计聊天服务器

  聊天服务器的全部的实现被分割到好几个类中。接口定义在程序包com.systinet.simplechat.server.iface中。它由三个类组成;聊天服务器的接口类ichatservice.java和用于聊天消息的表现两个结构和participants-chatmessage.java和chatperson.java。

  聊天服务器的实现在程序包com.systinet.simplechat.server.impl中。它把简单的接口的实现从后端业务逻辑中分离出来。我使用了适配器设计模式,那就是说,到chatservice.java的调用被委托给一个后端处理机。业务逻辑是相当简单的。它是在一个集合中保存消息的simplebackendimpl.java类的单一实例。

  初看起来,置配器/后端实现看起来对于用于一个简单的教程太复杂了。然而,即使复杂的现有的业务逻辑可以被重使用来变成一个没有任何改变它的代码的需要的web服务。这是一个常见的现实的使用案例。即使应用程序没有使用原来的适配器模式,编写一个象chatservice这样的包装类,不需要重写原始的后端程序逻辑。然而,后端可以使用jdbc和一个关系数据库来实现,否则作为一个ejb,甚至调用外部非java应用程序的本地方法。可能发生的事是无穷尽的。适配器模式只允许你很快地触发新的后端逻辑。 把一个聊天服务器转为一个web服务

  现在,这个聊天服务器只是一个java实现。它还不是soap。它只是一个用于运行在相同jvm上的客户端的可工作的聊天服务器。下一步就是生成聊天服务器发言soap并且创建一个描述它的wsdl文档。

  这个示例使用systinet的web applications and services platform(wasp)软件来创建web服务应用程序。wasp软件是平台无关的并且工作在几乎任何java环境中。这个平台提供了两个不同的部署情况:编程部署和声明部署。在这两种情况下,取得部署的是简单的旧的java对象。编程部署(也称运行时间发布)发生在一个应用的运行时间并且能动态的部署应用程序为web服务。你只要在你的应用程序中逐步开始wasp,并且使用到wasp应用编程接口的调用注册它的对象。换句话说,你事实上把wasp嵌入到你的应用程序。声明部署意味着把你的应用程序包装到一个部署程序包并且把这个发布到一个wasp的运行实例中。为了简单和便于访问起见,我们使用运行时间发布方法。

用java web服务打造聊天程序(图一)
图1:导入现有的代码

  安装聊天服务器到eclipse中

  假定你让带有wasp developer的eclipse启动并运行,安装示例代码。

  在eclipse中创建一个新建项目(file - > new - > project...)。选择systinet web services/web service project。

  在下面的对话框中输入项目名,chatserviceproject和位置。结束向导。

  从file菜单中,选择import...命令,并且选择zip file方法。

  在对话框中选择前面源代码中下载的压缩文件,并且点击finish按钮。

  你的工程现在应该包含两个带有chat service的源代码的程序包。你可以通过检查package explore视图来检查。

  soap启动聊天服务器

  现在你有了一个简单的聊天服务器的一个工作实现。为了能与soap通信,你要把它部署到使用运行时间发布方法的web服务服务器。

  启动绝对地址的服务器并且在服务器的地址下注册这个服务。服务器地址+服务路径组成了web服务的完整的uri。

  这里是启动soap服务器并且把聊天服务注册为一个web服务的应用程序代码类。这个源代码文件应该(很明显)应该被存为chatserverapp.java。

package com.systinet.simplechat.server.impl;

import org.systinet.wasp.*;
import org.systinet.wasp.webservice.registry;

public class chatserverapp {

public static void main(string[] args) throws exception {
wasp.startserver("http://localhost:6060");
registry.publish("/chatservice/", chatservice.class);

system.out.println("the chat server is up and running.");
}
}

  它很简单,只有两行代码:

wasp.startserver("http://localhost:6060");
registry.publish("/chatservice/", chatservice.class);

  wasp.startserver方法启动一个java应用程序内的服务器。registry.publish方法编程地部署chatservice类为一个web服务。这个服务的uri由服务器的地址和服务器的服务路径组成。wasp还自动地创建描述服务wsdl文档并且把它发布在service_uri/wsdl。

用java web服务打造聊天程序(图二)
图2:运行服务器。 构造并运行聊天服务器

  聊天服务器现在可以运行了。在构造完毕之后(project->build add),你可以启动它。首先,创建一个web服务运行器。这个运行器保证服务器有所有需要的库并且被适当的配置。为了创建运行器,从com.systinet.simplechat.server.impl程序包中选择chatserverapp并且从ide菜单中选择run->run...。

  打开的对话框是工程中的所有的运行器的管理器。双击wasp java application运行模板。创建了一个称为chatserverapp的新的运行器。总是使用这个运行器来运行chatserverapp类。按下run按钮来启动聊天服务器。

  服务器启动并且运行,准备与soap通信。它的位置是http://localhost:6060/chatservice/。动态生成wsdl文档的位置是http://localhost:6060/chatservice/wsdl。

  业务逻辑现在使用runtime api被编程部署到服务器上。

用java web服务打造聊天程序(图三)
图3:运行服务器的输出。

  客户端

  现在,你需要一个消费这个chatservice的客户端。

  假定你对这个服务所了解的所有的东西只是它的wsdl描述的位置: http://localhost:6060/chatservice/wsdl。你不能访问原始的web服务的源代码。你甚至不知道它是使用什么语言来实现的。你还不知道chatservice的精确位置,但是你知道每个web服务都在它的wsdl文档中完全描述。

  服务器创建一个代理,隐藏所有的soap并且从开发者垂直传送,并且让它们使用单一方法调用来调用web服务。为了运行,这个代理必须知道web服务的wsdl描述的位置,web服务的uri和它的java接口。你知道chatservice的wsdl位置,并且服务的uri包含在这个wsdl中。现在你所需要的是取得服务的java接口。手工创建它意味着非常了解wsdl和xml schema,并且它甚至仍然是一个很难的任务。幸运的是,wasp developer包含一个从它的wsdl生成一个web服务的java接口的工具。这个工具,称为wsdl2java,可用作命令行实用程序和一个ant任务,所以它非常便于与使用ant的构造整合。

用java web服务打造聊天程序(图四)
图4:创建客户端程序包。

  客户端的代码

  首先,创建一个用于客户端的新的程序包。从菜单选择file - > new - > package。在new package对话框中输入名为com.systinet.simplechat.client的程序包,并且按下finish按钮。

  wasp developer需要wsdl文件存在于工程中以便生成客户端类。下载聊天服务的wsdl文档到工程中。选择com.systinet.simplechat.client程序包,并且从菜单选择file - > new - > other...。new对话框现在打开了。在左边的工具栏中选择systinet web services。所有可用的向导现在出现在右边的工具栏中。选择wsdl from internet条目并且转到下一窗囗。

  在第二个窗口中填入wsdl文件的位置并且选择next。chatservice的wsdl文件位于http://localhost:6060/chatservice/wsdl。

  在最后一个窗口中,填充下载的wsdl文件的名称。设置它为chatservice并且点击finish。

  wsdl文件现在在你的工程中了。为了生成客户端类,从它的上下文菜单选择generate client...条目。

  当generate client from wsdl向导打开的时候,所有的值都设置为它们的默认值并且结束向导。

  现在你在两个新程序包中创建了几个文件;com.systinet.simplechat.client.iface和com.systinet.simplechat.client.iface.struct。前一个程序包包含接口定义,chatservice.java和一个被wasp框架使用的支持文件chatservice.xmap。后一个程序包包含使用在chatservice.java接口- chatmessage.java和chatperson.java的附加的结构。如果你检查这个生成的类,它们应该为你所熟知。它们不是原始的chatservice接口类准确无误的副本,但是它们精确地描述它的应用编程接口。

  还有一个wasp developer从wsdl文件创建的类。看看com.systinet.simplechat.client程序包。那里有一个新的文件,chatserviceclient.java。这是一个客户端应用程序生成的骨架。列表1显示了这个文件中的类。

  首先,几个wasp类被导入,然后你看看chatservice接口的导入的内容和从wsdl文件中生成的结构。这段代码的有意思的部分在main()方法中:

serviceclient serviceclient = serviceclient.create
(wsdluri, chatservice.class);
serviceclient.setserviceurl(serviceuri);
serviceclient.setwsdlservicename(new qname
("http://systinet.com/wsdl/com/systinet/simplechat/server/impl/", "chatservice"));
serviceclient.setwsdlportname("chatservice");
service = (chatservice) registry.lookup(serviceclient);

  这些代码创建客户端使用来远程调用聊天服务的代理。wasp developer生成比简单客户端需要的更多代码。因为wsdl文件可以包含有关多数的web服务的信息,生成的代码有些复杂,所以它能用于任何wsdl文件。然而,下面的一行代码将以同样的方法用在我们的简单的例子:

service = (chatservice) registry.lookup
("http://localhost:6060/chatservice/wsdl/", chatservice);

  服务对象现在准备调用。它的方法的每个调用导致聊天服务的远程调用。结束客户端来调用聊天服务。列表2显示了扩展的自生成的代码。

  构造和运行客户端既然客户端被实现,你需要构造并且运行它。为了构造代码,从菜单运行project - > build all命令。

  为了运行客户端,你将需要它的web服务运行器。

  选择工程中的chatserviceclient类并且从菜单选择run - > run...。双击wasp java application条目。一个称为chatserviceclient的新的运行器被创建并且随时可使用客户端。总是使用这个运行客户端。按下run按钮来启动客户端。

  客户端连接到聊天服务并且调用它的两个方法。在客户端的两次执行之后到控制台的输出应该如图5所示。

用java web服务打造聊天程序(图五)
图5:聊天客户端的输出。

扫描关注微信公众号