1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
15.5 一个Web应用.md 49 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

15.5 Создание веб-приложения

Давайте рассмотрим, как создать приложение, которое будет работать в реальной среде веб-технологий, полностью используя преимущества Java. Эта программа состоит из двух частей: одна часть — это Java-программа, работающая на веб-сервере, а другая — "кусочек программы" или "маленькая программа" (applet), который загружается в браузер пользователя (то есть "клиента"). Этот applet собирает информацию от пользователя и отправляет её обратно на сервер, где работает основная программа. Основная задача этого приложения очень проста: applet запрашивает электронную почту пользователя, проверяет её корректность (не содержит пробелов и имеет символ @) и передаёт её на сервер. Программа на сервере получает эти данные, проверяет файл с адресами электронной почты и сообщает клиенту, если адрес уже существует. В противном случае новый адрес добавляется в список.Если решить эту задачу традиционным способом, нам потребуется создать HTML-страницу со текстовым полем и кнопкой "Отправить" (Submit). Пользователи могут вводить любую информацию в текстовое поле и отправлять её на сервер без каких-либо проверок на стороне клиента. При отправке данных страница также должна сообщить серверу, что делать с этими данными — вызвать программу общего веб-интерфейса (CGI) и выполнить её немедленно после получения данных. Обычно такие CGI-программы пишутся на Perl или C (иногда на C++, но требуют поддержки сервера), и они должны контролировать все возможные ситуации. Программа сначала проверяет данные, чтобы убедиться, что они имеют правильный формат. Если формат неверный, CGI-программа должна создать HTML-страницу с описанием проблемы и отправить её обратно пользователю через сервер. Пользователь видит ошибку и повторяет попытку до тех пор, пока данные не будут приняты. Если данные верны, CGI-программа открывает файл с адресами электронной почты, добавляет новый адрес или указывает, что этот адрес уже существует. Независимо от того, был ли добавлен новый адрес или нет, CGI-программе требуется правильно оформить HTML-страницу для ответа пользователю. Как Java-разработчику, вышеописанный подход к решению проблемы кажется очень громоздким. Естественно, мы хотели бы выполнять все операции на Java.В первую очередь, мы будем использовать JavaScript для клиента, чтобы проводить проверку валидности данных, что позволит избежать передачи данных между сервером и клиентом, тем самым экономя время и полосу пропускной способности, а также снижая нагрузку на сервер за счёт минимизации необходимости создания HTML-страниц.Затем мы перестанем использовать Perl CGI-скрипты и заменим их запущенным на сервере Java-приложением. На самом деле, здесь мы полностью отказываемся от использования Web-сервера, оставляя лишь необходимость установки соединения между Java-скриптами клиента и запущенным на сервере Java-приложением. Как вы скоро убедитесь сами, несмотря на то, что всё кажется очень простым, существуют некоторые непредвиденные проблемы, делающие ситуацию немного сложнее. Лучше всего писать апплеты на Java 1.1, но это часто невозможно. На момент написания этой книги браузеры с поддержкой Java 1.1 были ещё достаточно редкими, а даже если они становятся популярными, следует помнить о пользователях, которые медленно обновляют свои системы. Поэтому с точки зрения безопасности лучше всего апплеты писать только на Java 1.0. В связи с этим мы не можем использовать JAR-файлы для объединения (.class) файлов апплета. Таким образом, нам следует стремиться минимизировать количество используемых .class файлов для уменьшения времени загрузки.

Итак, давайте рассмотрим веб-сервер, который я использовал при создании этого демонстрационного примера. Он действительно поддерживает Java, но только версию 1.0! Это значит, что серверное приложение также должно быть написано на Java 1.0.

