AWT клиент для веб-приложения. Часть 1
(Николай Зайкин)
Я смекнул, что у меня есть хороший мозг, что работает он
великолепно и что следует этим воспользоваться.
Владимир Набоков, "Лолита"
В этой небольшой статье вы найдете пример написания простого приложения клиент-сервер,
клиентом служит CGI-скрипт на Perl, клиентом является графическое (AWT) Java приложение.
Статья содержит информацию по следующим вопросам:
- Основы CGI программирования.
- Написание графического интерфейса (AWT).
- Описание модели делегирования событий (AWT Events).
- Работа Java приложения через HTTP прокси-сервер.
- Сохранение и загрузка пользовательских свойств.
- Чтение потока данных, содержащего кириллические символы.
1. Структура приложения.
Приложение работает как
on-line словарь
(англо-русский и русско-английский), оно состоит из клиентской и серверной частей. Сервер
- любой HTTP сервер, умеющий запускать CGI скрипты (Apache, IIS, etc). Скрипт, работающий
на сервере, написан на Perl. Во-первых, это улучшает переносимость на другую платформу,
во-вторых, этот язык широко испрользуется для серверных CGI приложений, и в-третьих, Perl
- язык для обработки текстовых данных (чем он и занимается по сути в нашем случае).
Скрипт универсален, он может работать как с обычным HTTP браузером (MSIE, NC), так и с
клиентом, не поддерживающим HTML (в нашем случае - это Java Application). Клиент - (как
уже упоминалось выше) - графическое Java приложение, умеющее работать через HTTP
прокси.
2. Серверная часть.
Как уже упоминалось выше, серверная часть состоит из CGI скрипта и нескольких файлов
словарей в plain-text
формате. Работа скрипта заключается в следующем:
- Прием HTTP запроса (http request) от клиента.
- Поиск перевода слова заданного в заголовке HTTP запроса по всем словарям.
- Выдача HTTP ответа (http response) в формате, запрошенном клиентом.
Рассмотрим кратко как вышесказанное выполняется в коде:
Используется стандартный модуль CGI.pm (хотя никто не мешает получать параметры, разбирая
переменную $ENV{'QUERY_STRING'}; ). Этот модуль являктся de-facto
стандартом для web-программистов, позволяет сократить время разработки приложения и
улучшить его защищенность. Мы создаем объект req (один на все CGI
приложение), посредством которого можем обрабатывать запрос и формировать ответ.
#!/usr/bin/perl -w
###################################################################
# dict.cgi
# author: Nikolay Zaikin (nikolay_zaikin@mail.ru)
# version: 0.0.2
# created: 24.04.2001
# modified: 24.04.2001
###################################################################
use CGI;
require 'dict.conf';
$req = new CGI;
Далее, мы получаем от клиента несколько параметров:
- word - слово для перевода;
- type - тип поиска (см. далее), задает алгоритм работы скрипта;
- app - тип клиента (HTML браузер или java application).
В случае, если какой-либо параметр не указан, ему присваивается значение по умолчанию
(для правильной работы скрипта).
my $word = $req->param('word'); # word for translating
my $type = $req->param('type');
my $app = $req->param('app'); # client application (web or java)
$word = ($word) ? $word : "sad";
$type = ($type) ? $type : "1";
$app = ($app) ? $app : "web"; # by default we use web client
Далее идет "самая главная" строка почти каждого CGI-скрипта, а именно,
указание клиенту "тип" отправляемого содержимого (Content-type). В ручном
исполнении это выглядит так:
print "Content-type: text/html\n\n";
В нашем, "продвинутом" исполнении это выглядит как:
print $req->header;
В зависимости от типа клиента, начинаем выводить ответ (хочу только напомнить, что для
сравнения числовых скаляров используется '==', а для сравнения
строковых скаляров используется 'eq'). И заодно засекаем время
старта работы скрипта.
if ($app eq "web") {
print <<EOD;
<HTML>
<HEAD>
</HEAD>
<BODY>
<FONT FACE="Helvetica, Verdana, Arial" SIZE="4">
EOD
$br = "<BR>";
$b1 = "<B>";
$b2 = "</B>";
}
my $start_time = time;
Открываем директорию со словарями (путь к директории хранится в файле
dict.conf) как обычный файл, читаем все имена файлов (словарей) в массив
dicts, отбрасывая имена каталогов в этой директории, а также имена двух
"специальных" каталогов, которые называются "." (указывает на текущий
каталог) и ".." (указывает на родительский каталог).
# open directory with dictionaries
opendir (DIR, $dict_dir) or die "can not open directory: $dict_dir : $!";
# read the directory, excluding folders and files with starting dots
@dicts = grep {!/^\./ && -f "$dict_dir/$_"} readdir (DIR);
# close directory with dictionaries
closedir DIR;
Ниже приведен непосредственно сам поиск перевода слова пр словарям. Подробно описывать
не буду, думаю, тут все очевидно. Хочу только привести несколько комментариев:
a. Словари достались мне в виде plain-text файлов, со следующей структурой:
<\n>
<слово 1><\n>
<перевод 1><\n>
<перевод 1><\n>
<\n>
<слово 2><\n>
<перевод 2><\n>
<перевод 2><\n>
..........
<\n>
<слово N><\n>
<перевод N><\n>
<перевод N><\n>
b. Я выбрал следующие алгоритмы поиска:
- type=1 Слово начинается с шаблона (для sad будут найдены
sad, sadness и т.д.);
- type=2 Слово строго совпадает с шаблоном (для sad будет найдено
только sad);
- type=3 Слово содержит в своем составе шаблон (для sad будут найдены
sad, ambassador, disadvantages и
т.д.).
my $i=0;
my $ooops=0;
my $oooops=0;
my $new_entry=1;
foreach $dict (@dicts) {
open (DICT, "$dict_dir/$dict")
or die "can not open file: $dict_dir/$dict :$!";
while (<DICT>) {
if ($_ eq "\n") {$ooops=0;$new_entry=1;} else {$new_entry=0;}
if ($ooops) {print "$_$br";}
if (($type eq "1") && (index($_, $word)==0) && ($oooops)) {
print "\n$br". ++$i." : $b1$_$b2$br";
$ooops=1;
} elsif (($type eq "2") && ($_ eq "$word\n") && ($oooops)) {
print "\n$br". ++$i." : $b1$_$b2$br";
$ooops=1;
} elsif (($type eq "3") && (index($_, $word)>=0) && ($oooops)) {
print "\n$br". ++$i." : $b1$_$b2$br";
$ooops=1;
}
$oooops=$new_entry;
}
}
Ну, и окончательно выводим время, затраченное скриптом на поиск переводов, и (при
необходимости) закрываем HTML тэги.
my $finish_time = time;
my $searching_time = $finish_time - $start_time;
if ($app eq "web")
{ print "<BR><FONT SIZE=\"2\"><I>"; }
print "\nsearching time = $searching_time sec";
if ($app eq "web")
{ print "</I></FONT><BR>\n";
print <<EOD;
</FONT>
</BODY>
</HTML>
EOD
}
На этом описание серверной части закончено. Теперь следует перейти к основной теме
этой статьи - описанию работы клиентской части приложения (Java Applcation).
TOC | Часть 2

|