荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Peter (小飞侠), 信区: Program
标  题: 服务器端Java应用编程
发信站: BBS 荔园晨风站 (Thu Jan 21 22:48:44 1999), 转信


   到目前为止,相信大家对客户端Java已经比较熟悉了,甚至可能已
经写过许多出色的App lets小程序。但是,大家可能不太熟悉服务器
端Java,也没写过服务器端Applet。本文将带领读者初窥服务器端Jav
a的门径。
    服务器端Java(SSJ,Server Side Java)是公共网关接口(CGI)和
低级服务器API程序设计(例如Netscape的NSAPI与Microsoft的ISAPI)
的混合体。有时我们称SSJ为Servlets或服务器端Applet。
    本文向大家介绍服务器端Java及引导大家一步步实现服务器端Ja
va的执行程序,Netscp e称之为服务器端Applets(SSA,Server Side A
pplet)。
    SSA像CGI的脚本程序一样,接收"get"和"post"请求,并返回一个W
eb页面(通常以HTML形式)。但是SSJ如同NSAPI/ISAPI一样是动态地装
入服务器的,这就消除了CGI启动时的延迟,也使SSJ能在两次执行中维
持它自身的状态,例如保持与数据库开放的连接。
    SSA在他们自己的"沙箱"("sandbox")中执行,这样可以保证安全
。例如,一个毁灭性的p plet不会像NSAPI/ISAPI程序设计那样摧毁整
个服务器,这种安全性允许上载执行Applet,就像客户机端Java的下载
执行Applet一样。SSA最重要的优点是Java的平台无关性和面向对象
的特性。
    本文以Netscape服务器Enterprise 2.0和Fast Track 2.0为例来
介绍服务器端Java应用的开发。

    准备服务器
    在编写服务器端Applet前,需要准备相应的服务器。首先打开服
务器的Java解释器。在服务器管理器的"Programs->Java"栏下点击"y
es"按钮启动Java解释器,服务器管理器就会提示输入"Java applet d
irectory",以存放SSA类文件。服务器提供有缺省地址。在Unix机上,
缺省值是/usr/ns-home/plugins/java/applets。在Windows机上,缺
省值为c:Program Fil es\Netscape\Server\plugins\Java\applets(
注:在这个输入栏,Netscape常常对其\  和 / 不加区别。不必担心,N
etscape对这两种类型斜杠的处理方式是相同的。)可能的话最好使用
缺省目录。如果习惯于自己的目录,只要该目录是在服务器的根目录
下面,就可把缺省目录下的所有文件拷贝到自己的工作目录下,保存这
些改动,关闭服务器,再重新启动该服务器。
    实验
    下面,我们利用Netscape提供的Applet进行实验。把浏览器指向h
ttp://servername/se rver-java/Connect,它加载并显示http://www
..meer.net/barn/index.html。Connet apple t为取出此页面建立一
个socket通讯,如果服务器在一个防火墙后面,这可能会导致服务器错
误。下面,让我们假定防火墙阻塞了socket,我们将编辑Connect appl
et代码,使它能在不同的Web服务器中访问不同页面。
    在"Java applet目录"中可得到Connect.java文件。它包含开发
服务器端Applet的基本类,其中最重要的类是HttpApplet,这是所有服
务器端Applet的超级类。实现服务器端Applt 所需的唯一方法是run
方法,Applet每接收一次"hit"就要执行一次该方法。在使输出转到客
户机之前,Connect的run方法向"host"打开一个socket并取出"reques
t"。通过设置变量"hs t",可以访问任一台机器;同样设置变量"reque
st",可以访问某"host"上的任一个页面。
    import netscape.server.applet.*;
    import java.io.PrintStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.DataInputStream;
    import java.net.Socket;
    class Connect extends HttpApplet {
    public void run() throws Exception {
        String host = "www.meer.net";
        //读者可以根据自己的环境修改此主机名
        int port = 80;
        String request = "GET /barn/index.html HTTP/1.0\n";
        // 同样可以修改
        Socket s = new Socket(host, port);
        OutputStream os = s.getOutputStream();
        PrintStream op = new PrintStream(os);
        op.println(request);
        InputStream is = sam();
        DataInputStream di = new DataInputStream(is);
        String line;
        if (returnNormalResponse("text/html")) {
            PrintStream out = getOutputStream();
            out.println("&lth1&gtData on "+host+ "  port  "+
port+ "</h1&gt" );
            out.println("request: "+request+"<hr>");
            while ((line = di.readLine()) != null)
                out.println(line);
        }
    }}
    设置变量"host"或"request"后,下一步就是重新编译Connect。
    在Windows系统下,把标准javac编译器的classpath设置成包括se
rv2-0.zip.javacclss path..\classes\serv2-0.zip Connect.java

    在Unix系统下,Netscape在Java applet目录的上级目录中提供一