15.5.1 Серверное приложениеТеперь обратимся к вопросу серверного приложения (или программы), которое я называю NameCollector (собиратель имен). Предположим, что несколько пользователей одновременно пытаются отправить свои адреса электронной почты. Какова будет ситуация? Если NameCollector использует TCP/IP сокеты, ему потребуется применение многопоточной модели, которую мы рассматривали ранее, чтобы обеспечить параллельное обслуживание нескольких клиентов. Однако все эти потоки будут пытаться записывать данные в один и тот же файл, содержащий все адреса электронной почты. Это требует установки механизма блокировки, чтобы гарантировать, что несколько потоков не будут одновременно обращаться к этому файлу. "Сигнализатор" может здесь помочь достичь цели, хотя возможно есть более простой способ.Если мы будем использовать datagram, нам не потребуется многопоточность. Одним datagram можно "слушать" входящие datagram. Как только будет замечен входящий datagram, программа будет обрабатывать его и отвечать datagram'ом обратно тому отправителю, который запросил информацию. Если datagram потерян по пути, пользователь заметит отсутствие ответа datagram и сможет повторно отправить запрос. При получении серверной программой данных, содержащих электронные адреса почты, она должна извлекать эти адреса и проверять локальные данные, чтобы узнать, содержится ли уже такой адрес (если нет, то добавляется). Таким образом, мы сталкиваемся с новой проблемой. Java 1.0 кажется недостаточно мощной для удобной работы с файлами, содержащими электронные адреса почты (в отличие от Java 1.1). Однако эту задачу легко решить с помощью C. Поэтому здесь есть возможность изучить самый простой способ соединения неприспособленной программы на Java с внешней программой. Программа использует объект Runtime, который включает метод exec(), запускающий отдельную программу на машине и возвращающий объект типа Process. Можно получить объект OutputStream, связанный с входящими данными этой отдельной программы; а также объект InputStream, связанный с выходящими данными.Всё, что требуется сделать, это написать программу на любом языке, которая может принимать входные данные через стандартный ввод и выводить результаты через стандартный вывод. Если некоторые задачи нельзя решить быстро и просто с использованием Java (или если вы хотите использовать существующий код вместо его переписывания), можно рассмотреть этот подход. Также можно использовать "native methods" Java, но это требует большего мастерства, как указано в приложении A. Программа на CЭто неприложение на Java было написано на C, так как Java не является оптимальным выбором для CGI-программ; по крайней мере, время запуска не может удовлетворить требования. Его задачей является управление списком электронных адресов (E-mail). Стандартный ввод принимает один E-mail адрес, программа проверяет этот адрес среди записей списка, чтобы определить его наличие. Если адрес отсутствует, он добавляется в список, и сообщается об успешной операции. Однако, если адрес уже присутствует в списке, это должно быть указано, чтобы избежать повторного добавления. Вам не следует беспокоиться, что вы полностью не понимаете следующий код. Это просто демонстрационная программа, которая показывает вам, как можно написать программу на другом языке и вызвать её из Java. Здесь конкретный язык не важен, главное — чтение данных с стандартного ввода и вывод данных на стандартный вывод.

//: Listmgr.c
// Используется NameCollector.java для управления
// файлом списка электронной почты на сервере
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BSIZE 250

