到 目 前 为 止, 相 信 大 家 对 客 户 端java 已 经 比 较 熟 悉 了, 甚 至 可 能 已 经
写 过 许 多 出 色 的applets 小 程 序。 但 是, 大 家 可 能 不 太 熟 悉 服 务 器 端java,也 没 写 过 服 务 器 端applet。 本 文 将 带 领 读 者 初 窥 服 务 器 端java 的 门 径。
服 务 器 端java(ssj,server side java) 是 公 共 网 关 接 口(cgi) 和 低 级 服 务 器api
程 序 设 计( 例 如netscape 的nsapi 与microsoft 的isapi) 的 混 合 体。 有 时 我 们 称ssj
为servlets 或 服 务 器 端applet。
本 文 向 大 家 介 绍 服 务 器 端java 及 引 导 大 家 一 步 步 实 现 服 务 器 端java 的
执 行 程 序,netscape 称 之 为 服 务 器 端applets(ssa,server side applet)。
ssa 像cgi 的 脚 本 程 序 一 样, 接 收“get” 和“post” 请 求, 并 返 回 一个web 页 面( 通 常 以html 形 式)。 但 是ssj 如 同nsapi/isapi 一 样 是 动 态 地 装 入服 务 器 的, 这 就 消 除 了cgi 启 动 时 的 延 迟, 也 使ssj 能 在 两 次 执 行 中 维 持它 自 身 的 状 态, 例 如 保 持 与 数 据 库 开 放 的 连 接。
ssa 在 他 们 自 己 的“ 沙 箱”(“sandbox”) 中 执 行, 这 样 可 以 保 证 安 全。
例 如, 一 个 毁 灭 性 的applet 不 会 像nsapi/isapi 程 序 设 计 那 样 摧 毁 整 个 服 务器, 这 种 安 全 性 允 许 上 载 执 行applet, 就 像 客 户 机 端java 的 下 载 执 行applet一 样。ssa 最 重 要 的 优 点 是java 的 平 台 无 关 性 和 面 向 对 象 的 特 性。
本 文 以netscape 服 务 器enterprise 2.0 和fast track 2.0 为 例 来 介 绍 服 务 器
端java 应 用 的 开 发。 准 备 服 务 器 在 编 写 服 务 器 端applet 前, 需 要 准 备 相 应
的 服 务 器。 首 先 打 开 服 务 器 的java 解 释 器。 在 服 务 器 管 理 器 的“programs
->java” 栏 下 点 击“yes” 按 钮 启 动java 解 释 器, 服 务 器 管 理 器 就 会 提 示 输
入“java applet directory”, 以 存 放ssa 类 文 件。 服 务 器 提 供 有 缺 省 地 址。
在unix 机 上, 缺 省 值 是/usr/ns ??home/plugins/java/applets。 在windows 机 上, 缺 省
值 为c:/program files/netscape/server/plugins/java/applets( 注: 在 这 个 输 入栏,netscape 常 常 对 其/ 和 / 不 加 区 别。 不 必 担 心,netscape 对 这 两 种 类 型 斜 杠的 处 理 方 式 是 相 同 的。) 可 能 的 话 最 好 使 用 缺 省 目 录。 如 果 习 惯 于 自 己 的目 录, 只 要 该 目 录 是 在 服 务 器 的 根 目 录 下 面, 就 可 把 缺 省 目 录 下 的 所 有文 件 拷 贝 到 自 己 的 工 作 目 录 下, 保 存 这 些 改 动, 关 闭 服 务 器, 再 重 新 启动 该 服 务 器。
实 验
下 面, 我 们 利 用netscape 提 供 的applet 进 行 实 验。 把 浏 览 器 指
向http://servername/server ??java/connect, 它 加 载 并 显
示http://www.meer.net/barn/index.html。connect applet 为 取 出 此 页 面 建 立 一 个socket
通 讯, 如 果 服 务 器 在 一 个 防 火 墙 后 面, 这 可 能 会 导 致 服 务 器 错 误。 下
面, 让 我 们 假 定 防 火 墙 阻 塞 了socket, 我 们 将 编 辑connect applet 代 码, 使 它
能 在 不 同 的web 服 务 器 中 访 问 不 同 页 面。
在“java applet 目 录” 中 可 得 到connect.java 文 件。 它 包 含 开 发 服 务 器
端applet 的 基 本 类, 其 中 最 重 要 的 类 是httpapplet, 这 是 所 有 服 务 器 端applet
的 超 级 类。 实 现 服 务 器 端applet 所 需 的 唯 一 方 法 是run 方 法,applet 每 接 收 一次“hit” 就 要 执 行 一 次 该 方 法。 在 使 输 出 转 到 客 户 机 之 前,connect 的run 方法 向“host” 打 开 一 个socket 并 取 出“request”。 通 过 设 置 变 量“host”, 可 以访 问 任 一 台 机 器; 同 样 设 置 变 量“request”, 可 以 访 问 某“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>");
out.println(“request: "+request+“<hr>");
while ((line = di.readline()) != null)
out.println(line);
}
}
}
设 置 变 量“host” 或“request” 后, 下 一 步 就 是 重 新 编 译connect。
在windows 系 统 下, 把 标 准javac 编 译 器 的classpath 设 置 成 包 括serv2
??0.zip.javac ??classpath ?? ??/classes/serv2 ??0.zip connect.java。
在unix 系 统 下,netscape 在java applet 目 录 的 上 级 目 录 中 提 供 一 个java 编
译 器(javac)。 这 个javac 用 来 编 译 的 实 际 上 是 一 个 叫 做java sun.tools.javac.main 的
脚 本 程 序。 在 某 些 系 统 中,sun.tools.javac.main 编 译 器 使 用 新 版jdk11 中 的 方法, 例 如java.lang.character.isjavaletterordigit(), 如 果 没 有jdk11, 可 能 会 遇 到 很
多 麻 烦。 最 好 选 择 常 用 的 标 准javac 编 译 器, 如javac ??classpath. ??/classes/serv2
??0.zip connect.java。 如 果 要 使 用 服 务 器 提 供 的javac 脚 本 程 序, 只 需
用“../javac” 来 替 换“javac”。
在 这 个 编 译 过 程 中, 可 能 会 出 现 这 样 一 个 错 误:
connect.java:1:package netscape.server.applet not found in import.
import netscape.server.applet. *;
^
1 error
在import 语 句 中 删 掉wildcards, 就 可 避 免 这 个 错 误。
在unix 系 统 下,netscape 在java applet 目 录 中 提 供 一 个makefile 文 件, 以 控
制applet 的 编 译。 可 惜, 这 个makefile 文 件 使 用‘ %’wildcard, 它 是mk/nmake 的扩 展, 有 时 不 可 获 取 其 代 码。 问 题 代 码 如 下:
%.class; %.java
../javac ??classpath ../classes/serv2 ??0.zip $ *.java
解 决 办 法 是 使 用suffixes 规 则, 编 辑makefile 文 件 的 第 一 行, 如:suffixes
:java.class 然 后 执 行:
javac ??classpath ../classes/serv2 ??0 zip $ <
即 删 去 了../, 这 样makefile 文 件 就 可 调 用 标 准 的javac 编 译 器。 测 试 这 个新 的makefile 文 件, 重 新 保 存connect.java 文 件, 然 后 执 行“make”。
methods
下 面 介 绍 几 个 有 用 的 方 法(methods)。
1.printstream getoutputstream() throws ioexception;
返 回 一 个printstream, 把 响 应 输 出 到 客 户 机 上, 此 方 法 代 替了system.out。
2.hashtable getformdata() throws ioexception;
返 回 一 个hashtable( 哈 希 表), 其 中 存 储 有htpp 请 求 的name ??value
对,value 串 是 从 加 密 的url 形 式 解 密 后 得 到 的。 若 没 有form data, 则 显 示i/o
异 常。
3.string getformfield(string fieldname)throws ioexception;
利 用getformfield 方 法 能 找 到 一 个field, 且 仅 仅 一 个。 若 没 有form data, 也
显 示i/o 异 常。
4.boolean retrunnormalresponse(string contenttype)throws ioexception;
根 据 在 参 数 中 指 定 的 内 容 类 型 启 动http 响 应。 若 是“get” 或“post” 请
求 则 返 回 值 为true, 若 是“head” 请 求 则 返 回false。
5.public boolean returnerrorresponse(string contenttype,int status,string reason) throws
ioexception;
启 动 响 应 报 错 。 它 带 有 三 个 参 数: 内 容 类 型、 状 态( 例 如httpapplet
bad ??request, 其 标 准 错 误 代 码 号 为400), 以 及 可 缺 省 的 用 来 说 明 错 误
原 因 的 字 符 串。
netscape 在 它 的 服 务 器 中 安 装 了 一 个api 入 门 手 册, 其 中 有 许 多 开 发 服
务 器 端java 经 常 调 用 的 方 法。 在unix 系 统 下, 通 过/usr/ns
??home/bin/httpd/admin/html/manual/pg/javapi.htm, 可
闽公网安备 35060202000074号