Rambler's Top100IT • archiv

rus / eng | Логин | Комментарий к колонке | Печать | Почта | Клуб




Колонки


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 >




Справка | Условия Copyright © 1999 — 2008, IT • archiv.
В начало | Логин | Комментарий к колонке | Поиск | Почта