个Java编译器(javac。这个javac用来编译的实际上是一个叫做java
sun.tools.javac.Main的脚本程序。在某些系统中,sun.tools.javac
..Main编译器使用新版JDK1.1中的方法,例如java.lang.Characte.is
JavaLetterOrDigit(),如果没有JDK1.1,可能会遇到很多麻烦。最好
选择常用的标准jaac编译器,如javacclasspath../classes/serv2-0.
zip Connect.java。如果要使用服务器提供的javac脚本程序,只需
用"../javac"来替换"javac"。
    在这个编译过程中,可能会出现这样一个错误:
    Connect.java:1:Package netscape.server.applet not found
in import.import nt scape.server.applet.*;
    ^
    1 error在import语句中删掉wildcards,就可避免这个错误。
    在Unix系统下,Netscape在Java applet目录中提供一个makefile
文件,以控制Applet的编译。可惜,这个makefile文件使用‘%’wildc
ard,它是mk/nmake的扩展,有时不可获取其代码。问题代码如下:
    %.class;%.java../javac -classpath ../classes/serv2-0.zip
$ *.java解决办法是使用suffixes规则,编辑makefile文件的第一行
,如:SUFFIXES :java.class然后执行:
    javac -classpath ../classes/serv2-0 zip $ <即删去了../,
这样makefile文件就可调用标准的javac编译器。测试这个新的makef
ile文件,重新保存Connect.java文件,然后执行"make"。

    Methods
    下面介绍几个有用的方法(Methods)。

    1.PrintStream getOutputStream() throws IOException;
    返回一个PrintStream,把响应输出到客户机上,此方法代替了Sys
tem.out。
    2.Hashtable getFormData() throws IOException;
    返回一个Hashtable(哈希表),其中存储有HTPP请求的name-value
对,value串是从加密的URL形式解密后得到 的。若没有form data,则
显示I/O异常。
    3.String getFormField(String fieldName)throws IOExceptio
n;
    利用getFormField方法能找到一个field,且仅仅一个。若没有fo
rm data,也显示I/O异常。

    4.boolean retrunNormalResponse(String contentType)throws
IOException;
    根据在参数中指定的内容类型启动HTTP响应。若是"get"或"post
"请求则返回值为tru, 若是"head"请求则返回false。

    5.public boolean returnErrorResponse(String contentType,
int status,Stringre ason) throws IOException;
    启动响应报错 。它带有三个参数:内容类型、状态(例如HttpApp
let BAD-REQUEST,其标准错误代码号为400),以及可缺省的用来说明
错误原因的字符串。
    Netscape在它的服务器中安装了一个API入门手册,其中有许多开
发服务器端Java经常调用的方法。在Unix系统下,通过/usr/ns-home/
bin/httpd/admin/html/manual/pg/javapi.t m,可找到此入门手册;
在Windows系统下,路径则为C:\Program Files\Netscape\Server\bn\
httpd\admin\html\manual\pg\javapi.htm。
    举例"Hello World"!
    现在让我们应用以上所述内容写一个"Hello World"服务器端App
let。当给出"target" 栏时,此Applet就向target问侯Hello,否则就
向"World"问候Hello。
    import netscape.server.applet.HttpApplet;
    import java.io.IOException;
    import java.io.PrintStream;
    class Hello extends HttpApplet {
    /* 缺省情况下,向"World"问候Hello */
    String helloTarget = "World";
    /* run() 用来处理请求  */
    public void run() throws Exception {
    /* getOutputStream() 用来与Client通话  */
    PrintStream out = getOutputStream();
    /* 使用 getFormField() 来确定是否与"World"以外的人物问候
Hello*/
    String formTarget = null;
    try {
      formTarget = getFormField("target");
      if (formTarget != null) {
        helloTarget = formTarget;
      }
    }
    catch (IOException e) {
      if (! e.getMessage().startsWith("missing query string"
)) {
        handleException(e, out);
      }
    }
    /* 问候Hello  */
    if (returnNormalResponse("text/html")) {
      try {
        out.println("Hello, " + helloTarget + "!");
      }
      catch (Exception e) {
        handleException(e, out);
      }
    }  }  private void handleException(Exception e, PrintStr
eam out) {
    try {
      returnErrorResponse("text/html", SERVER_ERROR, "Except
ion thrown");
    }
    catch (IOException ioe) {}  // 试图打印原始exception
    out.print("&lth1&gt");
    out.print(e);
    out.print("&lt/h1&gt\n");
    out.print("&ltpre&gt");
    e.printStackTrace(out) ;
    out.print("&lt/pre&gt");
    return;
    }}
    这个服务器端Applet像所有Netscape下的服务器端Applet一样是
netscape.server.apl et.HttpApplet的子类,并重载了方法run();通
过调用getOutputStream,可快速地得到一个输出流,即打印"Hello"(
或打印失败的原因)。调用getFormField来检查是否存在一个二选一
的target栏,然后返回一个正常的"text/html"响应,最后打印"Hello"
。我们注意到,该Appets 检查returnNormalResponse()的返回值,若
返回false时不做任何操作。如果不对返回值进行检查的话,则甚至对
"head"请求也会返回数据。

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店