Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Если один шаблон содержит несколько таких тегов, то событие ОnHTMLTag активизируется не один раз в пределах обработки одного шаблона




Давайте создадим серверный модуль, который будет генерировать Web-страницу с указанием текущего времени часов сервера, по часовому поясу, в котором находятся Москва и Афины.

Для этого, прежде всего, нужно сделать шаблон. Один из возможных вариантов шаблона приведен в листинге 10.2.

Листинг 10.2. Шаблон Web-страницы, на основании которого \в дальнейшем будет создан серверный модуль

<HTML>

<Н2>Привет!</Н2>

<Р>Сейчас на сервере: <#time ID=1>

<Р>А в Афинах: <#time ID=2>

<Н2>Счастливо!</Н2>

</HTML>

В шаблоне использовано два "прозрачных" тега, причем они отличаются лишь значением атрибута ID.

Создадим новый проект серверного модуля в Delphi с названием interact и добавим в него новое действие someinfo. Адрес на его активизацию укажем аналогично названию. После этого на вкладке "Internet" Component Palette нужно выбрать компонент TPageProducer и поместить его в наш Web-модуль. После присвоения свойству NAME нового генератора страниц, значения siproducer, его можно присвоить значению атрибута Producer действия someinfo.

После того как завершен процесс согласования свойств различных объектов системы, можно приступить к описанию функциональных особенностей работы объекта siproducer.

Поскольку в своей работе он будет использовать готовый шаблон, то нужно указать путь к этому файлу. Создайте файл шаблона, текст которого приведен в листинге 10.2 в каталоге HTDOCS того каталога, где установлен Apache и укажите в значении свойства HTMLFile объекта путь к нему.

Если скомпилировать проект в том виде как есть и, запустив сервер и браузер, указать в адресной строке последнего путь http://Iocalhost/cgi-bin/interact/someinfo, то загрузится страница без необходимых интерактивных данных. Обеспечим их появление.

Для этого необходимо активизировать свойство оштмьтад объекта siproducer.

В результате в тексте модуля Unitl появится код, приведенный в листинге 10.3.

Листинг 10.3. Шаблон для ввода функции — обработчика "прозрачных" тегов

procedure TWebModulel.SIpro'ducerHTMLTag(Sender: TObject; Tag: TTag;

const TagString: String; TagParams: TStrings; var ReplaceText: String); begin

end;

Несколько параметров, предусмотренных в этой процедуре, предназначены как для идентификации данных, с которыми должен работать код процедуры, так и для возврата результата работы модуля. Рассмотрим их подробнее:

  • sender. Хранит название объекта, вызвавшего эту функцию.
  • Tag. Указывает тип "прозрачного" тега. В Delphi определены следующие типы тегов (табл. 10.4). Теги, перечисленные в левой колонке таблицы, разумеется не появляются в теле HTML-шаблона. Они лишь описывают "прозрачные" теги. Например, все теги шаблона, приведенного в листинге 10.2, будут относиться к типу tgCustom.

Таблица 10.4. Предопределенные типы тегов

Название тега Описание
tgLink Соответствует появлению в шаблоне тега ссылки <А>. Результатом работы процедуры должна быть ссылка
tglmage Это значение параметр Tag принимает в случае, когда "прозрачным" тегом является HTML-элемент IMG. Процедура в результате своей работы должна предоставить описание изображения

 

tgTable To же самое для таблицы
tglmageMap То же самое для клиентской карты
tgObject То же самое для Active-объекта
tgEmbed То же самое для внедренного документа
tgCustom В случае когда в шаблоне встречается "прозрачный" тег, отличный от описанных выше, то параметр Tag принимает это значение
  • Tagstring. Этот параметр содержит, собственно, сам HTML-тег. Обратите внимание, что значением параметра является название элемента, без знаков <, > и #. Например, если "прозрачный" тег имеет вид </TABLE NAME=" mytabie">, то значением параметра Tagstring будет слово TABLE.
  • TagParams. Массив строк, содержащих значения атрибутов присвоенных данному "прозрачному" тегу.
  • RepiaceText. Переменная, которой в результате своей работы рассматриваемая функция siproducerHTMLTag должна присвоить замещаемое значение HTML-кода.