int alreadyInList(FILE* list, char* name) {
  char lbuf[BSIZE];
  // Переходим в начало списка:
  fseek(list, 0, SEEK_SET);
  // Читаем каждую строку из списка:
  while (fgets(lbuf, BSIZE, list)) {
    // Удаляем новую строку:
    char * newline = strchr(lbuf, '\n');
    if (newline != 0)
      *newline = '\0';
    if (strcmp(lbuf, name) == 0)
      return 1;
  }
  return 0;
}
```int main() {
  char buf[BSIZE];
  FILE* list = fopen("emlist.txt", "a+t");
  if(list == 0) {
    perror("не удалось открыть emlist.txt");
    exit(1);
  }
  while(1) {
    gets(buf); /* From standard input */
    if(alreadyInList(list, buf)) {
      printf("Уже есть в списке: %s", buf);
      fflush(stdout);
    } else {
      fseek(list, 0, SEEK_END);
      fprintf(list, "%s\n", buf);
      fflush(list);
      printf("%s добавлен в список", buf);
      fflush(stdout);
    }
  }
} ///:~Программа предполагает, что компилятор C поддерживает однобуквенное комментирование (`//`). Многие компиляторы поддерживают это, а также можно использовать компилятор C++ для компиляции этой программы. Если ваш компилятор этого не поддерживает, просто удалите эти комментарии. Первый функциональный метод в файле проверяет, содержится ли имя, переданное ему как второй аргумент (указатель на `char`), уже в этом файле. Здесь мы передаем файл как указатель типа `FILE`, который указывает на открытый файл (файл был открыт в функции `main()`). Функция `fseek()` перемещает позицию в файле; здесь она используется для перехода к началу файла. Функция `fgets()` считывает строку из файла `list` и помещает её в буфер `lbuf` — не более указанной длины буфера `BSIZE`. Все это происходит внутри цикла `while`, поэтому каждая строка в файле будет прочтена. Далее, с помощью функции `strchr()` находится символ новой строки, чтобы удалить его. В конце сравниваются имя, переданное функции, и текущая строка в файле с помощью функции `strcmp()`. Если найдено совпадение, то `strcmp()` вернет 0. После этого функция завершается и возвращает значение 1, что указывает на наличие имени в файле (отмечено, что при нахождении совпадения функция немедленно завершается, не тратя время на дальнейший просмотр списка). Если после полного просмотра списка совпадений не найдено, функция возвращает 0.В `main()` мы используем `fopen()` для открытия файла. Первый аргумент — это имя файла, второй — способ открытия файла; `a+` означает «добавление» и «открытие» (или «создание», если файл ещё не существует), чтобы обновить до конца файла. Функция `fopen()` возвращает указатель типа `FILE`; значение 0 указывает на неудачу операции открытия. В этом случае следует использовать `perror()` для вывода сообщения об ошибке и `exit()` для завершения работы программы.Если файл успешно открыт, программа переходит в бесконечный цикл. Вызов функции `gets(buf)` извлекает строку из стандартного ввода (помните, что стандартный ввод связан с Java-программой) и помещает её в буфер `buf`. Содержимое буфера затем передаётся простым вызовом функции `alreadyInList()`. Если содержимое уже присутствует в списке, то `printf()` отправляет это сообщение в стандартный вывод (Java-программа следит за ним). `fflush()` используется для очистки выходного буфера.

Если имя не находится в списке, то используется `fseek()` для перемещения в конец списка, и `fprintf()` для записи имени в конец списка. Затем `printf()` сообщает, что имя было успешно добавлено в список (также требуется очистка стандартного вывода), бесконечный цикл продолжается, ожидая нового имени.

Помните, что обычно невозможно компилировать этот программный код на вашем компьютере и затем загружать его на сервер Web, так как машина может использовать другой тип процессора и операционной системы. Например, мой веб-сервер оснащен процессором Intel, но работает под управлением Linux, поэтому необходимо сначала скачать исходный код, а затем использовать команды удаленного доступа (через `telnet`) для запуска компилятора C, который встроен в систему Linux, чтобы скомпилировать программу на сервере.(2) Java-программа

Эта программа запускает вышеупомянутую C-программу и создаёт необходимые соединения для взаимодействия с ней. Затем она создает сокет данных, который используется для "наблюдения" или "прослушивания" пакетов данных от фрагмента программы.

