Режим IntraWeb Page-mode.

 

Николай Ренжиглов ®

 

IntraWeb поддерживает два режима разработки сайтов: Application (Stand Alone application) и Page-Mode (речь идет, как и ранее, о поставке продукта вместе с Delphi 7.0 Enterprise и Architect). Описанный ранее Stand Alone-режим реализовывался как отдельный сервер или служба Windows 2000. Для сравнительного анализа с режимом Page-mode, который мы рассмотрим в этой главе, уделим внимание режиму IntraWeb-приложения, расширяющего функции другого (здесь и далее “основного” сервера) IIS или Apach.

Когда приложение разрабатывается как расширение основного сервера, все запросы направляются на обработку этим сервером, установленным на компьютере. Основной сервер перенаправляет запросы IntraWeb-приложению, которое генерирует ответ. Ответ передается основному серверу и далее клиенту для просмотра в браузере:

 

HTTP-клиент

 

WEB-сервер

 

IntraWeb- приложение

 

 

 

Справа на рисунке показан модуль расширения основного сервера, работающий в отдельном потоке. Для сравнения изобразим те же объекты в случае работы Stand alone-приложения:

 

HTTP-клиент

 

IntraWeb- приложение

 

 

В этой ситуации каждый серверный поток стартует при вызове нового экземпляра WEB-браузера на клиентском компьютере. Сколько окон браузера с клиентской стороны, столько и потоков на сервере.

Режим Page-mode используется для создания страниц, работающих в составе многостраничного  WEB-сайта. Здесь IntraWeb-приложение также работает через ISAPI-расширение основного сервера, но “несет ответственность” только за свою страницу сайта. Функциональности таких страниц могут быть также реализованы с использованием других языков (PHP или ASP для IIS), а серверные расширения как приложения Kylix, Delphi или C++ Builder.

 

В режиме Page Mode запрос клиента также обрабатывается основным сервером компьютера, который передает его дальше ISAPI-расширению, написанному, например, с использованием WebBroker или WebSnap. Далее диспетчер страниц WebBroker направляет его IntraWeb-приложению, генерирующему ответ с использованием стандартного механизма WebSnap. Но в этот механизм также включается IWPageProducer, возвращающий страницу как IWPageForm, а также такой элемент как IWModuelController. Вот как это выглядит на схеме:

 

 

 

HTTP-клиент

WEB-сервер

WebSnap- расширение

IntraWeb Page Mode- приложение

 

 

IntraWeb-часть такого приложения не порождает отдельного потока и работает в потоках, порожденных WebBroker или WebSnap-кодом. В этом радикальное отличие  модели от Stand Alone Application, в которой каждый поток связан с конкретной пользовательской сессией или, иначе говоря, с окном браузера. Поговорим об этом подробнее.

 

 

Отличие от режима Application.

 

В режиме Stand Alone Application запрос браузера порождает сессию в отдельном потоке, который создан и существует, пока данная сессия активна. Методы завершения сессии описывались ранее – это истечение времени time out или выполнение метода Terminate для объекта Application. Все это сильно напоминает работу в среде клиент-сервер, когда для каждого пользователя создается отдельный экземпляр клиентского приложения и отдельное подключение к базе данных, сохраняемое в течение всей сессии.

Работа в среде WEB вообще строится немного иначе. Поток, порожденный текущим запросом, после обработки модулем ISAPI удаляется из памяти сервера. Поддержка состояния на клиентской стороне требует в этом случае отдельного программирования или использования уже готовых программных структур, как в случае совместного использования IntraWeb и WebSnap.

 

 

Выбор между режимами Application и Page Mode.

 

Вопрос о том, какой подход использовать для создания IntraWeb-проекта, Application или Page Mode, в основном решает метод обработки пользовательской сессии. Там, где требуется полное управление пользовательской сессией и слежение за состоянием бизнес-объекта в процессе работы, форма Application mode предпочтительна.

С другой стороны, работа WEB-сайта с независимыми страницами ("Новости", "Форум", "Консультации" и так далее) не требует контроля сессии в полном объеме. Пользователь посетил один раздел, перешел к другому, третьему,  но при такой структуре сайта нет необходимости следить за  этими переходами. Для разработки сайтов такого рода более подходит Page Mode - модель.

 