Итак, в добавленной процедуре необходимо обеспечить замещение "прозрачных" тегов новым HTML-кодом. Для этого нужно в тело процедуры вписать код, приведенный в листинге 10.4.

Листинг 10.4. Тело процедуры

procedure TWebModulel.SiproducerHTMLTag(Sender: TObject; Tag: TTag;

const TagString: String; TagParams: TStrings; var RepiaceText: String); begin if (tagparams.Values['ID1]=('!')) then

RepiaceText:=Timetostr(Now)

else RepiaceText:=(Timetostr(Now-Encodetime(l,0,0,0)));

end;

Поскольку в шаблоне отсутствуют "прозрачные" теги, отличные от time, то проверку параметра Tagstring производить не нужно. В противном случае, оператор if изменится следующим образом:

if (TagString='time') and (tagparams.Values['ID1]=('1')) then...

Во время работы серверного модуля процедура siproducerHTMLTag вызывается дважды для обработки двух заданных тегов.

В результате получится страница, приведенная на рис. 10.7.

Рис. 10.7. Полученная Web-страница

Комбинация различных "прозрачных" тегов и их параметров позволяет организовать достаточно развитые механизмы выбора алгоритма наполнения Web-страницы активными элементами.

 

Получение параметров клиентских запросов (Класс TCGIRequest)

Разумеется, использование шаблонов и соответствующей процедуры их обработки не исчерпывает всех возможностей CGI. При интенсивном обмене данными между клиентом и сервером необходимо иметь доступ ко всему множеству параметров запроса, исходящего от клиента. В отличие от обычного CGI, реализованного классическими средствами консольного приложения, алгоритмы, которые создаются программистом на базе объектов Delphi, не нуждаются в прямом доступе к переменным окружения и потокам ввода с последующим переводом содержащихся в них данных, к удобному для использования формату. При запуске модуля создается объект Request класса TCGIRequest. В этот объект, при его инициализации, автоматически помешается вся информация, характеризующая запрос. В своей работе программист может использовать объект Request, в полях которого собраны воедино все данные пользователя. Наиболее важные свойства данного объекта приведены в табл. 10.5.

Таблица 10.5. Некоторые свойства объекта Request

Свойство Описание
Accept Тип MIME-данных, которые готов принять клиент в ответном потоке
Authorization Содержит информацию об аутентификации
CacheControl Содержит описание способа кэширования информации клиентом
Connection Содержит тип соединения, которое поддерживает браузер клиента
Content В случае если в запросе данные отправлялись методом Post, то это поле содержит тело запроса
ContentLength Содержит число символов в запросе
ContentType Содержит тип данных, отправленных в запросе
Cookie Поля cookie-файлов
Date Содержит дату и время отправки запроса
Method Содержит метод запроса
Pathlnfo Включает часть URL, содержащую адрес к модулю, обрабатывающему запрос
Query В случае, когда запрос осуществлялся методом Get, это поле содержит строку запроса (часть URL после знака?)
RemoteAddr Содержит IP-адрес клиента
UserAgent Определяет программное обеспечение клиента (модель браузера и операционной системы)
ContentFields Tstrings-массив, содержащий поля Post-запроса
CookieFields Tstrings-массив, содержащий поля cookie, переданные вместе с запросом
QueryFields Tstrings-массив, содержащий пола GET-запроса

Обратите внимание, что последние три свойства являются очень удобными для получения данных запросов. Если в классическом CGI-модуле приходится вводить функции для раскодировки содержимого полей форм, то здесь все данные уже доступны по имени элемента формы, в котором они были введены.

Рассмотрим пример. Пусть на Web-странице имеется форма для ввода смещения часового пояса клиента относительно Гринвича. Модернизируем предыдущий проект таким образом, чтобы клиент, кроме московского времени, мог узнать время в любом поясе Земли.

Прежде всего, необходимо заготовить начальную страницу, с которой пользователь отправит число, означающее интересующее его смещение времени.

Такая страница может иметь код, приведенный в листинге 10.5.

Листинг 10.5. Код страницы, в которой клиент указывает смещение времени

<HTML>

<Р>Укажите интересующий часовой пояс:

<FORM action="http://localhost/cgi-bin/interact/someinfo" method="POST">

<INPUT type="text" size=l maxlength=l name="dispersion">

<INPUT type="Submit" value="send">

</FORM>

</HTML>

Сохраните этот код в файле с названием someinfo.htm в том каталоге, где были сохранены предыдущие файлы примеров.

Кроме того, нужно изменить имеющийся шаблон, как показано в листинге 10.6.

Листинг 10.6. Измененный шаблон)

<HTML>

<Н2>Привет!</Н2>

<Р>Сейчас на сервере: <#time ID=1>

<Р>В Афинах: <ltime ID=2>

<Р>А в интересущем часовом поясе — <#interestedtime>

<Н2>Счастливо!</Н2>

</HTML>

Откройте предыдущий пример и дополните процедуру siproducerHTMLTag, как представлено в листинге 10.7.

Листинг 10.7. Дополненная процедура siproducerHTMLTag

procedure TWebModulel.SIProducerHTMLTag(Sender: TObject; Tag: TTag; const TagString: String; TagParams: TStrings; var ReplaceText: String); begin if (TagString='time') and (tagparams.Values['ID']=('1')) then ReplaceText:=Timetostr(Now) else if (TagString='time')

then ReplaceText: = (Timetostr(Now-Encodetime(1, 0, 0,0))) else ReplaceText:=Timetostr(Now-Encodetime(2,0,0,0)+ Encodetime(strtoint(Request. ContentFields.Values['dispersion']),0,0,0))

end;

Сохраните HTML-файл,, заполните форму, и на экране получится результат, приведенный на рис. 10.8.

Рис. 10.8. Результат работы модифицированного модуля

Как увидеть, выражение Request. ContentFields. Values ['dispersion'] обеспечивает удобный доступ к содержимому поля dispersion HTML-формы.

Обратите внимание, что в отсутствии введенных данных при обращении к полю формы не возникает исключительной ситуации.

 

Формирование параметров серверного ответа (класс TCGIResponse)

Поскольку зачастую ответ клиенту необходимо строить не только на основании шаблонов, но и используя различные сервисы, предоставляемые CGI, бывает удобно переложить весь процесс формирования ответа на самостоятельно подготовленный программистом код. Доступ ко всем информационным параметрам сообщения от сервера к клиенту обеспечивают объекты класса TCGIResponse.

Программист может посредством этих объектов не только определять наполнение ответа, но и управлять его отправкой. Это позволяет делать программы поистине гибкими и функциональными. Как и в случае с объектами класса TCGiRequest, где, правда атрибуты определены только для чтения, поля рассматриваемого класса предоставляют доступ ко всем необходимым параметрам.

Кроме того, многие поля предоставляют доступ к служебной информации, которая носит описательный характер и генерируется внутренними методами объектов класса. Обычно, при работе серверного модуля объекты класса TCGiResponse создаются автоматически и называются Response. Основные свойства этого объекта приведены в табл. 10.6.

Таблица 10.6. Основные свойства объекта Response

Свойство Описание
Allow, Определяет тип методов запросов, которые может обслуживать объекты данного класса
Content Содержит ответное сообщение. Данное поле имеет строковый формат и, как правило, должно содержать тело HTML-документа, либо двоичные данные, если, например, клиенту отправляется динамически созданный графический файл
ContentLength Возвращает число байт информации, отправляемой пользователю
ContentType Тип MIME содержимого ответа
Expires Содержит дату и время, когда информация, отосланная клиенту, должна считаться устаревшей
Server Содержит марку Web-сервера
StatusCode Содержит код, идентифицирующий статус выполнения клиентского запроса
ContentStream Как и свойство Content, содержит тело передаваемого сообщения, однако это поле имеет формат потока, что оптимизирует многие операции, например чтение из графического файла, с последующей отправкой содержимого
Cookies Содержит набор cookie-заголовков, которые должны быть отосланы клиенту вместе с ответом
CustomHeaders Содержит объект TStrings, который позволяет программисту устанавливать собственные HTTP-заголовки
HTTPRequest Объект Request, который вызвал создание данного объекта Response
Sent Содержит булевское свойство, которое возвращает информацию о том, отослан ли ответ клиенту
Location URL-адрес конечного документа. Используется в случае, когда вместо обработки запроса серверный модуль осуществляет его переадресацию

Кроме этих полей, данный объект содержит методы, приведенные в табл. 10.7.

Таблица 10.7. Методы объекта Request

Метод Описание
SendRedirect Функция, которая вместо отправки содержимого ответа посылает клиенту сообщение о необходимости переадресации запроса. Аргументом является URL, на который осуществляется этот переход
SendResponse Выдает команду объекту отослать ответ
SendStream Отправляет содержимое потока, указанное в аргументе, в качестве ответа клиенту
Sent Аналогично свойству Sent, возвращает информацию о том, отослан ли ответ клиенту
GetCustomHeader Возвращает значение HTTP-заголовков, установленных специально, по имени соответствующего заголовка
SetCookieField Добавляет к ответу cookie-параметр
SetCustomHeader Добавляет заголовок к HTTP-ответу

Работать с данным объектом удобно в контексте обработчика события OnAction действия.

Рассмотрим пример, возвращающий пользователю изображение, которое предварительно будет загружено серверным модулем и, затем, отправлено в поток вывода.

Как обычно, для этого необходимо вначале создать новый серверный модуль, затем добавить в него новое действие. Не важно, как оно будет называться, главное установить его вызов по умолчанию. После этого активизируйте это действие и перейдите на вкладку Events в окне Object Inspector. Если теперь два раза щелкнуть мышью по событию OnAction, то в окне Code Editor откроется "скелет" для ввода содержимого функции. Добавьте в нее код, приведенный в листинге 10.8.

Листинг 10.8. Пример кода, демонстрирующий отправку клиенту содержимого графического файла

procedure TWebModulel.WebModulelWebActionltemlAction(Sender: TObject;

Request: TWebRequest; Response: TWebResponse; var Handled: Boolean); var

stream:tmemorystream; begin

stream:=tmemorystream.Create;

stream.LoadFromFile('d:\кaпля.gif'); Response.ContentType:=('image/gif); Response.ContentStream:=stream; Response.SendResponse;

end;

Разумеется, название функции будет зависеть от названия действия. В примере оно оставлено по умолчанию. Путь также можно вводить к произвольному файлу. Главное, чтобы тип указанных MIME-данных совпал с фактическим содержимым файла.

Если скомпилировать проект (предварительно сохранив его в каталоге cgi-bin сервера) и указать адрес к исполняемому модулю, то в браузере появится следующее изображение (рис. 10.9).

Рис. 10.9. Изображение, которое было получено из потока вывода серверного модуля

В этом примере содержимое файла сначала загружается в поток stream, а затем отправляется клиенту. Перед отправкой необходимо указать тип содержимого.

Подробное описание применения объектов Response и Request смотрите в разделе, посвященном реализации информационной системы фирмы "Два кирпича" данной главы.

 

Работа с базами данных и генерация таблиц

Поскольку работа с базами данных занимает очень важное, если не центральное место в вопросах клиент-серверного взаимодействия, то мы в третий раз в данной книге коснемся этого вопроса, на этот раз с чисто практической точки зрения. Для начала, рассмотрим общие вопросы настройки и подключения баз данных. Опытные разработчики могут этот раздел пропустить.

 

Подключение базы данных

Для использования базы данных (БД) ее необходимо зарегистрировать в системе. Это позволяет избавиться от необходимости работать с физическим представлением информации в виде файла, и переложить ряд сервисов по обслуживанию доступа к данным, которые хранятся в БД, на соответствующий драйвер. Более того, регистрация БД скрывает многие аспекты взаимодействия с ней, такие как расположение самого файла с таблицами, его формат, и даже обеспечивает универсальность доступа к данным — с помощью языка SQL (см. гл. 3).

В поставку Delphi входит утилита Borland Database Engine (BDE), обеспечивающая взаимодействие программ, написанных с использованием продуктов этой фирмы, с БД. BDE обеспечивает взаимодействие программ как с локальными, так и удаленными БД, и, поскольку она должна включаться в комплект к любому программному продукту, написанному с использованием Delphi, то разработчики имеют право на неограниченное распространение этой утилиты.

Подключим к системе базу данных, находящуюся на дискете с примерами в каталоге database.

Прежде всего, необходимо перенести БД на жесткий диск. Для этого, скопируйте папку database в любой удобный каталог диска. Далее необходимо запустить утилиту BDE Administrator, значок которой находится на Панели управления. Перед вами откроется следующее диалоговое окно (рис. 10.10).

Здесь слева представлены пункты, соответствующие БД, зарегистрированным в системе. При активизации этих БД справа будут появляться их свойства. Для добавления новой БД необходимо выбрать пункты меню Object | New, после чего на экране появится окно выбора драйвера подключаемой базы данных. Название драйвера нужно оставить по умолчанию — Standard. После этого, в списке псевдонимов подключенных баз данных появится новый — Standard 1. Переименуйте его, выбирая опцию Rename контекстного меню (чтобы оно появилось, нужно щелкнуть правой кнопкой мыши, указав курсором мыши на псевдоним), на название shop. Теперь необходимо установить опцию, появившуюся в правой части окна Default Driver в Paradox и указать путь к каталогу, в котором хранятся файлы базы данных.

Все! Для любой программы, которую вы напишете на Delphi, уже неважно, где находится БД, как с ней нужно работать и т. д. Есть только псевдоним shop, по которому необходимые данные будут доступны.

Рис. 10.10. Вид утилиты BDE Administrator

 

Невизуальные объекты для работы с БД

Обычно при разработке настольных приложений, взаимодействующих с БД, создается специальный объект — контейнер, напоминающий форму, но отличающийся от последней тем, что служит для размещения только невизуальных компонентов. При написании CGI-модулей все невизуальные компоненты, относящиеся к работе с БД, можно помещать в автоматически создаваемый Web-модуль. В Delphi есть два фундаментальных компонента, обеспечивающие подключение к зарегистрированным БД: ттаЫе и TQuery. В отличие от настольных приложений, в которые нужно добавлять компоненты для отображения таблиц БД на экране, а также объект класса TDataSource, как "промежуточный слой" в обмене данными между последними и компонентами ттаЫе и TQuery, при работе в полностью невизуальной среде этого не требуется. Пиктограммы компонентов ттаЫе, TQuery и TDataSource приведены на рис. 10.11.

Компонент ттаЫе предназначен для доступа к таблицам, чтения и модифицирования данных, хранящихся в них. Использование этого компонента существенно облегчает и ускоряет разработку приложений, работающих с БД. Однако в сетевых программных комплексах лучше применять другой компонент — TQuery, обеспечивающий работу с таблицами путем передачи команд языка SQL, что позволяет создавать более гибкие решения, базирующиеся на всей мощи этого языка.

Рис. 10.11. Значки компонентов TTable, TQuery и TDataSource

Выполнение SQL-запросов и доступ к ячейкам таблицы

Подробно работу с базами данных мы описывать не будем, поскольку существует большое число хороших пособий по данной теме. Однако поскольку для реализации запланированного примера нам потребуется компонент TQuery, то коснемся основных моментов его работы.

Класс TQuery обладает основными свойствами, приведенными в табл. 10.8.

Таблица 10.8. Некоторые свойства объектов класса TQuery

Свойство Описание
Constrained Устанавливает запрет (значение true) на добавление и вставку в таблицу записей, не согласующихся с условиями проведенной выборки данных SELECT
ParamCount Возвращает число установленных параметров выборки
Params Содержит параметры SQL-запроса
RequestLive Если значение равно false, то в результате SQL-запроса генерируется таблица read-only. В противном случае, создается таблица, которая может быть изменена
RowsAffected Возвращает число строк, которые были получены, обновлены или удалены в результате выполнения последнего SQL-запроса. Если значение равно -1, то запрос не выполнился из-за возникшей ошибки
SQL Обозначает объект TStrings, который содержит строки SQL-запроса
Text Возвращает массив PChar — указателей на символы отправленного SQL-запроса
Filter Содержит выражение для фильтрации записей

 

Filtered Обеспечивает включение/отключение фильтрации записей
FilterOptions Определяет чувствительность к регистру фильтрации записей, а также разрешение на частичное совпадение фильтруемого выражения
RecNo Содержит порядковый номер текущей записи
RecorciCount Содержит общее число записей в сформированной таблице. Работает с таблицами Paradox и DBase
RecordSize Содержит размер памяти, отводимый под хранение одной записи таблицы
Active Открывает/закрывает текущий SQL-запрос
Bof Если значение равно true, то курсор находится на первой записи таблицы. В противном случае, принимает значение false
Eof Если значение равно true, то курсор находится на последней записи таблицы. В противном случае, принимает значение false
FieldCount Содержит число полей в записи
FieldValues Это свойство обеспечивает доступ к значению поля, которое указано в параметре свойства, для текущей записи

Для того чтобы получить доступ к представлению таблицы, сформированному в результате выполнения SQL-запроса, необходимо:

  • задать название БД, с которой будет вестись работа;
  • задать строку SQL-запроса, в результате которого должна быть сформирована таблица;
  • если это необходимо, то задать параметры для запроса;
  • установить значение свойства Active в true для отправки SQL-запроса драйверу БД;
  • если это необходимо, то задать параметры фильтрации данных и включить фильтр.

Наиболее часто используемые методы объектов класса TQuery описаны в табл. 10.9.

Таблица 10.9. Некоторые методы объектов класса TQuery

Метод Описание
ExecSQL Выполняет SQL-команду, указанную в свойстве SQL. He используется для команды SELECT

 

Cancel Отменяет изменения в текущей записи таблицы, если они еще не были отправлены в базу данных
Post. Отправляет изменения, внесенные в таблицу, в БД
Append Добавляет новую запись в представление таблицы, сформированное на основании SQL-запроса
Delete Удаляет текущую запись в таблице
Edit Открывает процесс редактирования данных в представлении таблицы
First Помещает курсор на первую позицию представления таблицы
Insert Вставляет новую запись в текущую позицию курсора
InsertRecord Вставляет новую запись и заполняет значения полей параметрами процедуры
Last Переводит курсор на последнюю запись представления таблицы
MoveBy Перемещает курсор на запись, отстоящую от текущей на число, указанное в параметре. Если число положительное, то курсор перемещается к последующей записи, а если отрицательное, то к предыдущей
Next Перемещает курсор к следующей записи
Refresh Обновляет содержимое представления таблицы из БД. Используется, если базу редактирует несколько клиентов одновременно
SetFields Устанавливает значения всех полей текущей записи из параметров процедуры



Поделиться с друзьями:


Дата добавления: 2014-12-29; Просмотров: 399; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.061 сек.