服务热线:13616026886

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

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

applet与servlet通讯的四种方法及其比较


   applet与servlet之间的联系一般是间接的,即页面请求由浏览器发送给servlet,
  作为回答,servlet将结果生成html文档发送给浏览器。很多时候在servlet与applet之
  间建立直接的联系是没有必要的,但如果要显示一些实时的动态数据,如聊天室窗口、
  新闻显示、股市行情等,建立两者之间的直接联系就很有用了。特别地,在较为复杂的
  分布式java应用中,这种通讯更是必不可少。在客户端java程序与服务器端java程序之
  间建立这种复杂的交互方式仅仅使用servlet与applet api是不够的,本文为你介绍和比
  较四种通讯方式:通过html页面传递参数,用java.net包的网络功能建立直接网络连接
  ,远程方法调用(rmi)与corba。
   一、通过html页面传递applet参数
   通过html页面传递参数是在servlet与applet之间建立联系最为常用的方法。serv
  let只要把传递给applet的参数写入html页面就可以了。这种通讯是单向的,用于实现s
  ervlet对applet的控制。其实现方法类如:
  // doget()方法生成一个包含applet的html页面,
  // 该applet需要一个data参数
  applet与servlet通讯的四种方法及其比较
   这种方法很简单,但它有两个缺点。首先,所有参数都是静态的,即一旦html页面
  发送完成,要更新其中部分数据就很困难了。虽然可以使用http的刷新机制,但这种刷
  新需要重新下载整个页面,效率是很低的。第二,如果需要传递给applet的数据量很大
  或数据结构很复杂,就会使得html页面过于庞大或复杂了。
   二、用java.net包建立双向通讯
   第二种方法是利用java.net包提供的网络能力。以有连接流通讯方式为例,在服务
  器端的操作为一般为:
   ⑴ 创建一个serversocket对象,在指定端口监听客户端发来的请求。
   ⑵ 在接收到请求时accept()方法将返回一个socket对象。
   ⑶ 用上述socket对象创建输入、输出流对象。
   ⑷ 通过输入、输出流与客户交互。
   ⑸ 交互完毕,关闭输入、输出流与socket。
   ⑹ 服务程序运行结束,关闭serversocket。
   实现代码代码类如:
  try{
  boolean flag=true;
  socket clientsocket=null;
  serversocket serversocket = new serversocket(0);
  system.out.println("server listen on: " +serversocket.getlocalport());
  while(flag){
  clientsocket=serversocket.accept();
  datainputstream is=new datainputstream( new bufferedinputstream(clientsocket
  .getinputstream()));
  printstream os=new printstream( new bufferedoutputstream(clientsocket.getout
  putstream()));
  // 处理applet请求
  os.close();
  is.close();
  clientsocket.close();
  }
  serversocket.close();
  }catch( ioexception e){
  system.err.println(" exception: "+e);
  }
   在客户端的操作为:
   ⑴ 创建socket对象建立与服务器的连接。
   ⑵ 用该socket对象创建输入、输出流。
   ⑶ 与服务器交互。
   ⑷ 交互完毕,关闭输入、输出流与socket。
   实现代码类如:
  try {
  socket clientsocket =new socket("servername",7);
  outputstream os=clientsocket.getoutputstream();
  datainputstream is=new datainputstream( clientsocket.getinputstream());
  // 其它操作.
  os.close();
  is.close();
  clientsocket.close();
  }catch(exception e){
  system.err.println("exception:"+e);
  }
   这种方法只依赖于标准的java网络支持,不需要用到附加的软件包或工具, 因此
  显得相当简洁和灵活,易于实现某些特殊的需要。但在另一方面,服务器端对进入请求
  以及客户端对返回结果的分析工作量较大。如果服务器端要执行大量的操作,可以考虑
  使用rmi。
   三、远程方法调用rmi
   java的rmi技术显著地改善了客户程序操作复杂的服务器端对象的能力。对applet
  来说,服务器端对象所提供的远程方法可以象普通的客户端句柄一样调用。使用rmi时应
  先定义远程接口,即一个继承自java.rmi.remote的公用接口。在该接口中定义要求在服
  务器上运行的方法,所有这些方法的throws子句至少应该声明java.rmi.remoteexcepti
  on异常。
   接下来是实现远程接口,远程接口的实现类应该:
   ⑴ 指定所实现的一个或多个接口。
   ⑵ 定义远程对象的构造方法。
   ⑶ 提供所有可供远程调用的方法的实现。
   ⑷ 创建和安装安全管理器。
   ⑸ 创建一个或多个远程对象实例。
   ⑹ 注册至少一个远程对象。
   下面的代码实现一个返回日期字符串的getdata()远程方法,该方法由接口rmiser
  v2app定义:
  // 本类继承自unicastremoteobject,实现接口serv2app
  package com.servletsolutions.serv2app.rmi;
  import java.rmi.*;
  import java.rmi.server.*;
  public class rmiimplementation extends unicastremoteobject
  implements rmiserv2app{
  public rmiimplementation() throws remoteexception{}
  public string getdata() throws remoteexception{
  return java.text.dateformat.getdateinstance().format(
  new java.util.date());
  }
  public static void main(string[] args){
  // 安全管理器
  system.setsecuritymanager(new rmisecuritymanager());
  try{
  // 远程对象实例
  rmiimplementation bootstrap = new rmiimplementation();
  // 注册
  naming.bind(args[0], bootstrap);
  system.out.println(args[0] + " 注册成功");
  }catch(exception e){
  system.err.println("注册失败.");
  system.err.println(e);
  }
  }
  }
   在客户端,applet对接口rmiserv2app的引用通过调用naming.lookup(string)获得
  ,如下所示:
   rmiserv2app obj = (rmiserv2app)naming.lookup("//" + getcodebase().getho
  st() + "/servername");
   除了编译java代码之外,还要用rmic编译器生成远程对象的存根和骨架。存根(s
  tub)是远程对象在客户端的代理,它将rmi调用传递给服务器端的骨架(skeleton),
  后者负责将该调用传递给实际的远程方法。例如执行命令rmic com.servletsolutions.
  rmiimplementation,则生成的两个类文件分别为rmiimplementation_stub.class 和rm
  iimplementation_stub.class,前者封装入applet且运行于客户端,后者封装入servle
  t且运行与服务器端。
   当大量的数据是由服务器端的对象动态提供时使用rmi是非常合适的。虽然rmi支持
  面向对象的分布式编程,但它要求客户端和服务器端都是java程序。因此,对于使用混
  合语言开发的应用来说,corba比rmi更为适用。
   四、使用corba
   corba即公用对象请求代理体系(common object request broker architecture)
  ,它的使用方法类似于rmi:定义接口,使用某个工具创建stub和skeleton,实现接口,
  在服务器上注册后客户就可以像本地对象一样访问远程对象了。两者主要的不同之处在
  于,corba使用一种语言中立的接口定义语言(idl)来定义接口,idl是一种可用于混合
  语言环境的更为广泛的协议集。corba最大的缺点在于客户本身必须具备调用orb的能力
  ,这往往意味着增加一个体积较大的jar文件。
   下面的corbaserv2app.idl是上述getdata()接口的idl描述,它定义了一组与java
  包名字对应的嵌套模块:
  module com {
  module servletsolutions {
  module serv2app {
  module corba {
  interface corbaserv2app{
  string getdata();
  };
  };
  };
  };
  };
   可以用idl2java从idl文件生成对应的java文件。其中_corbaserv2appimplbase.j
  ava包含了描述该接口的java抽象类,下面的corbaimplementation类继承自抽象类_cor
  baserv2appimplbase并具体实现getdata()方法:
  package com.servletsolutions.serv2app.corba;
  public class corbaimplementation extends _corbaserv2appimplbase {
  corbaimplementation(string s){ super(s); }
  public string getdata(){
  return java.text.dateformat.getdateinstance().format(new java.util.date());
  }
  }
   为了让该类可以被客户访问,servlet中还应该创建其实例。代码如下所示:
  // 在servlet的init()方法中初始化corbaimplementation对象
  // 其中boa(basic object adapter)的作用类似于rmi中的注册服务
  (程序略)

扫描关注微信公众号