```java
//: NameCollector.java
// Извлекает электронные адреса из пакетов данных и хранит их в файле,
// используя Java 1.02.
import java.net.*;
import java.io.*;
import java.util.*;
публичный класс NameCollector {
  константное целое COLLECTOR_PORT = 8080;
  константное целое BUFFER_SIZE = 1000;
  байт[] buf = новый байт[BUFFER_SIZE];
  DatagramPacket dp =
    новый DatagramPacket(buf, buf.длина);
  // Может прослушивать и отправлять данные через одно сокетное соединение:
  DatagramSocket socket;
  Процесс listmgr;
  PrintStream nameList;
  DataInputStream addResult;
  публичный NameCollector() {
    попробовать {
      listmgr =
        Runtime.getRuntime().exec("listmgr.exe");
      nameList = новый PrintStream(
        новый BufferedOutputStream(
          listmgr.getOutputStream()));
      addResult = новый DataInputStream(
        новый BufferedInputStream(
          listmgr.getInputStream()));
``````markdown
    } catch(IOException e) {
      System.err.println(
        "Не удалось запустить listmgr.exe");
      System.exit(1);
    }
    try {
      socket =
        new DatagramSocket(COLLECTOR_PORT);
      System.out.println(
        "Сервер NameCollector запущен");
      while(true) {
        // Ожидание получения datagram:
        socket.receive(dp);
        String received = new String(dp.getData(), 
            0, 0, dp.getLength());
        // Отправка в стандартный ввод listmgr.exe:
        nameList.println(received.trim());
        nameList.flush();
        byte[] resultBuffer = new byte[BUFFER_SIZE];
        int byteCount =
          addResult.read(resultBuffer);
        if(byteCount != -1) {
          String result =
            new String(resultBuffer, 0).trim();
          // Извлечение адреса и порта из полученного datagram для отправки ответа:
          InetAddress senderAddress =
            dp.getAddress();
          int senderPort = dp.getPort();
          byte[] echoBuffer = new byte[BUFFER_SIZE];
          result.getBytes(
            0, byteCount, echoBuffer, 0);
          DatagramPacket echo =
            new DatagramPacket(
              echoBuffer, echoBuffer.length,
              senderAddress, senderPort);
          socket.send(echo);
        }
        else
          System.out.println(
            "Непредвиденное отсутствие результата от listmgr.exe");
      }
    } catch(SocketException e) {
      System.err.println("Не удалось открыть сокет");
      System.exit(1);
    } catch(IOException e) {
      System.err.println("Ошибка связи");
      e.printStackTrace();
    }
  }
  public static void main(String[] args) {
    new NameCollector();
  }
} ///:~
````NameCollector` класс начинается с хорошо известной части: выбирается порт, создается datagram пакет, а затем создается ссылка на `DatagramSocket`. Далее следуют три метода, отвечающие за взаимодействие с C программой: объект `Process`, который возвращается после запуска C программы Java программой, создаёт потоки `InputStream` и `OutputStream`, представляющие стандартный вывод и стандартный ввод C программы соответственно. Как и в случае с Java IO, эти потоки требуют "обёртки", поэтому мы в конечном итоге имеем `PrintStream` и `DataInputStream`.
Все работы этого программы происходят внутри конструктора. Для запуска C-программы требуется получить текущий объект `Runtime`. Мы используем его для вызова метода `exec()`, который возвращает объект типа `Process`. В этом объекте процесса можно видеть, как с помощью простого вызова создаются потоки данных: `getOutputStream()` и `getInputStream()`. С этого момента все, что нам остаётся сделать — это передать данные в поток данных `nameList` и получить результаты из `addResult`.

