我一般通过URLConnection+数字签名!你呢!?

解决方案 »

  1.   

    转载: 通信策略
        如果你使用了这样的构造:在前端使用Applet,在后端使用Servlet,那么你将需要执行Applet和Servlet的通信。因为Applet受浏览器的安全模式的限制,我们在对一个Applet存取数据和信息时并没有太多的选择。正如我们在前面提到的,我们不能读取客户端的文件系统、不能运行客户端的程序,由于Applet不是在服务器上运行的,我们也不能访问服务器上的文件系统。我们只能建立到运行在我们的主机上的服务的网络连接。另外,不要忘记应用程序是在一个公开的Internet上发布的,防火墙可能会限制通过HTTP到Servlet或其它web-server模块的会话。事实上,因为Applet本身就是在网络上通过HTTP发布的,所以我们必须准确把握通信的策略。
        假定在客户端的Applet和服务器端的Servlet之间的网络连接是我们可以使用的唯一的通信路径,我们可以有几种方法交换信息。正如你知道的,文字流可以由服务器通过HTTP发放。但是你可能不知道Java对象出可以用这种方式发放。我们将详细地介绍HTTP文字流和HTTP对象流的使用。另外,我们将简单地介绍通过Socket进行通信的方法,当一个应用程序需要双向的、持续的连接时,这个方法会特别有用。
    HTTP文字流
        Applet与Servlet交换信息的最简单地方法就是通过HTTP文字流。Java的URL和URLConnection类型使得从一个URL读取数据变得很容易,你可以不用担心Socket和其它有关网络工作的通常的复杂问题。我们所需要的只是一个服务器端的组件,这个组件应该可以通过URL发放信息。这就是我们在这儿使用Servlet的原因。
        作为一个例子,我们想要监控服务器的JVM所能使用的内存的总数,并在一个Applet中用一个简单的仪表显示它。首先我们需要开发一个Servlet,当通过它的URL访问这个Servlet时可以返回我们所需要绘制仪表的信息。这个Servlet的源代码如清单1所示。
    清单1
    import javax.servlet.*;
    import javax.servlet.http.*;
    public class ShowMemservlet extends Httpservlet {
       public void doGet(HttpservletRequest req, HttpservletResponse res)
       throws servletException, IOException {
          res.setContentType("text/plain");
          PrintWriter out = res.getWriter();
          Runtime rt = Runtime.getRuntime();
          out.println(rt.freeMemory());
          out.println(rt.totalMemory());
       }
    }
        这个非常简单的Servlet会响应一个GET请求(直接通过浏览器或者是象我们在下面将看到的那样通过我们的Applet),并返回两行文字。第一行显示了服务器的JVM的剩余的自由空间,第二行显示了JVM可用的全部空间(译者注:包括已使用的空间)。
        要建立我们的Applet中的仪表,我们只需要建立一个到这个Servlet的连接,将它的InputStream封装到一个DataInputStream中,读出这两个参数,将其转换成数字,并更新我们的仪表。我们可以让我们的Applet执行Runnable接口并在其自己的线程中运行。每隔一秒钟,我们可以运行一个方法来更新我们的仪表。refresh()方法的代码如清单2所示。
    清单2
    private void refresh() throws MalformedURLException, IOException {
       URL url = new URL(getCodeBase(), "/servlet/ShowMemServlet");
       URLConnection con = url.openConnection();
       con.setUseCaches(false);
       InputStream in = con.getInputStream();
       DataInputStream textStream;
       textStream = new DataInputStream(in);
       String line1 = textStream.readLine();
       String line2 = textStream.readLine();
       double freeMem = Double.parseDouble(line1);
       double totalMem = Double.parseDouble(line2);
       int usedMem = totalMem - freeMem;
       int percentUsed = (int) 100 *(usedMem / totalMem);
       meter.setLength(percentUsed);
    }
        正如你看到的,HTTP文字流的使用相当简单而且直接。Applet建立到Servlet的连接,读取它返回的两行信息并对其进行适当的处理。
        使用简单的文字流来交换数据有一个主要的弱点,那就是Applet并不直接理解数据的信息,而是要将其转换成一个有用的格式。在我们的例子中,将字符串转换成数字还不算太复杂,但是当我们试图处理一个更复杂的数据和对象时,转换的工作会很快变得无法控制。事实上,在下面我们可以看到我们一种简单的方法来处理这些复杂的数据。
    HTTP对象流
        你也许还没有意识到HTTP连接也可以用来传输二进制的数据,就象传输文本数据一样,但是事实上每次你从一个web看到图象时或者是下载.zip文件时都在使用这个功能。我们可以利用这个功能并结合被称之为"对象序列"的技术从Servlet向Applet传输完整的Java对象。复杂的数据可以很容易地被传输,你不需要做任何解析和解释。
        对象序列允许我们将对象封装到二进制数据流,它可以到达一个OutputStream可以到达的任何地方:磁盘、屏幕或者是在我们的例子中,通过一个HTTP连接到达一个Applet。对象序列是JVM1.1和更高的版本才支持的功能,所以有一些老版本的浏览器不支持这一功能。但是Sun公司的Java插件几乎可以对所有的浏览器进行升级以支持最终版本的Java,这样它就可以支持对象序列。
        使用HTTP对象流和使用HTTP文字流的方法几乎一样。我们建立一个到我们的web主机上的Servlet的URL连接并读取其返回的数据。只不过我们不再是将InputStream封装到DataInputStream中,而是将其封装到ObjectInputStream中。我们可以按照适当的类型读取其中的对象。
        清单3显示了我们用来交换一个对象的一段代码,这个对象用来从Servlet获得有关书目的信息(包括作者、题目、价格和其它信息)。你会注意到在这里我们用ObjectOutputStream取代了清单1中的PrintWriter,其基本概念是相同的。
    清单3
    public void doGet(HttpservletRequest req, HttpservletResponse res)
    throws servletException, IOException {
       OutputStream out;
       ObjectOutputStream objStream;
       out = res.getOutputStream();
       objStream = new ObjectOutputStream(out);
       Album album = fetchNextAlbum();
       out.writeObject(album);
    }
        这个Servlet会生成书目对象的序列化版本,它可从它的fetchNextAlbum()方法作为一个数据流被接收。如果你通过一个web浏览器来访问这个Servlet,你会看到一堆垃圾,这是因为目前你只能处理文本而不能处理二进制数据的对象序列。请注意这个对象必须执行Serializable接口以使其序列化。此外,任何引用这个对象的其他对象也必须执行Serializable接口。
        在Applet端,每当用户单击Applet的Next按钮时,我们可以使用方法getNextAlbum()(程序如清单4所示)来从服务器获得书目对象。Applet将查询这个对象并显示其中的数据。
    清单4
    private Album getNextAlbum() throws MalformedURLException, IOException {
       URL url = new URL(getCodeBase(), "/servlet/Albumservlet");
       URLConnection con = url.openConnection();
       con.setUseCaches(false);
       InputStream in = con.getInputStream();
       ObjectInputStream objStream;
       objStream = new ObjectInputStream(in);
       album = (Album)objStream.readObject();
       return album;
    }
        正如你看到的,对象流给我们提供了一个非常简便的方法在Applet和Servlet之前交换一组复杂的信息。请注意我们所处理的不是单纯的数据而是对象,所以你可以在客户端和服务器之间重用这个对象。这使得我们的程序更为智能化并且可以防止重复的逻辑处理。
    Socket连接
        另外,一种不太常用的Applet和Servlet的通信策略是在两者之间建立Socket连接。这意味着开发者利用Socket连接设计并执行适当的协议来处理两者之间的通信。
        使用Socket的一个大的好处是这个连接是持续的而且是双向的。一个基于HTTP的连接只能短暂地交换信息。如果你想要不断地用新的信息更新Applet,你必须不断地建立新的HTTP连接。而对于一个Socket连接来说,你可以只建立一个与服务器的连接,就能实现不断地更新。
        当然,你可能想要建立一个多线程的系统,这样可以有几个Applet同时与服务器联系。请注意使用Socket有的时候并不是一个适当的方法,绝大多数的防火墙不允许通过罕见的端口号进行通信。然而,在一个内部的Intranet上,这还是一项很有用的技术。APPLET和SERVLET的协同工作
        在这篇文章中,我们讨论了有关建立一个前端使用Applet、后端使用Servlet的应用程序的一些有用的策略。Applet只有一个唯一的通信路径,但是我们可以有几种在Applet和Servlet之间交换信息的方式。对于简单的数据和信息,我们可以使用纯文本来传递。对于直接使用对象的工作以及其他复杂的数据结构,我们可以使用对象序列。对于内部的一些特殊的需要实时双向的连接的应用,我们可以使用Socket连接。
        Sun公司的应用程序模型所推荐的策略和我们在这里讨论的一样。将事务逻辑从界面中分离可以使得应用程序更加灵活,易于升级,这样的应用程序也更易于设计和维护。但是这个模型不允许你的Applet直接访问你的企业数据,这会大大减少你的系统的复杂性并大大提高你的系统的安全性。Applet和Servlet的协同工作将有助于建立一个较好的应用。