Область совместного применения IntraWeb и WebSnap.

 

 IntraWeb позволяет реализовать большую интерактивность, выделив страницы, реализующие диалог с пользователем, в Page-mode-приложения. Режим Page-mode очень хорошо интегрируется в приложения, написанные с использованием технологии WebSnap, появившейся в версии Delphi 6.0. Эта технология, прежде всего, направлена на автоматизацию стандартных процессов, происходящих при работе WEB-сайта:

 

·       Login Services. Загрузка пользователя производится специальным объектом загрузки. Этот объект регистрирует пользователя в соответствии с установленной моделью безопасности и следит за сроками действия разрешений на доступ к страницам.

·        User Management Services. Система поддерживает список пользователей со всей необходимой информацией о них (данных загрузки, предпочтениях  и так далее).

·        File Uploading Services. Это объект, автоматизирующий довольно сложный для программирования процесс загрузки файлов на сервер.

·       Access Rights. Объект производит контроль за правами доступа как стандартными средствами, установленными в Windows, так и разработанными специально.

·        File Management Services. Этот объект облегчает просмотр содержимого произвольного файла, хранящегося на сервере. Автоматизирует процесс контроля логических путей на сайте и физических на диске.

·       Server-side Scripting. Поддерживаются скрипты JavaScript, VBScript или другие ActiveScrip-языки. Скрипты на серверной стороне являются связующим звеном между скомпилированным Delphi-кодом и логикой, имеющейся на странице сайта.

 

 Прежде, чем мы изучим пример использования WebSnap совместно с IntraWeb, давайте вкратце рассмотрим технологии программирования для WEB и их эволюцию в Delphi.

 

 

1. История вопроса.

 

 

Возможность динамического формирования ответа сервера была впервые реализована с использованием CGI. Однако повышение интерактивности сайтов в этих рамках давалось ценой все возрастающих  усилий не только программистов, WEB-дизайнеров и инженеров, но и администраторов баз данных  и COM/CORBA-разработчиков. Фирма Borland участвовала в создании средств интерактивной WEB-разработки самым активным образом. Причем основные усилия были направлены на создание оптимальной архитектуры для систем разработки. Основными технологиями разработки WEB-приложений под Delphi на сегодняшний день являются

 

·       WEB broker

·       WEB Snap

·       WEB Services

 

Технология WEB Broker была первой попыткой фирмы Borland (Delphi 4.0) представить инструментарий для разработки WEB-приложений. Модули, созданные в рамках WEB-Broker, работали либо как CGI-приложения, либо как ISAPI-расширения стандартных WEB-серверов. Эффективность программирования была на уровне языков PHP, а о RAD-разработке не шло речи вообще – эта технология была и остается полностью не визуальной. Но развитие Delphi продолжалось и в версии 6.0 появилась технология WEB Snap. WebSnap максимально эффективна для работы с IntraWEB, поскольку эта технология способна поддерживать несколько разрабатываемых WEB-модулей, вызывать методы и свойства принадлежащих им объектам посредством скриптов, отделять WEB-дизайн, сохраненный в CSS и HTML-файлах от кода, хранящегося в серверных DLL-библиотеках. В DataSnap методы обработки бизнес-кода проекта и  методы поддержки архитектуры WEB-сервера разделены. Это разделение достигается  при помощи WEB-модулей следующих типов:

 

·       WebDataModule - аналог модуля данных в Delphi. Хранит невизуальные компоненты, доступные всем формам проекта. Содержимое модуля не отображается в режиме run-time.

·       WebPageModule – модуль, содержащий компоненты для отображения одной HTML-страницы сайта. Является контейнером для этих компонентов, поскольку вид страницы определяется HTML-шаблоном, хранящемся в файле с аналогичным расширением.

 

 

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

Итак, WEB Snap – это попытка предложить разработчикам автоматизацию процесса создания WEB-сайтов, прежде всего решающих типовые задачи.  Прежде чем анализировать работу WebSnap+IntraWeb проектов, рассмотрим вопрос об организации отладки серверных DLL-расширений.

2. Способы отладки ISAPI DLL-расширений сервера IIS.