Как обычно, мы связываем `DatagramSocket` с одним и тем же портом. В бесконечном цикле `while` программа вызывает метод `receive()` — если пакет данных ещё не пришёл, то этот метод будет находиться в состоянии "блокировки". После получения пакета данные извлекаются в строку `String rcvd`. Сначала мы удаляем пробелы с обоих концов строки (метод `trim`) и отправляем её в C-программу. Это выглядит следующим образом:```java
nameList.println(rcvd.trim());

Этот способ кодирования возможен благодаря тому, что метод exec() Java позволяет нам обращаться к любому исполняемому модулю, который может читать из стандартного ввода и записывать в стандартный вывод. Также существуют другие способы взаимодействия с неприсоединенным кодом Java, которые будут рассмотрены в Приложении А.

Получение результатов от C-программы несколько сложнее. Нам нужно вызвать метод read() и предоставить буфер для хранения результатов. Возвращаемое значение метода read() представляет собой количество байтов, полученных от C-программы. Если это значение равно -1, значит произошла ошибка где-то. В противном случае мы преобразуем resultBuf (буфер результата) в строку и также очищаем лишние пробелы. Затем эта строка помещается в DatagramPacket и отправляется обратно тому же адресу, с которого был получен запрос. Обратите внимание, что адрес отправителя является частью DatagramPacket, который мы получили.

Не забывайте, что хотя C-программа должна быть скомпилирована на сервере Web, Java-программа может быть скомпилирована на любом компьютере. Это возможно потому, что независимо от того, какой аппаратный платформы и операционной системы используется, компиляция даёт одинаковый байткод. Именно так работает "переносимость" Java.## 15.5.2 Часть программы NameSender

Как было отмечено ранее, апплет должен быть написан на Java 1.0 для обеспечения совместимости с большинством браузеров. Именно поэтому количество создаваемых нами классов должно быть минимальным. Поэтому мы не будем использовать заранее спроектированный класс Dgram, а вместо этого встроим все операции с datagram в код апплета. Кроме того, апплет должен содержать поток, который будет наблюдать за ответами сервера, вместо реализации интерфейса Runnable. Это решение снижает читабельность кода, но позволяет создать апплет, состоящий всего из одного класса (и одного запроса к серверу):

//: NameSender.java
// Программное обеспечение, отправляющее адрес электронной почты
// в виде дейтаграммы с использованием Java 1.02.
import java.awt.*;
import java.applet.*;
import java.net.*;
import java.io.*;  

Класс NameSender, расширяющий Applet и реализующий Runnable

Описание

Класс NameSender представляет собой апплет, который позволяет отправлять адрес электронной почты в рассылку. Он использует сетевые пакеты для передачи данных.

Атрибуты- pl: поток типа Thread.

  • send: кнопка с надписью "Добавьте адрес электронной почты в рассылку".
  • t: поле ввода текста с надписью "Введите ваш адрес электронной почты здесь" и шириной 40 символов.
  • str: строковое значение.
  • l, l2: метки.
  • s: объект DatagramSocket.
  • hostAddress: адрес хоста типа InetAddress.
  • buf: байтовый массив размером NameCollector.BUFFER_SIZE.
  • dp: объект DatagramPacket, использующий массив buf.
  • vcount: счетчик значений.#### Методы
init()

Инициализирует компоненты апплета и устанавливает макет.

public void init() {
    setLayout(new BorderLayout());
    Panel p = new Panel();
    p.setLayout(new GridLayout(2, 1));
    p.add(t);
    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);

    try {
        // Автоматическое назначение номера порта:
        s = new DatagramSocket();
        hostAddress = InetAddress.getByName(getCodeBase().getHost());
    } catch (UnknownHostException e) {
        l.setText("Не удалось найти хост");
    } catch (SocketException e) {
        l.setText("Невозможно открыть сокет");
    }

    l.setText("Готово к отправке вашего адреса электронной почты");
}
action(Event evt, Object arg)

Обрабатывает события, связанные с нажатием кнопки.

public boolean action(Event evt, Object arg) {
    if (evt.target.equals(send)) {
        if (pl != null) {
            // pl.stop(); Устарело в Java 1.2
            Thread remove = pl;
            pl = null;
            remove.interrupt();
        }
        l2.setText("");

        // Проверка ошибок в имени электронной почты:
        str = t.getText().toLowerCase().trim();

        if (str.indexOf(' ') != -1) {
            l.setText("Пробелы недопустимы в имени");
            return true;
        }

        if (str.indexOf(',') != -1) {
            l.setText("Запятые недопустимы в имени");
            return true;
        }

        if (str.indexOf('@') == -1) {
            l.setText("Имя должно содержать '@'");
            l2.setText("");
            return true;
        }

        if (str.indexOf('@') == 0) {
            l.setText("Имя должно предшествовать '@'");
            l2.setText("");
            return true;
        }

        String end = str.substring(str.indexOf('@'));
}
```        if (end.indexOf('.') == -1) {
            l.setText("Часть после '@' должна иметь расширение, например '.com'");
            l2.setText("");
            return true;
        }

        // Все хорошо, поэтому отправляем имя. Получаем
      // новый буфер, поэтому он сброшен в ноль. По какой-то причине вы должны использовать фиксированную размерность вместо динамического расчета размера:
      byte[] sbuf = 
        new byte[NameCollector.BUFFER_SIZE];
      str.getBytes(0, str.length(), sbuf, 0);
      DatagramPacket toSend = 
        new DatagramPacket(
          sbuf, 100, hostAddress,
          NameCollector.COLLECTOR_PORT);
      try {
        s.send(toSend);
      } catch (Exception e) {
        l.setText("Не удалось отправить datagram");
        return true;
      }
      l.setText("Отправлено: " + str);
      send.setLabel("Переслать");
      pl = new Thread(this);
      pl.start();
      l2.setText(
        "Ожидание верификации " + ++vcount);
    }
    else return super.action(evt, arg);
    return true;
  }
  // Часть потока апплета наблюдает за ответом от сервера:
  public void run() {
    try {
      s.receive(dp);
    } catch (Exception e) {
      l2.setText("Не удалось получить datagram");
      return;
    }
    l2.setText(new String(dp.getData(),
      0, 0, dp.getLength()));
  }
} ///:~

