Читая forum.xakep.ru я наткнулся на один интересный топик. Начинающий программист спросил: «Как сделать форум, интернет магазин на Delphi или на чём-то другом?!». Ответы меня удивили, хотя конечно и вопрос был несколько странно сформулирован. Тем не менее, именно средствам создания Web-приложений Borland всегда уделяла особое внимание. Не является исключением и такой, весьма популярный продукт этой компании, как Delphi. В его состав, в различных версиях, были включены такие достаточно мощные инструменты создания Web-приложений, как Web Broker, Web Snap и Web Services. Эти инструменты позволили разработчикам в полной мере использовать возможности Delphi для реализации бизнес логики в Web-приложениях. Тем не менее, при этом предполагается, что программист для создания сложных динамических страниц должен все же включать в свои приложения фрагменты кода, написанные на других языках (JScript или VBScript). Естественно, что далеко не каждый разработчик GUI-приложений обладает достаточными навыками создания и использования скриптовых конструкций. Вместе с тем в настоящее время, задача реализации полнофункционального Web-интерфейса для крупных информационных систем становится все более актуальной.
И вот, начиная с седьмой версии, Delphi пополнилась еще одним средством создания Web-приложений - IntraWeb от компании AtoZed Software. Об основах работы с этим продуктом я и хочу рассказать в статье.
Рассматриваемый продукт существенно упрощает процесс разработки, избавляя Delphi-программиста от необходимости внедрения в исходный код фрагментов, написанных на других языках программирования. Теперь Web-приложения можно разрабатывать, используя исключительно язык Delphi, при необходимости IntraWeb автоматически произведет конвертирование программных элементов в скрипты или HTML-код. Попробуем рассмотреть работу IntraWeb немного подробнее и выявить преимущества, которые дает эта технология.
IntraWeb поддерживает два режима разработки – режим приложения (Application Mode) и страничный режим (Page Mode). В страничном режиме, приложения могут создаваться в форматах ISAPI, Apache DSO, NSAPI, CGI, или Win-CGI. В режиме приложения – только в форматах ISAPI, NSAPI и Apache DSO. Несмотря на то, что страничный режим обладает несколько большей гибкостью, в рамках данной статьи остановимся на рассмотрении работы в режиме приложения, как более простом для изучения общих концепций IntraWeb.
Для работы нам понадобится браузер, поддержитвающий JavaScript, желательно IE версии 5.5 или старше. Сразу оговорюсь, что IntraWeb приложения поддерживают Netscape, Opera и другие браузеры. Однако при работе даже со стандартным HTML-кодом различные браузеры могут вести себя по разному. IntraWeb-приложения могут автоматически определять тип браузера, с которым работает пользователь. Тем не менее, зачастую, для того, что бы отображение было корректным, могут потребоваться дополнительные настройки приложения.
Для того чтобы создать новый проект выберем пункт меню File|New|Other и перейдем на закладку IntraWeb. Из множества предлагаемых вариантов выберем Stand Alone Application. Такое приложение будет являться самостоятельным сервером. Пользователь может обратиться к нему из браузера, набрав в командной строке соответствующий приложению
URL.
После выбора типа проекта необходимо указать директорий, в котором приложение будет сохранено. После того, как все вышеперечисленные действия выполнены, мы получим заготовку приложения. Заготовка включает в себя три модуля – IWProject, IWUnit1 и ServerController.
IWProject является, непосредственно, основным модулем проекта, выполняется инициализация приложения, а также подключаются формы, входящие в состав проекта. Как видно из приведенного ниже листинга, содержащего текст модуля IWProject, структура IntraWeb-проекта в принципе сходна со структурою обычного приложения.
program IWProject;
{PUBDIST}
uses
IWInitStandAlone,
ServerController in 'ServerController.pas' {IWServerController: TDataModule},
IWUnit1 in 'IWUnit1.pas' {formMain: TIWForm1};
{$R *.res}
begin
IWRun(TFormMain, TIWServerController);
end.
Существенным отличием является лишь то, что в данном модуле не производится создания форм проекта, как это происходит в обычном приложении. Вместо этого сразу вызывается процедура IWRun, которая является IntraWeb`овским аналогом метода Application.Run, используемого для запуска обычных приложений. Чуть позднее мы вернемся к рассмотрению этого вопроса, а пока обратимся к модулю
ServerController. Модуль ServerController должен входить в состав любого IntraWeb-проекта. Этот модуль позволяет настроить общие свойства приложения и определить особенности его поведения во время работы. Именно здесь обрабатывается каждая, вновь создаваемая сессия, при подключении пользователя к приложению.
Перейдя в редактор кода, мы увидим, что по умолчанию в модуль ServerController включено описание специального класса TUserSession. Разработчик может добавлять собственные атрибуты в структуру данного класса. Каждый пользователь IntraWeb-приложения, во время сессии будет обращаться к собственному экземпляру TUserSession. Соответственно, каждый описанный внутри класса атрибут так же будет иметь собственное значение. Для упрощения доступа к объекту используется функция UserSession. Так если описать объект:
TUserSession = class
public
Username: string;
Password: string;
end;
то в дальнейшем из любого модуля приложения можно будет вызвать синтаксическую конструкцию подобного вида:
UserSession.Username := 'Joe';
LPassword := UserSession.Password;
Именно таким образом разработчики IntraWeb рекомендуют организовывать глобальные переменные в приложении. Если же просто объявить их в секции public некоторого модуля, как это делается в обычных приложениях, то такие переменные будут общими для всех сессий, что, соответственно, может повлечь за собою конфликты, связанные с попыткой изменять их значения одновременно разными пользователями.
Теперь рассмотрим последний модуль, входящий в состав нашего проекта, - IWUnit1. В нем описывается форма formMain. Взглянув на Object Inspector, сразу становится ясно, что данная форма имеет существенные отличия от обычной формы приложения Delphi – TForm. Именно эта форма и является заготовкой главной страницы нашего приложения, и она должна отображаться в браузере. Попробуем разместить на форме несколько компонент из набора IW Standart – IWLabel, IWEdit и IWButton.
Что бы увидеть, как будет выглядеть только, что созданная форма в действии, запустим приложение на выполнение. В появившейся на экране форме нажмем первую слева кнопку (Launch selected browser and execute application). В окне браузера появится страница с размещенными на ней элементами управления, иными словами созданная нами форма теперь отображается как HTML страница. Чтобы в дальнейшем избежать подобной, относительно долгой процедуры запуска добавим для нашего приложения параметр “/LaunchBrowser”. Для этого используйте пункт меню
“Run|Parameters”.
Попробуем добавить в проект некоторую функциональность. Вернемся в режим редактирования приложения и напишем обработчик события OnClick для компонента IWButton1:
procedure TformMain.IWButton1Click(Sender: TObject);
begin
IWLabel1.Caption:=IWEdit1.Text;
end;
Нетрудно догадаться, что должно произойти. И действительно, запустив приложение можно увидеть, что при нажатии на кнопку метка IWLabel1 будет отображать тот текст, который введен в поле ввода IWEdit1.
В создаваемую форму можно добавить и фрагменты HTML кода. Разместив на форме компонент TIWText. По умолчанию данный компонент позволяет просто отображать на странице статический текст. Однако, если вы установите значение свойства RawText – true, а свойства WantReturns – false, то текст, занесенный с помощью Object Inspector`а в свойство Lines будет восприниматься приложением как код HTML.
Прежде чем перейти к рассмотрению работы с базами данных в IntraWeb, давайте рассмотрим механизмы взаимодействия между отдельными формами приложения.
Для того, чтобы добавить в наш проект еще одну форму активизируем пункт меню File|New|Other, перейдем на закладку IntraWeb и выберем Application Form. Сохраним полученный модуль на диске. Если после этого взглянуть на исходный код самого проекта (Project|View Source), то мы увидим, что формы, входящие в состав IntraWeb приложения не создаются автоматически, как это происходит в обычном приложении. Как уже говорилось ранее, в исходном коде нашего проекта отсутствуют строки инициализации форм подобные нижеследующей.
Application.CreateForm(TForm1, Form1);
Вместо этого создавать формы придется вручную. При нажатии на кнопку IWButton1 в нашем приложении будем открывать новую форму. Для этого добавим название модуля, в котором находится новая форма, в список используемых модулей для основной формы приложения. В секцию public вызывающей формы добавим следующее описание:
FNewForm:TFormMain1;.
Событие OnCreate обработаем следующим образом:
procedure TformMain.IWAppFormCreate(Sender: TObject);
begin
FNewForm:=TFormMain1.Create(WebApplication);
end;.
И, наконец, при нажатии кнопки вызовем новую форму, изменив код обработчика события OnClick:
procedure TformMain.IWButton1Click(Sender: TObject);
begin
FNewForm.Show;
end;
Запустив приложение, убедитесь, что при нажатии на кнопку IWButton1 браузер выведет на экран пустую страницу. Далее добавим на второю форму (formMain1) компонент IWLabel. Нашей задачей будет отображение текста, введенного в поле ввода IWEdit1. Для этого перед вызовом формы достаточно вставить строку следующего содержания:
FNewForm.IWLabel1.Caption:= IWEdit1.Text;
Таким образом, мы видим, что значения свойств размещаемых компонент можно передавать между формами IntraWeb-приложений без использования объекта TUserSession. Это происходит потому, что компоненты на формах являются членами классов самих IntraWeb форм, и, соответственно, инициализируются отдельно для каждой пользовательской сессии.
Теперь попробуем отобразить на главной странице приложения данные из таблицы. Как обычно, в таких случаях воспользуемся таблицей customer.db из базы данных DBDEMOS. Создадим новое Stand Alone with Data Module приложение. В DataModule1 поместим компоненты TDatabase, TTable, TSession и TDataSource. Установим для компонентов следующие свойства:
Свойство | Значение |
Session1 | |
AutoSessionName | True |
Table1 | |
DatabaseName | DBDEMOS |
TableName | customer.db |
DataSource1 | |
DataSet | Table1 |
На форме formMain разместим компоненты отображения данных IntraWeb – IWDBGrid, IWDBNavigator и несколько компонентов IWDBEdit. Свяжем эти компоненты с компонентами представления данных, подобно тому, как это делается в обычных проектах, присвоив значение «DataModule1.DataSource1» свойству DataSource. После того, как приложение запущено и в командной строке браузера набран соответствующий адрес, мы сможем увидеть страницу примерно следующего вида. При этом поведение страницы напоминает поведение обычного приложения, в котором свойство AutoEdit компонента DataSource имеет значение
false.
Вообще, мне достаточно редко попадались Web-страницы, позволяющие редактировать данные непосредственно в отображаемой таблице. Технически реализовать такую возможность непросто. Однако компонент IWDBGrid позволяет добиться такого эффекта. Я не буду подробно рассказывать, как это делается, при желании вы можете обратиться к демонстрационному примеру. Вместо этого хотелось бы немного подробнее рассмотреть поведение некоторых компонентов отображения данных. Так для формирования списков из набора данных в обычных приложениях достаточно часто используются компоненты DBLookupComboBox и DBLookupListBox. В том случае, если важно всего лишь осуществить выбор какого-либо значения, без занесения его в другой набор данных свойству DataSource значение не присваивается. Достаточно лишь определить свойства ListSource, ListField и KeyField. На мой взгляд, особенно удобно то, что при выборе конкретного значения из такого списка происходит, соответственно, изменение текущей записи, что дает возможность легко определить значение ключевого поля.
Компоненты IWDBLookupComboBox и IWDBLookupListBox, очевидно, не позволяют проделать подобную операцию. Для того, что бы получить значение ключевого поля выбранной записи приходится устанавливать значение свойства DataField.
При работе с данными стоит также обратить внимание на поведение сервера при нажатии кнопки “Back” браузера. Дело в том, что в этом случае может нарушаться синхронизация приложения, и пользователь получит сообщение примерно следующего содержания: «Вы попытались переслать или обновить данные со страницы, информация о которой уже не поддерживается серверным приложением. Попытка внести изменения будет проигнорирована. Вы будете синхронизированы с текущим местом приложения» (You have attempted to post or refresh data from a page that depends on information that is no longer available to the server application. Your attempted changes will be ignored. You will now be resynchronized to the current place in the application). После вывода данного сообщения приложение будет возвращено в то состояние, в котором оно прибывало до нажатия кнопки “Back”. Тем не менее, если возникает необходимость делать возврат на предыдущую страницу, то настроить поведение приложения при нажатии кнопки “Back” позволит изменение значения свойства .HistoryEnabled. Предупреждающее сообщение так же может быть отключено, если установить значение свойства .ShowResyncWarning -
false.
И все же, дабы лишний раз не искушать пользователя, я предпочитаю вызывать InterWeb приложения в отдельном окне браузера с отключенной командной строкой.
Как видно из рассмотренных примеров, использование IntraWeb технологии может заметно облегчить процесс написания Web-приложений. Delphi-программист в процессе разработки, образно выражаясь, попадает в родную среду, т.е. делает ту работу, которую он привык делать.
Кроме того, несмотря на то, что Web-приложения имеют множество неоспоримых преимуществ перед обычными, «настольными» приложениями, они далеко не всегда могут предоставить пользователю ту гибкость, которая может быть реализована в GUI-программах. Связано это, на мой взгляд, прежде всего с тем, что полнофункциональный Web-интерфейс организовать значительно сложнее. Разработчик серверных приложений должен затрачивать большое количество времени на написание необходимых элементов управления и их привязку к данным, либо максимально упрощать пользовательский интерфейс, что может привести к потере функциональности приложения. Возможно, появление IntraWeb в составе Delphi 7 и развитие этой технологии в трех следующих версия продукта, реально может поспособствовать решению этой проблемы и открыть много интересных технических решений.
Литература:
1. AtoZed Software. IntraWeb documentation.
2. AtoZed Software. Introduction to IntraWeb.
3. Материалы Borland Community Network. http://bdn.borland.com
4. Bob Swart. IntraWeb And ActiveForms. Delphi Magazine. Issue 102