Отладка ISAPI DLL-приложений перестала быть тем кошмаром, которым она была еще недавно в ранних версиях Delphi, когда, например, одной из рекомендаций был перезапуск WEB-сервера для каждой отладочной сессии. В Delphi 6 Professional и Enterprise появился встроенный отладчик Web App Debugger, работающий как COM-сервер. Кроме использования этого средства мы еще подробно рассмотрим отладочные компоненты Windows NT/2000, зарегистрированные в службах этой ОС.

2.1. Web App Debugger.

Программа Web App Debugger доступна в IDE Delphi в позиции меню Tools и работает как WEB сервер с использованием порта 1024 по умолчанию. Передача запроса отлаживаемому приложению построена на COM-технологии. Программа собирает статистическую информацию по запросам и обеспечивает отображение справок по ним.

Как только отработает мастер по созданию WEB-приложения (путь File|New|Other|WebSnap|Application),

 Delphi создаст пустую форму, содержащую в себе код  регистрации OLE-сервера и его GUID. Эту информацию включает в себя отладчик, предоставляя OLE-сервер для выбора в процессе отладки. Подробнее об этом процессе можно прочесть, например, в документации по Delphi и других источниках [1]. Для отладки таким способом уже имеющегося приложения (что мы и будем делать в дальнейшем c примерами IntraWeb) нужно создать программу именно такого типа, какой мы собираемся отлаживать. Затем удалить WEB-модуль, добавить вместо него имеющийся, добавить строку настройки свойства WEBModuleClass объекта WEBRequestHandler и сделать еще много чего. Это неудобно, но зато не требует установки и запуска IIS!

Продолжим. В проекте установим точку останова в каком-либо модуле и запустим приложение Tools|Web App Debugger. Появится окно сервера с кнопкой Start. Нажмем эту кнопку и перейдем по ставшей активной ссылке на сервер:

Выберем из списка нужный COM-сервер с именем MyApp1  и нажмем кнопку Go. Запустится WEB-браузер и сработают возможно установленные в программе точки останова.

 

 

Процесс отладки с помощью Web App Debugger начался. Этот путь достаточно прост и эффективен, но в случаях, когда использование сервера IIS необходимо, например, для оценки реальной работы сайта, существует еще один метод.

2.2. Отладка при помощи компонентов, зарегистрированных в службах.

Этот вид отладки требует работы на вашей машине IIS версии не ниже 5.0. Он также достаточно прост и эффективен для Delphi-приложений и также использует технологию COM. На вашем компьютере должна функционировать MS Windows 2000 Professional или Server и MS Distributed Transaction Coordinator. Перейдем в список сервисов (Administrative tools|Services) и активизируем MS DTC:

Если старт MS DTC закончится неудачей, проинициализируйте log-файл для этой системы

Run>Msdtc -resetlog

и повторите процедуру старта.

Теперь создадим виртуальную директорию IIS, например, с именем IWGuess, ссылающуюся на физический путь, по которому расположен пример GuessWB или любой другой из представленных в разделе /Demos/IntraWeb (Administrative tools|Personal Web Manager|Add Virtual Directory, не забудьте включить "галочку" Execute для директории):

Вызовем свойства (Administrative tools|Internet Services Manager|Default Web Site) этой директории и установим параметры как показано на скриншоте:

 

Обратите внимание, что свойство Application Protection равно значению Isolated. Это означает, что приложение GuessWB.DLL будет выполняться под управлением вновь созданного COM+ приложения в отдельном процессе. Кроме параметра Application Protection в этом окне изменено свойство Local Path и Application Name. Значение "GuessWB.dll" в позиции Application Name не имеет к исполняемому модулю никакого отношения и носит мнемонический характер. Можно вообще оставить это поле пустым.

COM+ приложения могут рассматриваться как компоненты, включающие в себя код авторизации, поддержку транзакций и многое другое. Это более широкий взгляд на то, что мы делаем сейчас, но тем не менее, воспользуемся технологией работы Windows с компонентами COM+ и рассмотрим свойства нашего компонента, как показано ниже:

Выберем позицию меню Properties и на закладке Identity установим Interactive User - the current logged on user, чтоб не вводить в процессе отладки никаких паролей.

Кроме того, с закладки General возьмем GUID для COM+ приложения (например, в ClippBoard) для последующего использования в среде Delphi.