Примечание: В данном примере используется IT-терминология, адаптированная для русского языка, чтобы обеспечить понятность и соответствие стандартам IT-документации. Интерфейс пользователя (UI) программы очень прост. Он включает TextField (текстовое поле) для ввода адреса электронной почты; кнопку (Button) для отправки адреса на сервер; а также два Label (этикетки) для отображения информации о состоянии.На данный момент можно заметить, что DatagramSocket, InetAddress, буферы и DatagramPacket являются сложными частями сетевого соединения. В конце концов, метод run() реализует многопоточность, позволяющую программному компоненту "слушать" ответы от сервера.

Метод init() использует знакомый инструмент для размещения графического интерфейса пользователя (GUI), а затем создает DatagramSocket, который будет использоваться как для приема, так и для передачи данных.

Метод action() отвечает за мониторинг нажатия кнопки "Отправить" (send). Учитывайте, что мы ограничены Java 1.0, поэтому использование более гибких внутренних классов невозможно. При нажатии кнопки первым делом проверяется поток pl. Если он не равен null, это указывает на наличие активного потока. Когда сообщение отправляется в первый раз, запускается новый поток для мониторинга ответов от сервера. Таким образом, если есть активный поток, значит, это не первое сообщение, отправленное пользователем. Ссылка pl устанавливается в null, а старый монитор прекращает свою работу (что является наиболее подходящим решением, поскольку stop() был "запрещен" в Java 1.2, как было объяснено ранее).

Независимо от того, была ли нажата кнопка впервые или нет, текст в I2 очищается.Следующий набор операторов проверяет, является ли имя электронной почты допустимым. Метод String.indexOf() используется для поиска недопустимых символов. Если такой символ найден, информация о нём предоставляется пользователю. Обратите внимание, что все эти действия выполняются без использования сетевых соединений, что обеспечивает высокую скорость выполнения и не влияет на пропускную способность и производительность сервера.При успешной проверке имени, оно упаковывается в пакет данных и отправляется на хост с адресом и номером порта, аналогично примеру с пакетами данных выше. Первый лейбл меняет своё состояние, указывая на успешную отправку. Также текст на кнопке изменяется на "Переотправить" (переотправить). Запускается поток, второй лейбл сообщает, что программа ждёт ответа от сервера. Метод run() потока использует DatagramSocket, содержащийся в NameSender, чтобы принимать данные (receive()). В случае отсутствия данных от сервера метод receive() будет находиться в состоянии "блокировки" или "паузы". Полученные пакеты помещаются в DatagramPacket dp объекта NameSender. Данные извлекаются из пакета и записываются во второй лейбл NameSender. После этого выполнение потока прекращается, и он становится "мертвым" потоком. Если за некоторое время ответ от сервера не получен, пользователь может стать нетерпеливым и снова нажать кнопку. Это приведёт к прерыванию текущего потока (после отправки данных создаётся новый). Поскольку используется один поток для мониторинга ответов, пользователю остаётся возможность свободно использовать UI во время мониторинга.

(1) Веб-страница

Конечно, апплет должен быть размещён на одной веб-странице. Ниже приведён полный исходный код страницы; немного изучив его, можно заметить, что он автоматически собирает адрес электронной почты с моего рассылочного списка (Mailing List).```html

<TITLE>Добавьте себя в рассылочный список Bruce Eckel по Java</TITLE>

Добавьте себя в рассылочный список Bruce Eckel по Java

Апплет на этой странице автоматически добавляет ваш адрес электронной почты в рассылочный список, поэтому вы будете получать информацию о новых версиях книги "Thinking in Java", а также уведомления о выходе книги в печати, информация о предстоящих семинарах по Java и уведомления о мультимедийном CD "Hands-on Java Seminar". Введите свой адрес электронной почты и нажмите кнопку, чтобы автоматически добавиться в этот рассылочный список.

Если после нескольких попыток вы не получаете подтверждение, это значит, что приложение Java на сервере имеет проблемы. В этом случае вы можете добавиться в список, отправив письмо на адрес Bruce@EckelObjects.com ```

