Создание Web-приложений с помощью C++Builder 5
Создание форм и обработка пользовательского ввода
Применение баз данных в Web-приложениях
Интерактивные формы для редактирования данных
Данная статья посвящена одной из неплохо зарекомендовавших себя технологий создания динамических интерактивных Web-сайтов — разработке CGI- и ISAPI-приложений. Будучи далеко не единственной технологией создания таких Web-сайтов, она тем не менее остается довольно популярной. В данной статье мы рассмотрим примеры создания CGI- и ISAPI-приложений, выполняемых под управлением Microsoft Internet Information Services, с помощью C++Builder 5. О других способах создания динамических Web-сайтов, например разработке ASP-приложений, вы можете прочитать в статье Сергея Трепалина «Создание серверных компонентов для ASP-приложений» на этом же CD-ROM.
Web-приложения (называемые также скриптами) представляют собой исполняемые файлы или библиотеки, выполняемые под управлением Web-сервера. Их назначение — в ответ на запросы пользователя динамически генерировать HTML-страницы, которые будут интерпретироваться Web-браузером.
Применение Интернета в широком смысле означает доступ к ресурсам, содержащимся в Сети. Любой ресурс Интернета однозначно идентифицируется с помощью адреса URL (Uniform Resource Locators), который можно ввести в соответствующем поле браузера либо выбрать, щелкнув мышью на гипертекстовой ссылке Web-страницы или другого документа. Примерами Интернет-ресурсов являются HTML-страницы, документы различных форматов, Java-аплеты, элементы управления ActiveX и другие файлы. Результат выполнения какого-либо приложения, управляемого Web-сервером, также является ресурсом Интернета, и если настройки уровня безопасности браузера позволяют использовать этот ресурс, он также будет интерпретирован браузером. Отметим, что приложения, выполняемые под управлением Web-серверов и являющиеся источником подобных ресурсов, способны обрабатывать параметры, содержащиеся в запросе пользователя, и результат их работы может зависеть от этих параметров.
Создать Web-приложение, динамически генерирующее подобные ресурсы (обычно HTML-документы), можно с помощью практически любого средства разработки — лишь бы оно позволяло создавать приложения для той операционной системы, в которой работает Web-сервер. Однако если вы хотите снизить трудозатраты, связанные с созданием таких приложений, то имеет смысл обратить внимание на средства разработки, позволяющие их минимизировать. С этой точки зрения довольно удачным выбором являются Borland Delphi 5 и Borland C++Builder 5 (редакции Enterprise и Professional), а также Delphi 4 и C++Builder 4 Enterprise, так как эти средства разработки содержат неплохие визуальные инструменты и компоненты для создания подобных приложений.
Рассматриваемые в настоящей статье примеры или их аналоги, если это особо не оговорено, можно создавать с помощью любого из перечисленных выше средств разработки. Сами примеры созданы с помощью C++Builder 5 Enterprise, но, думаю, пользователям Delphi не составит особого труда перенести их код на Object Pascal. Архив с примерами можно найти здесь.
Изучение разработки Web-приложений мы начнем с создания простейшего примера.
Простейшее Web-приложение
Для создания простейшего Web-приложения из главного меню среды разработки C++Builder выберем пункт File | New и в репозитарии объектов выберем пиктограмму Web Server Application (рис. 1).
Далее нужно выбрать тип приложения (исполняемый файл CGI или Win-CGI либо динамически загружаемая библиотека ISAPI/NSAPI DLL, представляющая собой функциональное расширение для Microsoft Internet Information Services или Netscape FastTrack). CGI-скрипт (CGI-Common Gateway Interface), будучи исполняемым файлом, запускается в отдельном процессе, в то время как ISAPI/NSAPI DLL (динамически загружаемая библиотека — выполняется в адресном пространстве Web-сервера. Поэтому ISAPI/NSAPI DLL требуют меньше ресурсов, чем CGI-скрипты. К тому же такие библиотеки после загрузки остаются в памяти сервера, что уменьшает время их отклика на последующие обращения к ним. Однако это мешает их отладке: после внесения в библиотеку каких-либо изменений необходим перезапуск Web-сервера. В связи с этим при разработке Web-приложений нередко сначала создается CGI-скрипт, который затем отлаживается, после чего на основе имеющихся модулей создается ISAPI/NSAPI DLL. Так мы и поступим: выберем опцию CGI Stand-alone executable и создадим Win32-консольное приложение для генерации HTML-документов. В результате получим объект TWebModule, напоминающий обычный модуль данных (рис. 2).
Рассмотрим, как работает Web-приложение. Если Web-сервер получает от браузера запрос, соответствующий спецификации CGI, он инициирует запуск CGI-приложения для его выполнения. Если запрос корректен, CGI-приложение обрабатывает его и генерирует HTML-документ, который отсылается Web-сервером обратно в браузер. Для обмена данными между браузером и сервером используется протокол HTTP (HyperText Transfer Protocol).
Когда Web-приложение получает HTTP-запрос, оно создает объект TWebRequest для представления запроса и объект TWebResponce для представления отклика, отправляемого в браузер пользователя. Затем оба объекта передаются объекту TWebModule (рис. 3).
Объект TWebModule содержит набор объектов TWebActionItems, хранящих информацию о том, как обрабатывать различные пользовательские запросы. Опознав запрос, он выбирает нужный из них и выполняет соответствующий обработчик события OnAction, обрабатывающий запрос и динамически генерирующий ответ, который передается Web-сервером в браузер пользователя.
Для того чтобы приложение было работоспособным, создадим хотя бы один объект TWebActionItem, реализующий отклик на пользовательский запрос. С этой целью из контекстного меню объекта TWebModule надо выбрать пункт Action Editor и нажать кнопку Add в появившейся форме. Далее можно установить свойства PathInfo и Default объекта WebActionItem1. Первое свойство является частью URL (Uniform Resource Locator) — полного описания доступа к ресурсу (рис. 4).
Свойство Default указывает, выполняется ли данный отклик, если параметр PathInfo в пользовательском запросе остался пустым (рис. 5).
Теперь создадим обработчик события OnAction компонента TWebActionItem:
void __fastcall TWebModule1::WebModule1WebActionItem1Action( TObject *Sender, TWebRequest *Request, TWebResponse *Response, bool &Handled) { AnsiString cont = AnsiString("<HTML><BODY><H3>Hello!</H3>"); cont = cont + AnsiString("<BR>"); cont = cont + AnsiString("<H2>Now is ") + TimeToStr(Time()) + AnsiString(" </H2>"); cont = cont + AnsiString("</BODY></HTML>"); Response->Content = cont; }
В этом обработчике события генерируется содержащая текущее время HTML-страница примерно следующего вида (рис. 6):
Сделаем одно небольшое, но важное замечание. Перед компиляцией такого приложения в С++Builder в опциях проекта следует отключить опцию Use dynamic RTL на странице Linker. Кроме того, стоит отключить и опцию Build with runtime packages на странице Packages либо поместить все эти библиотеки в тот же каталог, что и само приложение (рис. 7).
Дело в том, что запустить такое приложение из командной строки можно без проблем, при этом оно обращается к RTL и «пакетам», находящимся за пределами каталогов Web-сервера. Однако запустить его с помощью Web-сервера скорее всего не удастся — все эти файлы окажутся недоступны. В этом случае вместо ожидаемого результата выполнения приложения будет получено сообщение об ошибке примерно следующего вида:
CGI Error
The specified CGI application misbehaved by not returning a
complete set of HTTP headers. The headers it did return are: ...
Отметим, что при создании ISAPI DLL с использованием Delphi 4 или C++Builder 4 в такой библиотеке не должно быть «пакетов» — она обязательно должна состоять из одного файла.
После компиляции приложения можно сохранить полученный исполняемый файл в каталоге, предназначенном для Web-приложений (в случае MS Internet Information Services по умолчанию это каталог C:\Inetpub\scripts). Затем можно обратиться к приложению через Web-браузер, указав URL-приложения. Обратите внимание: внешнему пользователю, обращающемуся к созданному приложению через браузер, не видна (и не должна быть видна) структура каталогов компьютера, содержащего Web-сервер, — вместо этого ему следует вводить их псевдонимы. Такой подход к использованию каталогов Web-сервера необходим для обеспечения безопасности — внешний пользователь ничего не должен знать о файлах и каталогах компьютера, содержащего Web-сервер, кроме того что ему положено.
Запустив приложение, можно нажать кнопку Reload и убедиться, что текст в браузере меняется. Это значит, что страница генерируется динамически (рис. 8).
Из этого CGI-скрипта мы можем создать ISAPI DLL. Для этого следует создать новое Web-приложение в виде ISAPI DLL, удалить из него объект TWebModule, а вместо него добавить другой объект TWebModule из предыдущего проекта.
Создание форм и обработка пользовательского ввода
Отметим, что объект TWebModule существенно облегчает создание CGI-приложений, связанных с обработкой пользовательского ввода (например, в HTML-формах), заключающегося в изменении или добавлении данных. Типичными примерами таких приложений являются анкеты, которые в изобилии встречаются на многих Web-серверах. Дополним наше приложение такой анкетой.
Для отображения в браузере формы ввода данных пользователем создадим еще один компонент TWebActionItem (рис. 9):
Установим свойство Default вновь созданного объекта TWebAction равным True. Теперь добавим в WebModule1 компонент TPageProducer, назначение которого — генерировать HTML-документ на основе заранее заданного шаблона (рис. 10).
Для создания шаблона документа можно воспользоваться любым HTML-редактором, поддерживающим создание форм, например Microsoft FrontPage (рис. 11).
Исходный текст формы, представленной на рис. 11, имеет вид:
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <meta name="GENERATOR" content="Microsoft FrontPage 2.0"> <title>Untitled Normal Page</title></head> <body bgcolor="#FFFFFF"> <p> </p> <form method="GET"> <p>What is Your name?<font size="4"> <input type="text" size="20" name="T1"></font></p> <p>What is Your e-mail?<font size="4"> <input type="text" size="20" name="T2"></font></p> <p><font size="4"><input type="submit" name="B1" value="Submit"><input type="reset" name="B2" value="Reset"></font></p> </form> </body> </html>
Созданный документ можно сохранить в виде файла (и указать его имя в качестве свойства HTMLFile компонента TPageProducer). Можно также скопировать HTML-текст в буфер обмена и поместить его в редактор свойства HTMLDoc этого компонента.
Теперь создадим обработчик события OnAction сгенерированного нами компонента TWebActionItem2:
void __fastcall TWebModule1::WebModule1WebActionItem2Action( TObject *Sender, TWebRequest *Request, TWebResponse *Response, bool &Handled) { Response->Content=PageProducer1->Content(); }
Отметим, что в Delphi 5 и C++Builder 5 компонент TWebAction имеет свойство Producer, позволяющее непосредственно указать, какую именно HTML-страницу нужно генерировать при обращении. Это во многих случаях избавляет от необходимости создавать обработчик события OnAction данного компонента.
Сохранив проект, можно снова обратиться к нему с помощью браузера, указав значение PathInfo в URL (рис. 12):
Теперь осталось обработать пользовательский ввод, например, динамически сгенерировав страницу с введенными пользователем значениями. С этой целью добавим еще один компонент — TPageProducer (рис. 13): страницы, содержащей результаты обработки пользовательского ввода
В качестве значения свойства HTMLDoc вновь созданного компонента PageProducer2 введем следующий текст:
<html> <head> <title>Thank You!</title> </head> <body > <p>Dear <#T1>!</p> <p>Thank you for completing this form. We have included your e-mail address <#T2> in our mailing list. You will receive a lot of spam from us!</p> </body> </html>
Данный текст представляет собой шаблон документа. Он содержит специальные тэги, заменяемые в процессе формирования HTML-страницы строками, которые, в свою очередь, могут быть введены пользователем в созданную выше форму. В нашем случае это тэги <#T1> и <#T2>. Они представляют собой имена полей ввода в созданной ранее форме, в чем можно убедиться, просмотрев HTML-текст формы.
Для замены специальных тэгов следует создать обработчик события OnHTMLTag компонента PageProducer2:
void __fastcall TWebModule1::PageProducer2HTMLTag( TObject *Sender, TTag Tag, const AnsiString TagString, TStrings *TagParams, AnsiString &ReplaceText) { ReplaceText = Request->QueryFields->Values[TagString] + Request->ContentFields->Values[TagString]; }
Здесь Request — объект TWebRequest, сгенерированный приложением в результате пользовательского запроса. В свойстве QueryFields (объект TStrings) этого объекта содержатся имена параметров и значения, введенные пользователем, в виде Name=Value (реально они содержатся в переменной окружения QUERY_STRING, созданной Web-сервером, в виде Name1=Value1&Name2=Value2&…). Параметр TagString — строка, содержащаяся в тэге, подлежащем замене. Cвойство Values объекта TStrings используется, если строки, содержащиеся в этом объекте, представимы в виде Name=Value (что и происходит в данном случае).
Отметим, что если в тэге <form>, содержащемся в тексте формы, вместо метода GET указан метод POST, то вместо свойства QueryFields следует использовать свойство ContentField.
Теперь создадим еще один компонент TWebAction (со значением свойства PathInfo, равным /test3) для отображения страницы, сгенерированной с помощью PageProducer2, и добавим еще один обработчик события OnAction:
void __fastcall TWebModule1::WebModule1WebActionItem3Action( TObject *Sender, TWebRequest *Request, TWebResponse *Response, bool &Handled) { Response->Content=PageProducer2->Content(); }
Возникает вопрос: каким образом можно инициировать генерацию этой страницы после нажатия пользователем кнопки Submit в форме ввода? С этой целью следует описать реакцию на ее нажатие в HTML-тексте формы, то есть отредактировать свойство HTMLDoc компонента PageProducer1:
<form method="POST" action="http://mywebserver/scripts/formproc.exe/t3">
В параметре action указывается URL ресурса, предоставляемого при нажатии кнопки Submit. В данном случае это наше приложение со значением PathInfo, равным /test3 (естественно, имя Web-сервера, так же как и другие части URL, может быть другим).
Теперь можно снова скомпилировать и сохранить приложение. Обратившись к нему с помощью браузера и заполнив форму, нажмем на кнопку Submit. В результате получим страницу, сгенерированную динамически на основе введенных в форму данных (рис. 14):
Из этого CGI-скрипта, как и в предыдущем случае, можно создать ISAPI DLL.
Применение баз данных в Web-приложениях
Мы можем создать код, позволяющий добавлять записи в какую-нибудь таблицу, в созданный ранее обработчик события WebModule1WebActionItem3Action (и таким образом действительно получить простейший список рассылки). Для этого необходимо добавить некоторые из компонентов доступа к данным в WebModule1 и установить соответствующие свойства (рис. 15):
Перепишем созданный ранее обработчик события WebModule1WebActionItem3Action:
void __fastcall TWebModule1::WebModule1WebActionItem3Action( TObject *Sender, TWebRequest *Request, TWebResponse *Response, bool &Handled) { AnsiString CustName=Request->QueryFields->Values["T1"] + Request->ContentFields->Values["T1"]; AnsiString CustEmail=Request->QueryFields->Values["T2"] + Request->ContentFields->Values["T2"]; Table1->Open(); Table1->Append(); Table1->FieldByName("Name")->Value=CustName; Table1->FieldByName("E-mail")->Value=CustEmail; Table1->Post(); Table1->Close(); Response->Content=PageProducer2->Content(); }
Теперь наше приложение сохраняет пользовательский ввод в таблице базы данных. Чтобы убедиться в этом, можно скомпилировать, а затем протестировать приложение.
Мы рассмотрели простейший пример использования баз данных в Web-приложениях. Но, как правило, требуется публикация данных в Интернете и представление их в браузере. Для этой цели используются компоненты TDataSetTableProducer и TQueryTableProducer, получающие данные либо из компонентов TDataSet, либо c помощью запроса к базе данных и представляющие их в виде HTML-документа в табличном виде.
Для создания приложений, осуществляющих публикацию данных в Интернете, можно воспользоваться «мастером» DB Web Application Wizard со страницы Business репозитария объектов (рис. 16).
DB Web Application Wizard представляет собой последовательность диалоговых панелей, в которых следует выбирать базу данных, таблицу и публикуемые поля (рис. 17).
После заполнения всех форм мы получим компонент TWebModule, в который входят компоненты TTable (или TQuery), TSession и TDataSetPageProducer. Этого достаточно для создания простейшего приложения для публикации данных. Выглядеть оно будет примерно так, как показано на рис. 18.
Таблица, выбранная для этого примера (biolife.db из базы данных BCDEMOS), содержит графические поля. Рассмотрим варианты отображения их в таблице.
Один из способов решения этой проблемы — создание в таблице вычисляемого поля, содержащего соответствующий HTML-тэг со ссылкой на графический файл, полученный на основе изображения, извлеченного из соответствующей записи. Именно так мы и поступим. Кроме того, необходимо учитывать, что несколько человек могут обратиться к одной и той же таблице с разными запросами одновременно, поэтому конкретный пользователь не должен видеть в своем браузере изображения, которые ему не предназначены. Этого можно достичь, например, присвоив файлам с изображениями уникальные имена. Обработчик события OnCalcField для компонента Table1, реализующий этот прием, может выглядеть, например, так:
void __fastcall TWebModule1::Table1CalcFields( TDataSet *DataSet) { TDateTime DT = Now(); Word hour,min,sec,msec; DecodeTime(DT,hour,min,sec,msec); //Создадим уникальный ID, основанный на текущем значении времени UserID=IntToStr(hour)+IntToStr(min)+IntToStr(sec)+IntToStr(msec); //Создадим уникальное имя для файла с изображением int i=random(1000000000); AnsiString FileName=UserID+"_"+IntToStr(i)+".JPG"; //Save an image to a file TJPEGImage *JPG= new TJPEGImage; TPicture *P = new TPicture(); P->Assign(Table1->FieldByName("Graphic")); JPG->Assign(P->Graphic); JPG->SaveToFile(FileName); Table1Picture->Value="<IMG SRC='"+FileName+"'>"; &P->Free; &JPG->Free; }
Необходимо также сослаться на соответствующий h-файл:
#include <vcl\jpeg.hpp>
Видимо, приведенный выше код нуждается в некоторых комментариях. При написании предполагалось, что вероятность извлечения какого-либо изображения двумя пользователями одновременно в течение одной и той же миллисекунды ничтожно мала. В этом случае можно сгенерировать имена файлов извлекаемых изображений, комбинируя величину, основанную на значении времени с точностью до миллисекунды, со случайным числом, которое уникально для каждой записи в данном сеансе работы пользователя, но, к сожалению, не уникально для нескольких пользователей одновременно.
Может возникнуть вопрос: почему файл с графическим изображением не удаляется в обработчике события OnCalcFields? Дело в том, что изображение может быть загружено в браузер намного позже, чем приложение завершит свою работу (особенно если пользователь имеет доступ в Интернет по обычной телефонной линии с помощью модемного соединения). Это означает, что файлы с изображениями после окончания работы приложения должны храниться на жестком диске Web-сервера. Поэтому удаляться они должны другим приложением либо просто другим экземпляром того же самого приложения, запущенным позже. Пример кода, реализующего удаление ненужных файлов с графическими изображениями в предположении, что для загрузки всех изображений в браузер конкретного пользователя достаточно десяти минут, приведен ниже:
void __fastcall TWebModule1::WebModuleCreate(TObject *Sender) { //Delete old *.JPG files TSearchRec sr; if (FindFirst("*.JPG", faAnyFile, sr) == 0) { do { if (Double(Now())-Double(FileDateToDateTime(sr.Time))>0.00694) //10 минут - это примерно 0.00694 часть дня DeleteFile(sr.Name); } while (FindNext(sr) == 0); FindClose(sr); } //инициализируем генератор случайных чисел Randomize(); }
В обработчике события OnCrerate нашего объекта TWebModule удаляем все изображения, хранящиеся в каталоге Web-приложения более десяти минут, и инициализируем генератор случайных чисел.
Отметим, что каталог, в котором размещены файлы с графическими изображениями, должен быть доступен для чтения пользователями Интернета. Поскольку в нашем примере это тот же самый каталог, где находится исполняемый файл, не исключено, что для работоспособности этого приложения нужно внести соответствующие изменения в настройки каталогов Web-сервера — например, каталог Scripts Internet Information Services, где обычно помещают Web-приложения, по умолчанию такого разрешения не имеет. Однако с точки зрения безопасности более оправданно размещение файлов с изображениями в другом каталоге.
Наконец, щелкнем правой клавишей мыши на компоненте TDataSetTableProducer, выберем опцию Response Editor и изменим вид HTML-таблицы (рис. 19).
Можно, например, изменить свойства Cellpadding, Cellspacing, Border, BgColor HTML-таблицы, отвечающие за расстояние между ячейками, их цвет, толщину линий сетки. Кроме того, мы можем сгенерировать объекты THTMLTableColumn и изменить их свойства, что позволит установить свои правила отображения колонок таблицы и их заголовков.
Теперь можно сохранить, скомпилировать и протестировать приложение. Результат изображен на рис. 20.
Выполнение всех рассмотренных выше примеров возможно с помощью Delphi 5 и C++Builder 5 Enterprise и Professional, а также Delphi 4 и C++Builder 4 Enterprise. Пример, который будет рассмотрен в следующей части статьи, можно выполнить только посредством Delphi 5 и C++Builder 5 Enterprise, поскольку в нем использованы компоненты InternetExpress, отсутствующие в других версиях этих средств разработки.
Интерактивные формы для редактирования данных
Вернемся ненадолго к примеру, в котором реализована форма ввода данных в таблицу, содержащую список рассылки. Если при работе с подобным приложеним пользователь введет в какие-либо поля формы некорректные данные, узнает он об этом только после отправки данных формы на Web-сервер и получения результата их обработки. Иными словами, интерактивность данного приложения невелика.
Несколько иначе обстоит дело с более интерактивным Web-приложением, которое позволяет, как минимум, не обращаться к серверу для проверки соответствия введенных данных каким-либо банальным требованиям типа отсутствия букв в числовом поле, а также контролирует корректность введенных данных в момент, когда фокус ввода покидает данное поле, а не когда вся запись отправляется на сервер. Пути достижения этой цели известны, и наиболее распространенным из них является применение скриптовых языков (VBScript или JavaScript). Фрагменты кода на этих языках, содержащие логику проверки корректности данных, могут находиться в HTML-странице, и при отображении в браузере они интерпретируются им, позволяя произвести такую проверку без обращения к серверу. В этом случае наше CGI- или ISAPI-приложение должно «уметь» генерировать страницы, содержащие код на одном из этих языков.
В принципе, при наличии времени и знаний одного из скриптовых языков создать интерактивный аналог приведенных выше примеров не так уж сложно. Однако при наличии Delphi 5 или C++Builder 5 Enterprise добиться интерактивности можно более простым способом. Этот способ заключается в применении компонентов InternetExpress, которые предназначены для создания MIDAS-клиентов, являющихся Web-приложениями. Подобные приложения обмениваются XML-данными с браузерами, поддерживающими интерпретацию кода JavaScript. Подробности о MIDAS-приложениях подобного типа можно узнать из статьи «MIDAS3: новые возможности» (КомпьютерПресс, № 1’2000).
Отметим, что применение компонентов InternetExpress не ограничено только «истинными» MIDAS-приложениями с отдельным сервером доступа к данным — с помощью этих компонентов можно создать Web-приложение, являющееся обычным клиентом серверной СУБД. Однако подобное приложение более интерактивно, чем традиционное HTML-приложение, и ниже мы увидим, в чем это выражается.
Итак, создадим простейшее приложение, иллюстрирующее применение компонентов InternetExpress. В этом примере мы поместим MIDAS-сервер и MIDAS-клиент в одно и то же приложение. Для этого создадим новое CGI-приложение и поместим компоненты TTable и TDataSetProvider в объект TWebModule — они представляют собой «серверную» часть этого приложения. Теперь необходимо установить значения свойств DatabaseName и TableName компонента Table1 (например, BCDEMOS и Customers.db). Далее следует установить значение свойства DataSet компонента DataSetProvider1 равным Table1 — это означает, что компонент Table1 теперь доступен для будущих MIDAS-клиентов.
Теперь поместим в тот же самый объект TWebModule компоненты TXMLBroker и TmidasPageProducer, представляющие собой «клиентскую» часть нашегоWeb-приложения. Первый из них отвечает за получение пакетов данных от MIDAS-сервера, а второй — за генерацию Web-страницы, направляемой в браузер. В данном примере MIDAS-сервер находится внутри нашего же приложения, поэтому установим значение свойства ProviderName компонента XMLBroker1 равным DataSetProvider1, оставив свойство RemoteServer пустым (рис. 21).
Далее необходимо выбрать пункт Web Page Editor из контекстного меню компонента MidasPageProducer1. Этот редактор свойств позволяет указать, какие интерфейсные элементы для отображения и редактирования данных нужно отображать в браузере. Например, добавим в него компонент DataForm с вложенными в него компонентами FiedlGroup и DataNavigator. Установим значение свойства XMLBroker компонента FieldGroup1 равным XMLBroker1, а свойства XMLComponent компонента DataNavigator1 — FieldGroup1 (рис. 22).
Следующим шагом будет установка значения свойства IncludePathURL компонента MidasPageProducer1. Это URL, где наше Web-приложение должно найти JavaScript- и HTML-файлы, используемые для генерации Web-страниц. Файлы *.js и *.html следует скопировать из каталога Cbuilder5\Source\Webmidas в каталог, соответствующий этому URL.
Следует заметить, что каталог Inetpub\Scripts, являющийся по умолчанию каталогом для Web-приложений Microsoft Internet Information Services и, следовательно, потенциальным местом для размещения нашего Web-приложения, — не самое подходящее место для данных файлов. Дело в том, что по умолчанию файлы из этого каталога можно запускать на выполнение, но они недоступны для чтения. Поэтому нужно изменить настройки этого каталога или, что более предпочтительно, использовать другой каталог.
Наконец, следует создать объект TWebActionItem, установить значение его свойства Default равным true, а значение свойства Producer — MidasPageProducer1. Наше приложение готово.
Теперь можно сохранить проект, скомпилировать его и перенести исполняемый файл в соответствующий каталог Web-сервера. Результат выполнения данного приложения показан на рис. 23.
Теперь осталось рассмотреть, почему полученное приложение более интерактивно, чем приложение, результат выполнения которого изображен на рис. 12. Анализ поведения последнего приложения показывает, что оно позволяет редактировать одновременно несколько записей, перемещаться между ними, использовать кнопки Undo или Post, добавлять и удалять записи – и все это без обращения к Web-серверу. Только нажатие кнопки ApplyUpdates инициирует новый запуск Web-приложения для того, чтобы сохранить внесенные пользователем изменения в базе данных. Если внимательно рассмотреть текст Web-страницы, генерируемый этим приложением, можно увидеть фрагменты кода JavaScript, а также XML-данные, соответствующие содержимому таблицы или запроса (их объем можно ограничить свойством MaxRecords компонента TXMLBroker). Поскольку код JavaScript интерпретируется браузером, а все необходимые данные содержатся внутри Web-страницы, при перемещении по записям и их редактировании нет необходимости обращаться к Web-серверу, пока пользователю не потребуется новая порция записей из базы данных. Это означает, что InternetExpress-приложения более интерактивны, чем HTML-приложения.
Заключение
В данной статье мы рассмотрели создание наиболее часто встречающихся типов Web-приложений с помощью C++Builder. Изучили, как динамически генерировать Web-страницы, обрабатывать пользовательский ввод и сохранять его в базе данных, как публиковать данные в Интернете и организовать вывод графических изображений. Наконец, мы обсудили, как создать интерактивное Web-приложение для редактирования данных.
Следует заметить, что создание приложений подобного класса возможно с помощью не только средств разработки Borland, но и большинства других (Microsoft Visual Basic, Sybase PowerBuilder, Microsoft Visual FoxPro и т.д.). Названия классов, применяемых при генерировании таких приложений, могут быть иными, но основные принципы остаются примерно теми же, что и в приведенных примерах.
В заключение отметим, что CGI/ISAPI — не единственная технология создания Web-приложений, содержащих код, исполняемый на Web-сервере. В настоящее время все более популярной становится технология ASP (Active Server Pages), позволяющая включать результат выполнения серверного кода в Web-страницы. Подробнее об этом можно прочитать в других статьях, в частности в статье Сергея Трепалина «Создание серверных компонентов для ASP-приложений» на нашем CD-ROM.
КомпьютерПресс 2'2001