Перейдем в Delphi IDE, загрузим проект GuessWB. В командной строке запуска установим:

 

Dllhost.exe - это Windows-приложение, в адресном пространстве которого выполняется COM+ или создается его контекст. Идентификатор COM+ компонента указан в строке Parameters.

Установим точку останова, например, при нажатии кнопки butnGuess, запустим приложение и отдельно окно WEB-браузера с URL http://100.100.100.100/iwguess/guesswb.dll/guess (здесь указан тестовый IP-адрес). При нажатии на кнопку, в среде Delphi IDE происходит остановка:

Если в момент остановки вам доступно окно Component Services, обратите внимание на анимацию соответствующей пиктограммы: шарик вращается - значит COM-приложение работает. Завершить проект можно, например, нажав Ctrl+F2, а останавливать COM-приложение (что не всегда одно и то же) - путем выбора позиции ShutDown в меню компонента при включенной анимации.

3. Пример WebSnapServey.

После того, как мы решили проблемы, связанные с отладкой ISAPI DLL, перейдем к основной цели главы - рассмотрению примера IntraWeb Page Mode - приложения. В поставке Delphi имеется пример WebSnapServey (…Delphi7\), позволяеющий разобраться в следующем:

  1. Как осуществляется интеграция IntraWeb и WebSnap.
  2. Как используется  IntraWeb Page Mode.
  3. Как используются  сессии WebSnap, управляемой IntraWeb-компонентом.
  4. Как осуществляется  аутентификации пользователя средствами WebSnap.
  5. Как примененять IntraWeb для создания интерфейса страницы.

Зарегистрируйте COM+ компонент для отладки примера, как описано выше, и запустите его на выполнение. Почти весь проект состоит из взаимодействия компонентов WebSnap и Web-форм, подробное объяснение методов работы с которыми выходит за рамки данной главы. Если читатель недостаточно знаком с платформой WebSnap, отсылаем его к документации по Delphi и другим многочисленным источникам.[2]

 

Подробно проанализируем работу проекта.

Добавленный в проект TIWModuleController включается в механизм обработки запросов WebSnap. Этот компонент напрямую наследуется от TComponent и экспонирует интерфейс IWebDispatch. Для обеспечения работы  TIWModuleController  в проект включен также и TWebDispatcher, располагающийся на закладке Internet палитры компонентов.

            На этапе разработки демонстрационного примера авторами в проект были добавлены WebSnap Page-модули:

Обратите внимание, что затем компоненты TPageProducer удалены и заменены на TIWPageProducer (с закладки IntraWeb). Вот результат:

Этот IW-продюсер будет "продуцировать" в примере IntraWeb-форму, которая создается в проекте с использование закладки IntraWeb: File| New| Other| IntraWeb| Page Form. Продюсер IW-формы обрабатывает только одно событие OnGetForm. Определим обработчик события так, чтобы продюсер "знал" с какой IW-формой он будет работать:

procedure TPage1.IWPageProducer1GetForm(ASender: TIWPageProducer;
  AWebApplication: TIWApplication; var VForm: TIWPageForm);
begin
  VForm:=TformMain.Create(AWebApplication)
end;

 

При появлении ошибки трансляции, связанной с этим кодом, проверьте наличие объявлений модулей  IWApplication и IWPageForm в строке uses.

Запустим проект на выполнение (пароль и логин для загрузки страниц проекта один и тот же: test). В момент обработки события продюсера создается один экземпляр IW-формы для каждой WEB-страницы, как это и принято в WebSnap. При голосовании на странице formPage1 пользователь нажимает кнопку Vote. Начинается  обработка события OnClick и приложение производит анализ введенной информации. Поскольку работа этой части кода имеет принципиальное значение, приводим полностью соответствующий фрагмент.

 

 

procedure TformPage1.butnVoteClick(Sender: TObject);

var

  LBest: TSTMovie;

  LWorst: TSTMovie;

