Для создания динамических эффектов при просмотре Web-страниц в модулях расширения клиентской части (активность на стороне клиента) используют ап-плеты, подключаемые программы, объекты ActiveX и сценарии.
Исполняемые программы являются первым поколением клиентских расширений. Для организации работы такой программы в Web-приложении необходимо ее предварительно установить и сконфигурировать обозреватель. Поэтому при
514
Часть IV. Базы данных и Интернет
использовании исполняемых программ очень трудно обеспечить совместимость Web-приложения с различными обозревателями. Кроме того, использование такой технологии нарушает принцип стандартности клиентского интерфейса.
Апплеты Java применяются для создания динамически формируемого интерфейса пользователя. Апплет представляет собой байтовый код, который интерпретируется виртуальной Java-машиной, входящей в состав обозревателя. Загрузка апплета производится при загрузке Web-документа. Принцип функционирования апплета делает возможным подключение классов Java, хранящихся на сервере. Код апплета может начать выполняться сразу после загрузки в компьютер клиента или активизироваться с помощью специальных команд.
Используя библиотеку классов Java, можно создавать мультимедийные страницы и организовывать распределенные процедуры обработки данных с использованием различных серверов и протоколов.
Апплет может быть специализирован для работы с внешними базами данных. С этой целью в Java включены наборы классов для поддержки графического пользовательского интерфейса и классы для доступа к БД.
Для включения дополнительного действия в Web-приложение достаточно включить тег апплета в Web-документ и поместить апплет-класс в библиотеку аппле-тов на сервере. При этом изменения в конфигурацию Web-сервера вносить не нужно.
Для взаимодействия апплета Java с внешним сервером баз данных разработан специализированный протокол JDBC (Java DataBase Connectivity — совместимость Java с базами данных), построенный на принципах интерфейса ODBC и применяется для стандартизации кода апплета Java при организации доступа к различным СУБД.
Архитектура Web-приложений, публикующих БД
Для публикации БД на Web-страницах в архитектуру приложений вводятся дополнительные уровни, включающие сервер БД, сервер приложений и источник БД.
При такой архитектуре Web-сервер передает запрос на генерацию Web-страниц своей программе-расширению, которая на основе информации БД формирует требуемый документ. Затем Web-сервер отсылает готовые страницы обратно обозревателю. Как мы знаем, для формирования динамических страниц используются различные средства и технологии: ASP и IDC/HTX-страницы, программы-расширения сервера на основе интерфейсов CGI и ISAPI.
При использовании ASP и IDC/HTX-страниц запрос на получение динамически формируемой Web-страницы передается специальным динамическим библиотекам, входящим в состав Web-сервера. Например, если в качестве Web-сервера используется Personal Web Server и публикация осуществляется средствами IDC/HTX, то применяется динамическая библиотека httpodbc.dll. Такие библио-
Глава 19. Web-приложения и интерфейсы
515
теки анализируют файл ASP или IDC и НТХ-файлы, которые используются в качестве шаблонов.
Напомним, что публикация БД на Web-страницах бывает статической и динамической. Программы-расширения Web-сервера, публикующие базы данных, включают в себя элементы, характерные для обычных приложений БД. При статической или динамической публикации должна использоваться архитектура приложений БД, дополненная характерными компонентами архитектуры Web-приложений. Рассмотрим подробнее архитектуру Web-приложений, использующих БД.
Двухуровневые Web-приложения
При двухуровневой архитектуре Web-приложений источник БД хранится на том же компьютере, где находится Web-сервер. Для доступа к источнику БД используются модули расширения. В простейшем случае в архитектуру Web-приложений добавляется источник БД.
Функционирование Web-приложения при такой архитектуре заключается в следующем. Обозреватель для начала работы с Web-приложением отсылает URL-адрес главной страницы приложения Web-серверу. Последний, обработав запрос URL, высылает требуемую страницу в формате HTML обратно обозревателю. Эта страница несет общую информацию о Web-приложении и позволяет пользователю выбрать нужную ему функцию из предоставляемых приложением. Далее возможны несколько вариантов работы Web-приложения.
Если пользователю нужна определенная информация из БД, то обозреватель по ссылке, находящейся в загруженной HTML-странице, формирует URL-запрос к модулю расширения сервера. Используемые при этом технологии различаются в зависимости от типа Web-сервера и других особенностей Web-приложения. Например, если на Web-узле установлен Web-сервер Microsoft Internet Information Server, то это может быть технология ASP- или IDC/HTX-страниц, интерфейсы CGI или ISAPI, а если установлен сервер Apache, то интерфейс CGI.
Если необходимо сформировать запрос URL с параметрами, то на уровне обозревателя могут использоваться сценарии JavaScript для проверки правильности ввода параметров запроса.
После того как пользователь выбрал ссылку, обозреватель отсылает URL Web-серверу. Для обработки запроса сервер вызывает требуемый модуль расширения и передает ему параметры URL. Модуль расширения сервера формирует SQL-запрос к БД.
Из модуля расширения сервера доступ к БД может осуществляться различными способами и на основе различных интерфейсов. Например, в случае использования технологии ASP-страниц применяются объектная модель ADO, объектный интерфейс OLE DB, интерфейс ODBC. Также возможен вариант непосредственного доступа к БД. Например, в случае модуля ISAPI, разработанного в среде Delphi, для доступа к БД может использоваться один посредник — драй-
516
Часть IV. Базы данных и Интернет
вер BDE (Borland DataBase Engine), входящий в состав программных средств модуля расширения сервера.
Недостатки рассмотренной двухуровневой архитектуры: повышенная нагрузка на Web-сервер, поскольку все действия по обработке URL-запросов, извлечению информации из БД и формированию HTML-страниц выполняются Web-сервером и модулями расширения Web-сервера; низкий уровень безопасности из-за невозможности обеспечить требуемый уровень защиты информации в БД. Для преодоления указанных недостатков применяются Web-приложения с большим числом уровней.
Трехуровневые Web-приложения
При включении в Web-приложение промежуточного уровня, основанного на технологии "клиент-сервер", его архитектура расширяется до трехуровневой. При такой архитектуре клиентский уровень занимает обозреватель, на уровне сервера находится сервер БД, а на промежуточном уровне размещаются Web-сервер и модули расширения сервера. Модуль расширения сервера выступает преобразователем протоколов между клиент-серверным приложением БД и Web-сервером (рис. 19.4).
Для получения данных модуль расширения Web-сервера формирует и отсылает SQL-запрос удаленному серверу БД. На компьютере, где установлен удаленный |
Введение уровня Web-сервера в клиент-серверные приложения БД расширяет возможность их применения как межплатформенного приложения. Принципы взаимосвязи обозревателя и Web-сервера остаются те же, что и в предыдущей архитектуре. Отличия этой архитектуры заключаются в организации взаимодействия модуля расширения сервера и источника БД.
Глава 19. Web-приложения и интерфейсы
517
сервер БД, содержится и сама база данных. После получения SQL-запроса удаленный сервер направляет его SQL-серверу (серверу баз данных). SQL-сервер обеспечивает выполнение запроса и выдачу модулю расширения Web-сервера результатов запроса.
Таким образом, в трехуровневой архитектуре вся обработка SQL-запроса выполняется на удаленном сервере. Достоинства такой архитектуры по сравнению с предыдущей состоят в следующем: уменьшение сетевого трафика — в сети циркулирует минимальный объем информации; увеличение уровня безопасности информации, поскольку обработка запросов к базе данных выполняется сервером БД; повышение устойчивости Web-приложения к сбоям; взаимозаменяемость компонентов архитектуры приложения; снижение сложности модулей расширения Web-сервера.
Недостатком рассмотренной архитектуры является увеличение времени обработки запросов, связанное с дополнительным обращением по сети к серверу БД. Для устранения этого недостатка между сервером БД и Web-сервером должны использоваться высокоскоростные надежные линии связи.
Дальнейшее развитие архитектуры Web-приложений и технологии "клиент-сервер" привело к появлению многоуровневой архитектуры, в которой между модулем расширения Web-сервера и базой данных, кроме сервера БД, дополнительно вводится сервер приложений. Сервер приложений является промежуточным уровнем, который обеспечивает организацию взаимодействия клиентов ("тонких клиентов") и сервера БД.
Отметим, что в некоторых архитектурах информационных систем Web-сервер может структурно объединяться с сервером приложений.
При функционировании Web-приложений с использованием многоуровневой архитектуры сохраняется возможность параллельной работы Web-обозревателей и клиентских приложений БД. В этом случае говорят о смешанном Web-приложении.
Интерфейсы Web-приложений
В следующих разделах описаны общепринятые интерфейсы программирования Web-приложений — общий интерфейс взаимодействия CGI и интерфейс программирования серверных приложений ISAPI.
Общий интерфейс взаимодействия CGI
CGI-модуль представляет собой консольный исполняемый файл, загружаемый сервером для обработки данных обозревателя и генерации HTML-документа. Обмен данными между сервером и CGI-модулем происходит через стандартные входной и выходной потоки. Кроме того, для передачи параметров и получения системной информации могут задействоваться переменные окружения. При ис-
518
Часть IV. Базы данных и Интернет
пользовании CGI-интерфейса (протокола) можно формировать HTML-документ динамически (в ответ на запрос пользователя из обозревателя).
CGI-модуль может вызываться из обозревателя для динамического формирования HTML-документов на основании данных, введенных посетителями Web-сервера при помощи форм или путем выбора ими ссылок. Напомним, что обработку данных, введенных пользователем в интерфейсные элементы формы, можно выполнить с помощью обработчика, URL которого задается атрибутом action тега формы, а способ передачи данных из формы на Web-сервер определяет атрибут method тега формы.
При разработке CGI-модуля необходимо учитывать, каким методом HTTP-протокола будут передаваться данные между обозревателем и сервером. Основными методами передачи параметров запроса являются post и get. Метод post применяется для посылки информации, включенной в HTTP-запрос и относящейся к ресурсу, указанному URL-адресом CGI-модуля. Метод get используется для передачи информации в URL-адресе CGI-модуля. В зависимости от метода, примененного в HTTP-запросе, сервер формирует передаваемые для CGI-модуля параметры различными способами. В случае метода get для получения параметров запроса привлекаются переменные окружения (переменные операционной системы MS-DOS, устанавливаемые командой set), если же задействован метод post, данные доставляются через стандартный поток ввода (рис. 19.5).
Например:
<HTMLXHEADXTITLE>npMMep С61-модуля</Т1ТЬЕ>
</HEAD>
<BODY>
<А HREF="https://localhost/scripts/my_cgi.exe?TEST=modul">
Загрузить CGI-модуль по запросу
https://localhost/Scripts/my_cgi.exe?TEST=modul</A>
<FORM ACTION=https://localhost/scripts/my_cgi.exe METHOD=POST>
<В>Введите ваше имя:</В>
<INPUT MAXLENGTH=60 NAME=NAME SIZE=40 VALUE="My_login">
<BR>Tnn действия: <INPUT CHECKED NAME=TYPE TYPE=radio
VALUE=Registry>- Зарегистрировать <INPUT NAME=TYPE TYPE=radio УАЬиЕ=ЕхеС1гЬе>Выполнить сценарий <BRXINPUT NAME=Submit TYPE=Submit УАШЕ=Послать запроО <BRXINPUT NAME=Reset TYPE=Reset VALUE=C6pocXBR> </FORMX/PX/BODYX/HTML>
В окне обозревателя будут отображены ссылка (загрузить CGi-модуль по запросу https://iocaihost/Scripts/my_cgi.exe?TEST=modui) и элементы управления, входящие в состав формы. При нажатии специальной кнопки Послать запрос, имеющей тип Submit, обозреватель отправляет запрос Web-серверу. Последний, в свою очередь, запускает CGI-модуль, находящийся по URL-адресу https://localhost/Scripts/my_cgi.exe. При этом данные, введенные пользователем в интерфейсные элементы формы, переносятся через стандартный поток ввода.
Глава 19. Web-приложения и интерфейсы
519
При выборе пользователем ССЫЛКИ Загрузить CGI-модуль по запросу
https://iocaihost/Scripts/my_cgi.exe?TEST=modui обозреватель передает запрос Web-серверу на загрузку CGI-модуля, расположенного по URL-адресу https://localhost/Scripts/my_cgi.exe. При этом для посылки запроса используется метод get, и сервер отправляет CGI-модулю только данные, находящиеся в командной строке (TEST=modui) через переменную окружения query_string.
Метод get может использоваться и для передачи данных формы. В этом случае в теге формы указывается metod=get. При использовании метода get данные размещаются в переменной окружения query_string в следующем формате:
"Имя1=Значение1&Имя2=Значение2&ИмяЗ=ЗначениеЗ"
Здесь имя1, имя1, имяЗ — значения параметров name, задающих имена полей формы. При этом количество параметров определяется, исходя из числа элементов формы (в данном случае таких элементов три). На место значений параметров подставляются данные из соответствующих полей.
Отметим, что не все значения интерфейсных элементов формы передаются на сервер. Например, значение служебного элемента типа reset
<INPUT NAME=Reset TYPE=reset VALUE=C6poc>
не передается на сервер, т. к. оно не несет полезной информации.
Если в приведенном выше примере HTML-документа параметр method сопоставить с методом get, то переменная query_string примет значение
NAME=My_login&TYPE=Registry&Submit=Send
Это значение будет закодировано, т. е. символы пробела будут замещены символами +, а специальные и управляющие коды (в случае их использования) будут заменены на последовательности символов вида ххх, где хх — шестнадцате-ричное представление символа.
520
Часть IV. Базы данных и Интернет
Если в имена или в поля интерфейсных элементов входят символы, набранные в альтернативной кодировке, то при их передаче сервер будет также подставлять вместо каждого такого символа шестнадцатеричный код, предваряемый символом %.
Если в приведенном выше примере первый интерфейсный элемент оформить
как <input maxlength=60 ыаме=имя size=40 value="moe имя">, то переменная query_string будет иметь следующее значение:
%C8%CC%DF=%CC%CE%C5+%C8%CC%DF&TYPE=Registry&Submit=Send
В результате CGI-модуль генерирует HTML-документ, который помещается в стандартный поток вывода. Web-сервер задействует для управления и передачи различной информации CGI-модулю многочисленные переменные окружения.
Переменные окружения
Переменные окружения применяются в CGI-модуле для получения от Web-сервера служебной информации о самой программе Web-сервера, параметрах HTTP-запроса и другой информации, передаваемой сервером модулю. Например, в случае применения метода get при формировании HTTP-запроса в переменную query_string помещаются передаваемые пользовательские данные, а при альтернативном подходе (метод post) в переменных окружения content_type и content_length содержатся тип и длина передаваемой информации соответственно. Сами данные в последнем случае доставляются через стандартный входной поток.
Переменные окружения могут включать, к примеру, следующие данные:
□ server_name — символическое имя или IP-адрес компьютера, на котором запущен Web-сервер (задается в URL при обращении к этому Web-серверу);
□ gateway_inerface — версия CGI-интерфейса;
□ server_port — номер порта, на который обозреватель посылает запросы Web-серверу;
□ query_string — строка символов, следующая за знаком? в URL данного запроса;
□ remote_ident — имя пользователя, полученное от сервера (если сервер поддерживает аутентификацию);
□ httprefer — URL документа HTML, из которого осуществляется вызов CGI-модуля;
□ http_connection — тип соединения;
□ http_host — имя узла, на котором работает Web-сервер;
□ http_accept_encoding — тип схемы кодирования, используемой обозревателем для формирования запроса Web-серверу;
□ нттр from — имя пользователя, установленное в настройках обозревателя.
Глава 19. Web-приложения и интерфейсы
521
(Замечание^
Тип MIME (Multipurpose Internet Mail Extensions, многоцелевые расширения почтового стандарта Интернета) определяет протокол передачи почтовых сообщений, используемый взамен стандартного.
Для Web-сервера Microsoft PWS 95/2.0 в среде Windows 98 и адреса
HREF="https://igin/scripts/my_cgi.exe?TEST=modul"
задаваемого в адресной строке обозревателя, переменные окружения будут иметь следующие значения:
SERVER_SOFTWARE = Microsoft-PWS-95/2.0
SERVER_NAME = igin
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.0
SERVER_PORT = 80
REQUEST_METHOD = POST
HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
PATH_T PANSLATED = C:\WebShare\wwwroot\
SCRIPT_NAME = /scripts/my_cgi.exe
QUERY_STRING = TEST=modul
REMOTE_HOST = 127.0.0.1
REMOTE_ADDR = 127.0.0.1
CONTENT_TYPE = application/x-www-form-urlencoded
HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
HTTP_USER_AGENT = Mozilla/4.7 [en] (Win98; I)
HTTP_ACCEPT_LANGUAGE = en, ru
HTTP_CONNECTION = Keep-Alive
HTTP_HOST = igin
HTTP_ACCEPT_ENCODING = gzip
Остальные переменные принимают нулевое значение (Null).
Здесь: igin — имя компьютера, на котором выполняется CGI-модуль;
C:\webShare\wwwroot\— каталог, в котором находится CGI-модуль; my_cgi.exe — имя файла, содержащего модуль.
Для Web-сервера MS IIS 5.0 в среде Windows 2000 Server и адреса, задаваемого в адресной строке обозревателя:
https://igin/Scripts/my_cgi.exe
следующие переменные окружения могут иметь значения, отличные от представленных выше:
SERVER_SOFTWARE = Microsoft-IIS/5.0 SERVER_NAME = igin
522
Часть IV. Базы данных и Интернет
GATEWAY_INTERFACE = CGI/1.1 SERVER_PROTOCOL = HTTP/1.1 PATH_TRANSLATED = c:\inetpub\wwwroot SCRIPT_NAME = /Scripts/my_cgi.exe REMOTE_HOST = 127.0.0.1 REMOTE_ADDR = 127.0.0.1
Стандартный вывод
После перекодировки входных данных в CGI-модуле необходимо сформировать HTML-документ для передачи его на стандартное устройство вывода. При этом HTML-страница динамически генерируется на основании информации, хранимой в БД, которая может обновляться в реальном масштабе времени.
Интерфейс программирования серверных приложений ISAPI
Перспективным направлением, в котором развиваются технологии создания моделей расширения сервера, является интерфейс (протокол) программирования серверных приложений ISAPI. Этот интерфейс разработан для преодоления ограничений и недостатков интерфейса CGI. В отличие от CGI, интерфейс ISAPI предусматривает реализацию модулей расширения сервера в виде динамической библиотеки. При этом для обработки каждого запроса обозревателя к модулю расширения сервера ISAPI не создается отдельный процесс, а вызываются функции модуля ISAPI, которые один раз загружаются в память при первом обращении.
Есть несколько вариантов реализации протоколов серверных расширений. Наибольшее распространение получили два из них — NSAPI компании Netscape и ISAPI фирмы Microsoft. Из-за ограниченности объема книги мы рассмотрим только возможности протокола ISAPI.
Приложения, построенные с использованием протокола ISAPI, основаны на аналогичных с CGI-модулями принципах взаимодействия с сервером. Отличия указанных протоколов заключаются в осуществлении обмена данными между модулем и сервером.
Модули расширения ISAPI, как и модули CGI, принимают от сервера данные, которые передает модулю обозреватель, обрабатывают эти данные и динамически формируют HTML-документ. Однако вместо чтения содержимого переменных окружения и стандартного потока ввода модуль расширения ISAPI получает данные при помощи специально предназначенных для этого функций. Аналогично вместо записи выходных данных в стандартный поток вывода модуль расширения ISAPI также вызывает специальные функции.
Модули ISAPI в зависимости от назначения подразделяются на две группы: обычные модули расширения ISAPI и фильтры ISAPI. Первая группа предназначена, как и CGI-модули расширения сервера, для динамического формиро-
Глава 19. Web-приложения и интерфейсы
523
вания HTML-документов. Фильтры ISAPI обеспечивают выполнение нестандартных задач управления всеми данными, проходящими через сервер (например, кодирование данных, сбор статистической информации об использовании ресурсов сервера и т. д.).
Рассмотрим основные принципы создания и работы модулей расширений ISAPI. Модуль ISAPI реализуется в виде библиотеки DLL. Эта библиотека загружается в одно адресное пространство с Web-сервером при первом обращении к ней из обозревателя. Причем вызов ISAPI-модуля осуществляется подобно вызовам CGI-модулей расширения — из форм или ссылок. ISAPI-модуль исполняется в рамках единого адресного пространства программных ресурсов сервера. Такая организация ISAPI-модуля позволяет значительно повысить производительность сервера в целом по сравнению с сервером, использующим CGI-модули.
Преимущество ISAPI-интерфейса становится особенно заметным при одновременном активном использовании модуля расширения несколькими пользователями.
Отметим, что CGI-модули являются более надежным средством с точки зрения устойчивости Web-сервера к сбоям. Так, при возникновении ошибки в ISAPI-модуле может произойти аварийное завершение работы всего Web-сервера, тогда как в случае возникновения ошибки в CGI-модуле будет завершен только отдельный процесс. По упомянутой причине особенности отладки ISAPI-модуля состоят в том, что для перезапуска ISAPI-модуля требуется его переименовать или перезагрузить Web-сервер.
Рассмотрим структуру модулей ISAPI. Библиотека DLL, представляющая собой
ISAPI-МОДуЛЬ, Экспортирует как МИНИМУМ две функции: GetExtensionVersion И
HttpExtensionProc. Кроме этих функций, ISAPI-модуль может использовать функцию TerminateExtension, которой передается управление перед выгрузкой ISAPI-модуля из памяти. Эта функция освобождает ресурсы, выделенные ISAPI-модулю.
ФуНКЦИЯ GetExtensionVersion (var Ver: THSE_VERSION_INFO): BOOL Предназначена для того, чтобы ISAPI-модуль мог сообщить серверу версию спецификации ISAPI-интерфейса и строку описания ISAPI-модуля. Параметр-переменная ver указывает управляющую структуру, тип которой описан так:
type
THSE_VERSION_INFO = packed record
// Версия спецификации интерфейса ISAPI
dwExtensionVersion: DWORD;
// Строка описания модуля ISAPI
IpszExtensionDesc: array [0..HSE_MAX_EXT_DLL_NAME_LEN-1] of Char; end;
ФуНКЦИЯ HttpExtensionProc(var ECB: TEXTENSION_CONTROL_BLOCK): DWORD
обеспечивает основную функциональность ISAPI-модуля и используется для
524
Часть IV. Базы данных и Интернет
обмена данными между ISAPI-модулем и сервером. Параметр-переменная есв указывает управляющую структуру, тип которой описан так:
type
TEXTENSION_CONTROL_BLOCK = packed record
// Размер блока в байтах
cbSize: DWORD;
// Версия спецификации интерфейса ISAPI
dwVersion: DWORD;
// Идентификатор соединения
ConnID: HCONN;
// Код состояния HTTP
dwHttpStatusCode: DWORD;
// Данные протоколирования
IpszLogData: array [0..HSE_LOG_BUFFER_LEN - 1] of Char;
// Переменная окружения REQUEST_METHOD
IpszMethod: PChar;
// Переменная окружения QUERY_STRING
IpszQueryString: PChar;
// Переменная окружения PATH_INFO
lpszPathlnfo: PChar;
// Переменная окружения PATH_TRANSLATED
IpszPathTranslated: PChar;
// Полный размер данных, полученных от обозревателя
cbTotalBytes: DWORD;
// Размер доступного блока данных
cbAvailable: DWORD;
// Указатель на доступный блок данных
lpbData: Pointer;
// Тип полученных данных
IpszContentType: PChar;
// Функция для получения значений переменных окружения
GetServerVariable: TGetServerVariableProc;
// Функция для посылки данных обозревателю
WriteClient: TWriteClientProc;
// Функция для получения данных от посетителя
ReadClient: TReadClientProc;
// Служебная функция
ServerSupportFunction: TServerSupportFunctionProc; end;
Поясним особенности использования основных полей этой структуры данных.
Поле cbTotalBytes предназначено для записи суммарного количества байтов данных, принимаемых от обозревателя. Блок данных размером не более
Глава 19. Web-приложения и интерфейсы
525
48 Кбайт считывается сервером автоматически. Эти данные становятся доступны при вызове функции HttpExtensionProc. Но полностью данные дочитываются В ЦИКЛе при ПОМОЩИ фуНКЦИИ ReadClient.
Поле cbAvaiiabie служит для сохранения длины блока данных, полученных автоматически от обозревателя (не более 48 Кбайт).
Поле LpbData содержит указатель на область памяти, в которой размещен полученный сервером от обозревателя блок данных размером cbAvaiiabie байтов.
В управляющий блок помимо данных включены следующие указатели на методы.
Поле Getservervariabie содержит указатель на функцию, средствами которой ISAPI-модуль определяет значения переменных среды окружения.
В поле writeciient находится указатель на метод, используемый для отправки данных обозревателю, в отличие от интерфейса CGI, в случае применения которого модуль расширения помещает результат в стандартный поток вывода.
Поле ReadClient хранит указатель на функцию, предназначенную для считывания данных в буфер предварительного чтения, имеющий адрес LpbData и размер, не превышающий 48 Кбайт.
В поле serverSupportFunction содержится указатель на функцию, служащую для пересылки стандартного заголовка протокола HTTP и осуществления других действий.
Глава 20
Публикация баз данных средствами Delphi
Система Delphi предоставляет программисту мощные средства для разработки сложных Web-приложений. Специальные компоненты Delphi позволяют помещать информацию из БД непосредственно на HTML-страницы. С помощью Delphi можно создавать Web-приложения на основе интерфейсов CGI, WinCGI, ISAPI и NSAPI. В этой главе рассматривается использование интерфейсов CGI и ISAPI как наиболее часто встречающихся.
Компоненты, используемые при разработке Web-приложений
При разработке Web-приложений используются компоненты Палитры компонентов, расположенные на странице Internet (рис. 20.1). Рассмотрим назначение этих компонентов.
Рис. 20.1. Страница Internet Палитры компонентов
□ webDispatcher (Web-диспетчер) предназначен для создания Web-модуля данных и позволяет модулю расширения Web-сервера обрабатывать HTTP-запросы.
□ PageProducer (генератор страниц) предназначен для преобразования HTML-шаблона в HTML-документ. При этом в HTML-шаблоне производится замена специальных тегов на данные, которые генерируются динамически при выполнении программы с помощью обработки события опнтмьтад.
□ DataSetTabieProducer (генератор таблицы набора данных) предназначен для генерации HTML-документа, который содержит таблицу из данных, полу-
Глава 20. Публикация баз данных средствами Delphi
527
ченных в результате обработки запроса к БД на получение всех записей. Наследует свойства объекта TDataSet.
□ DataSetPageProducer (генератор страницы набора данных) предназначен для преобразования HTML-шаблона, содержащего ссылки на поля БД, вместо которых динамически при выполнении приложения подставляются значения из текущей записи БД.
□ QueryTabieProducer (генератор таблицы по запросу) предназначен для генерации HTML-документа, который содержит таблицу из данных, полученных в результате обработки запроса к БД.
□ SQLQueryTabieProducer (генератор таблицы по SQL-запросу) предназначен для генерации HTML-документа, который содержит таблицу из данных, полученных в результате обработки SQL-запроса к БД.
□ Tcpciient (клиент TCP) добавляет объект типа TTcpCiient к форме или модулю данных для преобразования приложения в TCP/IP-клиента; определяет требуемое соединение с сервером TCP/IP, управляет открытым соединением и завершает законченное соединение.
□ TcpServer (сервер TCP) добавляет объект типа TTcpServer к форме или модулю данных для преобразования приложения в сервер TCP/IP; ожидает запросы на TCP/IP-соединения от других машин и устанавливает соединения при получении запросов.
□ udpSocket (сокет UDP) добавляет объект типа TUdpSocket к форме или модулю данных для преобразования приложения в UDP/IP-клиент или UDP/IP-сервер.
□ XMLDocument (документ XML). Класс TXMLDocument может использоваться непосредственно для доступа к узлам (элементам) документа с помощью интерфейса IXMLNode или применяться совместно с классами и интерфейсами, генерируемыми Мастером XML Data Binding.
□ WebBrowser (Web-обозреватель) создает собственный обозреватель для отображения HTML-страниц. Для использования этого компонента требуется Microsoft Internet Explorer версии не ниже 4.0.
(_____ ЗамечаниеJ
UDP (User Datagram Protocol) представляет собой протокол передачи прикладных пакетов дейтаграммным методом. Подобно TCP, использует протокол IP для доставки данных, но, в отличие от TCP, обеспечивает обмен дейтаграммами без подтверждения.
В справке указано назначение еще двух компонентов: ciientSocket (сокет клиента, служит для создания приложений TCP/IP-клиента, может быть добавлен к форме или модулю данных) и ServerSocket (сокет сервера, служит для создания приложений TCP/IP-сервера, может быть добавлен к форме или модулю данных), которых на странице Internet Палитры в действительности нет.
При разработке Web-приложений наиболее часто используются компоненты, предназначенные ДЛЯ генерации HTML-документов (PageProducer, QueryTabieProducer,
528
Часть IV. Базы данных и Интернет
DataSetTableProducer, DataSetPageProducer) И ДЛЯ создания модулей расширения Web-сервера (webDispatcher). Более подробно особенности их применения будут рассмотрены ниже.
Статическая публикация
Как отмечалось, статическая публикация базы данных в Интернете используется при редком обновлении информации в БД. При использовании такого типа публикации информация из БД помещается в HTML-документ, который хранится постоянно в файле на диске. При этом запрос на получение данных не приводит к большой загрузке сервера, т. к. пользователю возвращается уже готовый HTML-документ.
Для статической публикации можно использовать обычное приложение Windows, которое запускают периодически (после обновления информации в БД). Вообще говоря, для такой публикации достаточно создать простейшее приложение БД, которое обеспечивает:
□ доступ к БД;
□ генерацию HTML-документа на основе информации, получаемой из БД;
□ сохранение созданного файла на диске.
Рассмотрим особенности использования средств Delphi для решения этих задач на следующем примере.
Пусть требуется выполнить статическую публикацию содержимого демонстрационной БД, входящей в состав стандартной поставки Delphi. Эта БД имеет псевдоним dbdemos и имя файла таблицы Animals.dbf (при полной установке Delphi псевдоним создается автоматически).
Разместим в форме 2 кнопки Button и установим с помощью Инспектора объектов их свойства Name в значения Gen и show соответственно. Кроме кнопок, поместим в форму компонент Table. Ниже приведен код модуля DbHTML генератора HTML-страниц.
unit DbHTML;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, DBTables, StdCtrls, ComCtrls; type
TDbHTMLForm = class(TForm) Tablel: TTable; Gen: TButton; Show: TButton; procedure GenClick(Sender: TObject); procedure ShowClick(Sender: TObject); end;
Глава 20. Публикация баз данных средствами Delphi
529
var
DbHTMLForm: TDbHTMLForm; implementation
{$R *.DFM}
uses
Shellapi, FileCtrl;
// Обработчик события OnClick кнопки Gen procedure TDbHTMLForm.GenClick(Sender: TObject); var HTMLStr: TStringList;
I: Integer; begin
// Инициализация объекта Table1 Tablel.Close;
Table1.DatabaseName:= 'DBDEMOS'; Tablel.TableName: = 'Animals.dbf; Tablel.Open;
// Создание заголовка HTML-документа
HTMLStr:= TStringList.Create;
HtmlStr.Clear;
HtmlStr.Add ('<HTML>');
HtmlStr.Add ('<HEAD>');
HtmlStr.Add ('<TITLE>' + 'HTML-страница, отчет из БД' +
'</TITLE>'); HtmlStr.Add ('</HEAD>');
HtmlStr.Add ('<BODY BGCOLOR="#FFFFEE">'); HtmlStr.Add ('<H1><CENTER> Данные из файла ' + Tablel.TableName +
'</CENTERX/Hl>');
// Вывод тега, открывающего таблицу HtmlStr.Add('<TABLE BORDER>');
// Вывод тега, открывающего строку таблицы
HtmlStr.Add('<TR>');
// Создание заголовков таблицы
for I:= 0 to Tablel.FieldCount - 1 do
HtmlStr.Add('<TH>' + Tablel.Fields[I].FieldName + '</TH>'); // Вывод тега, закрывающего строку таблицы HtmlStr.Add('</TR>');
530
Часть IV. Базы данных и Интернет
II Вывод данных Tablel.First; // Перебор всех записей while not Tablel.EOF do begin HtmlStr.Add('<TR>');
for I:= 0 to Tablel.FieldCount - 1 do // Вывод тега ячейки данных таблицы if Tablel.Fields[I].DisplayText = ''
then HtmlStr.Add('<TD>' + ' '+ '</TD>')
else HtmlStr.Add('<TD>' + Tablel.Fields[I].DisplayText + '</TD>'); HtmlStr.Add('</TR>'); Table1.Next; end;
// Вывод тега, закрывающего таблицу
HtmlStr.Add('</TABLE>');
// Вывод тега, закрывающего тело документа
HtmlStr.Add ('</BODY>');
// Вывод тега, закрывающего документ
HtmlStr.Add ('</HTML>');
// Сохранение сформированного HTML-документа в файле Htmltest.htm HtmlStr.SaveToFile ('Htmltest.htm'); HtmlStr.Free; end;
// Обработчик события OnClick кнопки Show
procedure TDbHTMLForm.ShowClick(Sender: TObject);
begin
// Запуск просмотра файла HTMLTEST.htm
ShellExecute (Handle, 'open', pChar('HTMLTEST.htm'), '', '', sw_ShowNormal);
end;
end.
В приведенном примере HTML-страницы генерируются без использования специальных средств библиотеки VCL. Формирование и сохранение в файле HTML-страниц задается в явном виде. Интерфейсная часть приложения представляет собой ОКНО С двумя кнопками: Gen И Show.
Рассмотрим подробнее, как происходит обработка события нажатия кнопки.
Глава 20. Публикация баз данных средствами Delphi
531
В процедуре GenClick ИСПОЛЬЗуеТСЯ объект HTMLStr ТИПа TStringList, В КОТОРОМ хранятся строки формируемого HTML-документа. В начале процедуры выполняется инициализация объекта Tabiei с помощью следующего кода:
Tablel.Close;
Table1.DatabaseName:= 'DBDEMOS';
Tablel.TableName: = 'Animals.dbf;
Tablel.Open;
Здесь для объекта Tablel устанавливаются значения свойств, задающих источник БД. Свойство DatabaseName определяет псевдоним (dbdemos), а свойство TabieName задает таблицу БД (в рассматриваемом случае используемая таблица находится в файле Animals.dbf). Методы close и open соответственно закрывают и устанавливают соединение с БД. При этом вызов метода close перед инициализацией объекта Tablel обеспечивает успешное выполнение кода при повторном обращении к процедуре GenClick.
Далее в процедуре осуществляются создание объекта stringList с помощью конструктора Create:
HTMLStr:= TStringList.Create;
и его инициализация с помощью метода clear:
HtmlStr.Clear;
Формирование HTML-документа выполняется с помощью метода Add:
HtmlStr.Add ('<HTML>');
Информация из БД выводится в формируемый HTML-документ в табличном виде. В частности, заголовок таблицы выводится с помощью следующего кода:
HtmlStr.Add('<TABLE BORDEFO ');
HtmlStr.Add('<TR>');
for I:= 0 to Tablel.FieldCount - 1 do
HtmlStr.Add('<TH>' + Tablel.Fields[I].FieldName + '</TH>');
HtmlStr.Add('</TR>');
Свойство FieldCount задает число полей в записи таблицы. Строка Tablel.Fields [I].FieldName возвращает указатель на строку, содержащую имя поля. При этом объект Fields является массивом полей записи. Выражение Fields [I] позволяет обратиться к полю записи с номером i (нумерация с нуля).
Далее в обработчике стоит итерационный цикл, содержащий вложенный цикл с параметром:
Tablel.First;
while not Tablel.EOF do begin
HtmlStr.Add('<TR>');
for I:= 0 to Tablel.FieldCount - 1 do if Tablel.Fields[I].DisplayText = ''
532
Часть IV. Базы данных и Интернет
</TD>' |
then HtmlStr.Add('<TD>' +
else HtmlStr.Add('<TD>' + Tablel.Fields[I].DisplayText + '</TD>'); HtmlStr.Add('</TR>'); Table1.Next; end;
Перед началом цикла с помощью метода First указатель текущей записи устанавливается на первую запись таблицы. Во внешнем цикле указатель текущей записи последовательно перемещается по записям таблицы, а во внутреннем цикле осуществляется перебор всех полей текущей записи. Выход из внешнего цикла происходит при достижении указателем текущей записи конца таблицы (значение выражения not Tablel.eof становится ложным).
Метод Tablel.Fields [I].DisplayText возвращает указатель на строку, содер
жащую данные из 1-го поля текущей записи. Чтобы обозреватель не нарушал
структуру таблицы, при отсутствии в поле данных в формируемый