返回介绍

15.6.2 程序片

发布于 2024-10-15 23:56:34 字数 6559 浏览 0 评论 0 收藏 0

程序片实际要比 NameSender.java 简单一些。这部分是由于很容易即可发出一个 GET 请求。此外,也不必等候回复信息。现在有两个字段,而非一个,但大家会发现许多程序片都是熟悉的,请比较 NameSender.java。

//: NameSender2.java
// An applet that sends an email address
// via a CGI GET, using Java 1.02.
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;

public class NameSender2 extends Applet {
  final String CGIProgram = "Listmgr2.exe";
  Button send = new Button(
    "Add email address to mailing list");
  TextField name = new TextField(
    "type your name here", 40),
    email = new TextField(
    "type your email address here", 40);
  String str = new String();
  Label l = new Label(), l2 = new Label();
  int vcount = 0;
  public void init() {
    setLayout(new BorderLayout());
    Panel p = new Panel();
    p.setLayout(new GridLayout(3, 1));
    p.add(name);
    p.add(email);
    p.add(send);
    add("North", p);
    Panel labels = new Panel();
    labels.setLayout(new GridLayout(2, 1));
    labels.add(l);
    labels.add(l2);
    add("Center", labels);
    l.setText("Ready to send email address");
  }
  public boolean action (Event evt, Object arg) {
    if(evt.target.equals(send)) {
      l2.setText("");
      // Check for errors in data:
      if(name.getText().trim()
         .indexOf(' ') == -1) {
        l.setText(
          "Please give first and last name");
        l2.setText("");
        return true;
      }
      str = email.getText().trim();
      if(str.indexOf(' ') != -1) {
        l.setText(
          "Spaces not allowed in email name");
        l2.setText("");
        return true;
      }
      if(str.indexOf(',') != -1) {
        l.setText(
          "Commas not allowed in email name");
        return true;
      }
      if(str.indexOf('@') == -1) {
        l.setText("Email name must include '@'");
        l2.setText("");
        return true;
      }
      if(str.indexOf('@') == 0) {
        l.setText(
          "Name must preceed '@' in email name");
        l2.setText("");
        return true;
      }
      String end = 
        str.substring(str.indexOf('@'));
      if(end.indexOf('.') == -1) {
        l.setText("Portion after '@' must " +
          "have an extension, such as '.com'");
        l2.setText("");
        return true;
      }
      // Build and encode the email data:
      String emailData = 
        "name=" + URLEncoder.encode(
          name.getText().trim()) +
        "&email=" + URLEncoder.encode(
          email.getText().trim().toLowerCase()) +
        "&submit=Submit";
      // Send the name using CGI's GET process:
      try {
        l.setText("Sending...");
        URL u = new URL(
          getDocumentBase(), "cgi-bin/" +
          CGIProgram + "?" + emailData);
        l.setText("Sent: " + email.getText());
        send.setLabel("Re-send");
        l2.setText(
          "Waiting for reply " + ++vcount);
        DataInputStream server =
          new DataInputStream(u.openStream());
        String line;
        while((line = server.readLine()) != null)
          l2.setText(line);
      } catch(MalformedURLException e) {
        l.setText("Bad URl");
      } catch(IOException e) {
        l.setText("IO Exception");
      } 
    }
    else return super.action(evt, arg);
    return true;
  }
} ///:~

CGI 程序(不久即可看到)的名字是 Listmgr2.exe。许多 Web 服务器都在 Unix 机器上运行(Linux 也越来越受到青睐)。根据传统,它们一般不为自己的可执行程序采用.exe 扩展名。但在 Unix 操作系统中,可以把自己的程序称呼为自己希望的任何东西。若使用的是.exe 扩展名,程序毋需任何修改即可通过 Unix 和 Win32 的运行测试。