begin

  LBest := miMotionPicture;

  LWorst := miMotionPicture;

  if cmboBest.ItemIndex = -1 then begin

    textMsg.Lines.Text := 'Please select a choice for best Star Trek movie.';

  end else if cmboWorst.ItemIndex = -1 then begin

    textMsg.Lines.Text := 'Please select a choice for worst Star Trek movie.';

  end else begin

    LBest := TSTMovie(cmboBest.Items.Objects[cmboBest.ItemIndex]);

    LWorst := TSTMovie(cmboWorst.Items.Objects[cmboWorst.ItemIndex]);

    if LBest = LWorst then begin

      textMsg.Lines.Text := 'Sorry - but you cannot pick the same movie for best and worst.';

    end else begin

      if WebContext.Session.Values['Confirm'] <> 'Y' then begin

        if LBest = miFinalFrontier then begin

          textMsg.Lines.Text := 'Ugh. The Final Frontier was trully horrid. Are you sure that is'

           + ' your choice for best?';

          butnVote.Caption := 'Vote with my questionable choice anwyays';

          WebContext.Session.Values['Confirm'] := 'Y';

        end else if LBest = miVoyageHome then begin

textMsg.Lines.Text := 'Good choice! The Voyage home was good wasn''t it?';

butnVote.Caption := 'Record my vote!';

WebContext.Session.Values['Confirm'] := 'Y';

        end;

      end;

    end;

  end;

  textMsg.Visible := textMsg.Lines.Count > 0;

  if not textMsg.Visible then

     begin

RecordVote(LBest, LWorst);

ProduceResponse := False;

DispatchPageName('PageResults', WebContext.Response, []);

     end;

end;

 

Строки  в конце обработчика выделены для упрощения ссылок на них. Если в процессе голосования возникают какие-либо замечания к заполнению полей, отображается  элемент формы textMsg, содержащий текст замечания. В этом случае выделенные строки не выполняются. Форма передается клиенту как ответ сервера и мы видим её же в окне браузера. Это происходит потому, что:

 

1.     свойство IWPageForm-формы ProduceResponse=TRUE (по умолчанию) и форма передается;

2.     свойство формы PostToSelf=TRUE - данные отправляются в качестве ответа самой же форме. Заметьте, что свойство формы AutoProcess установлено в TRUE (это значение по умолчанию), что позволяет автоматически обрабатывать значения HTTP-элементов формы, а также их состояние.

При отключенном параметре AutoProcess=FALSE жать на кнопку Vote бесполезно - событие formPage1.butnVoteClick(Sender) даже не будет вырабатываться. В этом случае submit-компонент (кнопка) формы не будет автоматически обнаруживаться. А вот для формы formResults, на которой отображаются результаты голосования в виде чарта, это свойство должно быть отключено (AutoProcess=FALSE), ведь там нет submit-компонентов и она должна быть передана диспетчеру страниц без их анализа.

 

 

Если же голосование проведено без замечаний, помеченный код выполняется. При этом:

 

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

2.     Значению ProduceResponse присваивается значение FALSE, запрещающее передачу формы в качестве ответа сервера.

3.     Вызывается процедура DispatchPageName, которая, используя интерфейс IPageDispatcher, указывает диспетчеру страниц проекта, что нужно в качестве ответа WebSnap-приложения WebContest.Response использовать страницу с именем "PageResults". Далее этот ответ будет передан WEB-серверу, который отошлет её клиенту. Клиент увидит в окне браузера чарт с результатами голосования.

 

Такова схема работы проекта. Возникает вопрос: почему результаты голосования записываются с применением потокозащищенного кода, а, например, при рисовании на полотне (canvas) формы formResults нет даже намека на потоки. Дело в том, что списки GVotesBest и GVotesWorst модуля Globals являются глобальными, доступ к которым осуществляется из разных "клиентских " запросов (сессий). Это требует защиты, реализованной в проекте в виде критических секций.

Процедура formResults.IWPageFormRender, рисующая на полотне, вызывается при выполнении DispatchPageName (последний оператор в выделенном фрагменте) и работает в рамках текущей пользовательской сессии WebContext.Session. В рамках данной пользовательской сессии определено и значение параметра Confirm, хранящего признак того, были ли высказаны пользователю комментарии относительно его выбора. Значения этому параметру  также присваиваются простым оператором без использования потоков:

 

WebContext.Session.Values['Confirm'] := 'Y';

 

 



[1] М. Канту. Delphi 6.0 для профессионалов. Изд. Дом Питер 2002

[2] М. Канту. Delphi 6.0 для профессионалов. Изд. Дом Питер 2002