Использование метки апплет (<applet>) очень простое и ничем не отличается от того, что было показано в главе 13.

15.5.3 Проблемы, требующие вниманияМетод, который мы использовали ранее, казался идеальным. Без использования CGI-скриптов, время запуска CGI-программы на сервере не увеличивается. Этот подход позволяет получать быстрый ответ. К тому же, как только Java 1.1 станет широко распространённой, серверная часть может быть полностью реализована на Java (хотя связываться с неким не-Java программой через стандартные входные/выходные данные тоже достаточно просто).Однако следует обратить внимание на некоторые проблемы. Одна из них особенно легко игнорируется: поскольку Java-приложение работает постоянно на сервере и большую часть времени находится в режиме ожидания метода Datagram.receive(), это создает дополнительную нагрузку на процессор. По крайней мере, я столкнулся с этой проблемой на своём сервере. С другой стороны, на этом сервере нет других активных операций. И если мы будем использовать более мощный сервер, то запустить программу с помощью команды nice (программа Unix, которая предотвращает использование процессами слишком много CPU) или аналогичной команды поможет решить эту проблему. В многих случаях важно обращать внимание на такие приложения — заблокированный receive() способен вызвать перегрузку процессора. Второй вопрос относится к использованию брандмауэра. Брандмауэр можно рассматривать как стену между локальной сетью и Интернетом (на самом деле это специализированное оборудование или программное обеспечение для брандмауэра). Он наблюдает за всеми входящими и исходящими соединениями с Интернетом и гарантирует, что они не нарушают заранее установленные правила.Брандмауэр выглядит несколько консервативно и требует строгое следование всем правилам. Если правило не выполнено, он немедленно отклоняет запрос. Например, если мы находимся в сети, расположенной за брандмауэром, и начинаем использовать веб-браузер для подключения к Интернету, брандмауэр требует, чтобы все передачи осуществлялись через допустимый HTTP-порт сервера, который обычно 80. Теперь представьте, что приходит Java-код NameSender, который пытается отправить данные на порт 8080, чтобы пройти мимо "защищенного" диапазона портов 0-1024. Брандмауэр автоматически считает его худшим случаем — использование вирусов или незаконной проверки порта — и просто запрещает продолжение передачи.Если наш клиент использует первичное подключение к интернету (например, через типичного провайдера услуг доступа в интернет), проблема с брандмауэром не возникает. Однако возможно, что некоторые важные клиенты скрываются за брандмауэрами, и поэтому они не могут использовать наши программы.

После всего того, что мы узнали о Java, это действительно печально, так как кажется, что придётся отказаться от использования Java на серверах и учиться писать скрипты на C или Perl. Но не стоит отчаиваться.

Отличное решение было предложено компанией Sun Microsystems. Если всё будет работать согласно плану, веб-серверы будут оснащены "малыми службами" или "служебными апплетами" (Servlets). Они будут принимать запросы от клиентов (через разрешённый порт 80 брандмауэра) и запускать малые службы вместо CGI-программ. По замыслу компании Sun, эти малые службы будут написаны на Java и смогут выполнять свои задачи только на сервере. Серверы, запускающие такие маленькие программы, будут автоматически запускать их для обработки запросов от клиентов. Это значит, что все наши программы могут быть написаны на Java (100% чистый кофе). Это явно очень привлекательная идея: после того как ты привык к Java, тебе больше не нужно будет учиться новому языку для выполнения задач на сервере.Однако, поскольку управление запросами происходит только на стороне сервера, API для малых служб не предоставляет графического интерфейса пользователя. Это прекрасно подходит для NameCollector.java, которая и так не нуждается в графическом интерфейсе. При написании данной книги на java.sun.com уже был доступен очень простой сервер для сервлетов. Sun поощрял других разработчиков веб-серверов к добавлению поддержки сервлетов в свои продукты.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master