和往常一样,程序片设置了自己的用户界面(这次是两个输入字段,不是一个)。唯一显著的区别是在 action() 方法内产生的。该方法的作用是对按钮按下事件进行控制。名字检查过以后,大家会发现下述代码行:

      String emailData = 
        "name=" + URLEncoder.encode(
          name.getText().trim()) +
        "&email=" + URLEncoder.encode(
          email.getText().trim().toLowerCase()) +
        "&submit=Submit";
      // Send the name using CGI's GET process:
      try {
        l.setText("Sending...");
        URL u = new URL(
          getDocumentBase(), "cgi-bin/" +
          CGIProgram + "?" + emailData);
        l.setText("Sent: " + email.getText());
        send.setLabel("Re-send");
        l2.setText(
          "Waiting for reply " + ++vcount);
        DataInputStream server =
          new DataInputStream(u.openStream());
        String line;
        while((line = server.readLine()) != null)
          l2.setText(line);
        // ...

name 和 email 数据都是它们对应的文字框里提取出来,而且两端多余的空格都用 trim() 剔去了。为了进入列表,email 名字被强制换成小写形式,以便能够准确地对比(防止基于大小写形式的错误判断)。来自每个字段的数据都编码为 URL 形式,随后采用与 HTML 页中一样的方式汇编 GET 字串(这样一来,我们可将 Java 程序片与现有的任何 CGI 程序结合使用,以满足常规的 HTML GET 请求)。

到这时,一些 Java 的魔力已经开始发挥作用了:如果想同任何 URL 连接,只需创建一个 URL 对象,并将地址传递给构建器即可。构建器会负责建立同服务器的连接(对 Web 服务器来说,所有连接行动都是根据作为 URL 使用的字串来判断的)。就目前这种情况来说,URL 指向的是当前 Web 站点的 cgi-bin 目录(当前 Web 站点的基础地址是用 getDocumentBase() 设定的)。一旦 Web 服务器在 URL 中看到了一个“cgi-bin”,会接着希望在它后面跟随了 cgi-bin 目录内的某个程序的名字,那是我们要运行的目标程序。程序名后面是一个问号以及 CGI 程序会在 QUERY_STRING 环境变量中查找的一个参数字串(马上就要学到)。

我们发出任何形式的请求后,一般都会得到一个回应的 HTML 页。但若使用 Java 的 URL 对象,我们可以拦截自 CGI 程序传回的任何东西,只需从 URL 对象里取得一个 InputStream(输入数据流)即可。这是用 URL 对象的 openStream() 方法实现,它要封装到一个 DataInputStream 里。随后就可以读取数据行,若 readLine() 返回一个 null(空值),就表明 CGI 程序已结束了它的输出。

我们即将看到的 CGI 程序返回的仅仅是一行,它是用于标志成功与否(以及失败的具体原因)的一个字串。这一行会被捕获并置放第二个 Label 字段里,使用户看到具体发生了什么事情。

1. 从程序片里显示一个 Web 页

程序亦可将 CGI 程序的结果作为一个 Web 页显示出来,就象它们在普通 HTML 模式中运行那样。可用下述代码做到这一点:

getAppletContext().showDocument(u);

其中,u 代表 URL 对象。这是将我们重新定向于另一个 Web 页的一个简单例子。那个页凑巧是一个 CGI 程序的输出,但可以非常方便地进入一个原始的 HTML 页,所以可以构建这个程序片,令其产生一个由密码保护的网关,通过它进入自己 Web 站点的特殊部分:

//: ShowHTML.java
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;

public class ShowHTML extends Applet {
  static final String CGIProgram = "MyCGIProgram";
  Button send = new Button("Go");
  Label l = new Label();
  public void init() {
    add(send);
    add(l);
  }
  public boolean action (Event evt, Object arg) {
    if(evt.target.equals(send)) {
      try {
        // This could be an HTML page instead of
        // a CGI program. Notice that this CGI 
        // program doesn't use arguments, but 
        // you can add them in the usual way.
        URL u = new URL(
          getDocumentBase(), 
          "cgi-bin/" + CGIProgram);
        // Display the output of the URL using
        // the Web browser, as an ordinary page:
        getAppletContext().showDocument(u);
      } catch(Exception e) {
        l.setText(e.toString());
      } 
    }
    else return super.action(evt, arg);
    return true;
  }
} ///:~

URL 类的最大的特点就是有效地保护了我们的安全。可以同一个 Web 服务器建立连接,毋需知道幕后的任何东西。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文