А. Шуленин, Microsoft
Правилом хорошего тона при написании статей, прямо или косвенно затрагивающих тему Сети, стало введение, содержащее философский анализ природы данного общественного явления и причин столь взрывного роста его популярности. В силу априори ограниченного объема пространства и времени мы позволим себе отступить от этого правила и перейдем сразу к более прозаическим вопросам практики создания Internet/Intranet приложений для работы с Microsoft SQL Server.
Internet действительно неожиданно бурно ворвался в устоявшуюся жизнь разработчиков клиент-серверных приложений. Однако первоначальный шок довольно быстро прошел, как только наступило осознание нехитрого в общем-то факта, что структура Интернет/интранет приложений имеет много общего с традиционной платформой "клиент-сервер". Правильнее говоря, World Wide Web также основывается на клиент-серверной архитектуре. В самом деле, Web-браузер является типичным клиентским front-end'ом, основное отличие которого от клиентских мест, построенных с помощью Visual C++, Visual Basic, Visual FoxPro и других средств разработки, состоит в более гибко настраиваемой функциональности, которая может определяться даже во время выполнения программы. При этом не требуется ни перекомпиляции, ни переустановки модулей, что уже само по себе является нетривиальной задачей в больших и сложных клиент-серверных системах масштаба корпорации. Правда, первоначально браузеры использовались только как средства форматирования статического текста. Однако активно развивающийся в Internet бизнес вскоре перестал довольствоваться простой публикацией рекламы предприятия и справочной информации о его деятельности. Например, клиент имел полное право хотеть выбрать из рекламного проспекта фирмы понравившиеся ему образцы и совершить покупку. Подобно типичному интерфейсу клиентского приложения на VB, VFP и т.д., сценарий работы предполагал заполнение клиентом некоторой формы, населенной, вообще говоря, различными элементами управления, отправку соответствующего запроса на сервер и прием результатов обработки. Таким образом, требования бизнеса выдвинули на первый план принципы динамического взаимодействия браузера и Web-сервера внутри сессии, что заставило задуматься как об активной роли браузера, так и о расширении функциональности сервера по сравнению с простым хранением и пересылкой HTML-документов.
Первым способом повышения активности Web-страниц стали приложения Common Gateway Interface (CGI), поскольку спецификация CGI позволяет браузеру вызвать тот или иной исполняемый модуль или скрипт на Web-сервере, который мог обратиться с запросом к базе данных, построить в HTML-кодах страницу результатов и передать ее обратно Web-серверу, который же, в свою очередь, отсылал результаты браузеру. CGI-приложения могут содержать вызовы других программных (написанных, например, на С++) или командных (.bat, .cmd) файлов. С помощью CGI-cкриптов, а точнее на языке PERL (Practical Extraction and Reporting Language), построено немало интерактивных Web-приложений. К сожалению, каждый такой скрипт исполняется как иной, нежели Web-сервер, процесс, что быстро "съедает" ресурсы даже достаточно "навороченной" по сегодняшним меркам машины, особенно при большом количестве заходов на сервер.
Помимо исполнения CGI-скриптов, Microsoft Internet Information Server (MS IIS) предоставляет разработчикам возможность создания с помощью соответствующего API (ISAPI) приложений в виде dll, запуск которых происходит в ответ на команду или выбор линка на Web-странице. Каждое такое приложение выполняется в адресном пространстве Web-сервера, что, естественно, повышает скорость работы и существенно экономит машинные ресурсы. В зависимости от сложности сайта и приложений, dll могут быть предзагружены одновременно с запуском сервера, либо подгружаться/выгружаться из памяти по мере необходимости.
Целью настоящей статьи является рассказ о способах построения активных Web-страниц и средствах их взаимодействия с Microsoft SQL Server. К наиболее известным средствам разработки приложений на основе ISAPI относятся входящий в состав MS IIS Internet Database Connector (IDC), а также свободно распространяемый dbWeb. Кроме этого, мы рассмотрим простую, но достаточно мощную утилиту в составе самого MS SQL Server 6.5 под названием SQL Web Assistant. В завершение мы поговорим о развитии стратегии распределенных вычислений, компонентном подходе к созданию распределенных приложений и о концепции активных серверных страниц как наглядной реализации компонент доступа к MS SQL Server через Интернет/интранет. Позиционирование этих средств по шкале "сложность/функциональность" приводится на рис.1.
В состав Microsoft SQL Server 6.5 входит SQL Web Assistant (см.рис.2), с которого было бы целесообразно начать наше рассмотрение, так как это довольно простая в использовании утилита, не требующая знания HTML и серьезной практики работы с SQL. Web Assistant имеет интерфейс мастера (wizard), т.е. состоит из ряда последовательных форм с вопросами, отвечая на которые администратор может сэкономить время по выполнению рутинного HTML-кодирования и получить готовую (в HTML-кодах) страницу, содержащую результаты опубликования произвольного запроса к базе. Полученная страница не является активной в строгом смысле этого слова, так как публикуется при помощи push-метода (cм.рис.4), т.е. обновление происходит по инициативе сервера, и не допускает обновления со стороны клиента. Однако сервер может производить обновление (перегенерацию) страницы на триггерной основе или на основе расписаний задач под управлением SQL Executive. Мастер работает только с базами данных MS SQL Server и использует три хранимых процедуры sp_makewebtask, sp_runwebtask и sp_dropwebtask. При необходимости они могут использоваться самостоятельно в кодах T-SQL.
Рассмотрим следующий простой пример. Пусть мы имеем некоторую базу данных MS SQL Server, содержащую таблицу rates с курсами валют.
id | kod | kurs |
1 | Валюта 1 | 1000.00 |
2 | Валюта 2 | 2000.00 |
3 | Валюта 3 | 3000.00 |
4 | Валюта 4 | 4000.00 |
5 | Валюта 5 | 5000.00 |
6 | Валюта 6 | 6000.00 |
7 | Валюта 7 | 7000.00 |
8 | Валюта 8 | 8000.00 |
9 | Валюта 9 | 9000.00 |
Мы хотим публиковать на Web оперативные данные об изменении курсов, как только таковые будут иметь место. Для этого мы определяем задачу публикации:
sp_makewebtask @outputfile = 'c:\rates.htm', @query = 'select kod, kurs from rates', @procname=web_rates,@resultstitle = 'Курсы валют', @URL = "http://www.microsoft.com", @reftext = 'Microsoft Home Page', @whentype=9
Практически все значения параметров здесь интуитивно понятны. В пояснении нуждается только последний @whentype, который означает, что страница должна быть создана сразу по выполнении данного оператора, а также в дальнейшем по мере поступления запросов. Полный перечень параметров процедуры и их назначение приводится в руководстве по языку T-SQL.
Далее мы можем определить триггер на все виды транзакций в таблице rates:
if exists (select * from sysobjects where id = object_id('dbo.tr') and sysstat & 0xf = 8)
drop trigger dbo.tr
go
create trigger tr on dbo.rates for insert,update,delete
as exec sp_runwebtask @procname=rates
go
Теперь любое изменение в таблице rates вызовет обновление страницы c:\rates.htm. В своей презентации на выставке UnixExpo'97 я немного усложнил задачу и посылал запрос на MS SQL Server по электронной почте непосредственно в теле письма с темой SQL.
update rates set kurs=kurs+100 where id=1
На MS SQL Server в этот момент была запущена утилита SQLMail, обеспечивающая взаимодействие с электронной почтой, и хранимая процедура
sp_processmail @subject='SQL', @dbuse='db_rates', @set_user='dbo',
смысл которой состоял в том, чтобы сканировать содержимое ящика входящих сообщений, выбирать из них непрочитанные с темой SQL и передавать содержащийся запрос на выполнение MS SQL Server. Как только письмо поступало, запрос обрабатывался и триггер инициировал обновление соответствующей страницы.
Microsoft dbWeb представляет собой шлюз между 32-битными ODBC-ресурсами, в качестве которых могут выступать, например, Microsoft SQL Server, Microsoft Access, Microsoft Visual FoxPro, Oracle и т.д., и MS IIS. dbWeb предусматривает создание схемы, содержащей описание данных и связанных с ними Web-страниц. Он поддерживает исполнение запросов в реальном режиме времени на основе "pull"-модели публикации, позволяя тем самым создавать активные Web-страницы.
Microsoft dbWeb структурно состоит из двух основных компонент: dbWeb Service и dbWeb Administrator (cм.рис.5). dbWeb Service является типичным ISAPI-приложением, которое обрабатывает пользовательские запросы, направляемые посетителем страницы через браузер, и управляет соединениями между браузером, ODBC-ресурсом и IIS. К функциям dbWeb Administrator относится создание HTML-страниц, содержащих результаты выполнения запросов на основе уже упоминавшихся схем, с помощью которых осуществляется управление публикуемыми данными. Схемы определяют сам запрос и структуру страниц. При этом не требуется знания HTML или ISAPI, так как в состав dbWeb Administrator входит интерактивный мастер-построитель схем (Schema Wizard), который в традиционной для любой программы-мастера манере позволяет задать поля поиска по методу Query-by-Example (QBE), выбрать поля для отображения в таблице страницы результатов и определить переходы из списка записей в отдельные страницы, содержащие развернутую информацию по текущей записи. Настройкой соответствующих свойств можно разрешать или запрещать операции вставки, удаления и редактирования. Для проверки прав пользователя используется система безопасности той СУБД, к которой происходит доступ. dbWeb имеет в своем составе широкий спектр шаблонов страниц, которые при необходимости могут быть легко откорректированы и настроены разработчиком для более полного соответствия его задачам. Таким образом, dbWeb не является конечным пользовательским приложением. Скорее его можно охарактеризовать как достаточно легкий в использовании инструментарий разработки, который, как всякий мастер, не поддерживает языка программирования и оттого, на мой взгляд, несколько проигрывает в функциональности рассмотренному нами ранее SQL Web Assistant, несмотря на возможность инициируемого посетителем обновления информации в базе. Тем не менее, эта программа успешно справляется с автоматизацией большинства рутинных операций по организации соединений и публикации данных из БД и покрывает, по разным оценкам, порядка 40-60% потребностей бизнеса среднестатистической фирмы при организации доступа к своим источникам данных через Internet. dbWeb является свободно распространяемым приложением и может быть установлен с Microsoft Technet, Windows NT Resource Kit или непосредственно с www.microsoft.com.
IDC является другим примером достаточно давно и успешно используемого ISAPI-приложения. Он входит в состав MS IIS. С помощью вызовов функций ODBC API IDC обеспечивает прямую связь между полями HTML-формы и соответствующим ODBC-достижимым источником данных, например, базой данных MS SQL Server, без необходимости написания замысловатых CGI-скриптов. Схема работы IDC показана на рис.6.
Для доступа к данным и публикации на Web IDC использует файлы двух типов- .idc и .htx. Файл с расширением idc содержит всю необходимую информацию о соединении с источником данных, текст запроса, а также ссылку на соответствующий htx-файл. Файл с расширением htx служит шаблоном страницы, на которой будут опубликованы данные из базы, а также элементы оформления в виде статического текста, графики, видео и т.п.
MS IIS распознает расширение .idc как вызов httpodbc.dll, которая считывает http-заголовки из управляющего блока ISAPI для определения параметров запроса. Httpodbc.dll читает и разбирает idc-файл, указанный в URL. Имя источника, имя пользователя, пароль и пр. используются для подключения к соответствующему ресурсу ODBC, после чего httpodbc передает на выполнение SQL-запрос и получает результаты. Результаты используются для наполнения заготовки в виде htx-файла, после чего полученный HTML-документ MS IIS передает браузеру. Описанная последовательность действий иллюстрируется на рис.7
Продолжим развитие нашего простого примера из п.2 средствами IDC. Опубликуем таблицу rates с помощью файлов rates.idc и rates.htx
Rates.idc:
Datasource: rates
Template: rates.htx
SQLStatement: select id,kod,kurs from rates
Username: sa
Rates.htx:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 2.0">
<title></title>
</head>
<body>
<p><font size="5"><strong>Курсы валют</strong></font></p>
<table border="1">
<tr>
<th><font face="Times New Roman CYR">Код</font></th>
<th><font face="Times New Roman CYR">Курс</font></th>
</tr>
<%begindetail%> <tr>
<td><a
href="http://ntalexejs/aaa/rates_edit.idc?id1=<%id%>"><font
face="Times New Roman CYR"><%kod%></font></a></td>
<td><font face="Times New Roman CYR"><%kurs%></font></td>
</tr>
<%enddetail%></table>
</body>
</html>
Попутно заметим, что Microsoft FrontPage предоставляет удобный редактор для построения заготовок и программу-мастер для генерации idc-файлов. Результат показан на рис.8.
Предположим, по ссылке мы хотим предоставить возможность редактирования текущего курса валюты. Тогда соответствующая пара файлов может выглядеть следующим образом:
Datasource: rates
Template: rates_edit.htx
SQLStatement: select id, kod, kurs from rates where id=%id1%
Username: sa
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<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>
<p> </p>
<form action="rates_submit.idc?kurs1=<%txtKurs%>&id1=<%id%>"
method="POST" name="rates_edit"
<%txtkurs%>"&id1="<%id%>"">
<p><font face="Times New Roman CYR">Код валюты- <strong><%kod%></strong>
</font></p>
<p><font face="Times New Roman CYR">Курс <input
type="text" size="20" name="txtKurs" value="<%kurs%>"></font></p>
<p><input type="submit" name="B1"
value="Передать изменения"></p>
</form>
</body>
</html>
Результат приводится на рис.9. Далее результаты редактирования курса передаются обратно в базу данных, т.е. файл rates_submit.idc будет, очевидно, содержать оператор update, а соответствующий .htx- переход на новую страницу или возвращение обратно на просмотр списка и т.д.
Необходимо отметить, что соответствующий источник данных (в нашем случае rates) должен быть создан в ODBC-менеджере как системный, иначе он не будет виден другим пользователям.
Когда речь заходит о компонентах ActiveX, как правило, неявно подразумевается клиентская часть приложения. Microsoft Active Server Pages (ASP)- активные серверные страницы- представляют собой инструмент для эффективной разработки серверных Web-приложений, интегрирующих в своем составе HTML-код, VBScript и компоненты ActiveX. Это означает, что в уже существующие наработки легко могут быть встроены фрагменты кода на VBScript или JavaScript, а также вызовы соответствующих объектов ActiveX. Как, наверное, известно, VBScript- это сужение хорошо знакомого языка программирования Visual Basic на область создания Web-страниц. Основным идейным отличием VBScript от VB, на мой субъективный взгляд, служит то, что VBScript не содержит операторов файлового ввода-вывода и вообще средств прямого доступа к операционной системе (напрашиваются параллели, если Java сопоставить с С/С++, не правда ли). Кроме этого, в VBScript существует только один тип переменных- variant, отсутствуют декларативные константы и т.п. Наличие привычного синтаксиса языка высокого уровня существенно упрощает создание HTML-страниц. См. классический пример:
<HTML>
<BODY>
<% For i = 3 To 7 %>
<FONT SIZE=<% = i %>>
Hello World!<BR>
<% Next %>
</BODY>
</HTML>
Кроме этого, в состав среды активных серверных страниц (ASP Framework) входят следующие 5 основных встроенных объектов.
Подробнее узнать о назначении и использовании объектов ASP, их методах и свойствах можно, обратившись к документации, например, Active Server Pages Roadmap.
Помимо базовых объектов, ASP поддерживают многочисленные компоненты ActiveX, которые упрощают создание и значительно повышают функциональность активных Web-страниц. К ним относятся различные элементы управления, компоненты, создающие содержание приложения, компоненты ввода/вывода в файл (чего, как мы помним, не было в VBScript) и многие другие. Но нас в первую очередь будут интересовать компоненты, позволяющие организовать доступ к базам данных, или Active Data Objects (ADO).
В отличие от хорошо известных Data Access Objects (DAO) или Remote Data Objects (RDO) ADO имеют менее иерархически строгую структуру (см.рис.10) и потому более удобны при работе с базами данных.
Например, публикация нашей таблицы с курсами валют при помощи ASP и ADO может быть выполнена следующим образом.
Ratesado.asp
<% if IsObject(Session("conn")) then
set c=Session("conn")
else
set c=Server.CreateObject("ADODB.Connection")
c.Open "rates","sa",""
set Session("conn")=c
end if
set RS=c.Execute("select * from rates")%>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 2.0">
<title>Курсы валют</title>
</head>
<body>
<p><font size="5" face="Times New Roman CYR"><strong>Курсы
валют</strong></font></p>
<table border="1">
<tr>
<th align="left"><font face="Times New Roman CYR">Код</font></th>
<th align="left"><font face="Times New Roman CYR">Курс</font></th>
</tr>
<% do while not RS.EOF %> <tr>
<td><% id1=RS("id") %> <a
href="http://ntalexejs/aaa/ratesado_edit.asp?id1=<%=id1%>"><%=RS("kod")%></a></td>
<td><%=RS("kurs")%> </td>
</tr>
<% RS.MoveNext
loop %></table>
</body>
</html>
Получим результат, аналогичный рис.7. Обратите внимание на передачу идентификатора соединения между разными скриптами с помощью переменных класса Session. Обновление курса валюты организуем следующим образом:
Ratesado_edit.asp
<%id1=Request.QueryString("id1")
RS=Session("conn").Execute("select kod,kurs from rates where id="&id1)
kurs1=RS("kurs")%>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-1251">
<meta name="GENERATOR" content="Microsoft FrontPage 2.0">
<title>Код валюты</title>
</head>
<body>
<form action="ratesado_submit.asp" method="POST" name="frm">
<input type="hidden" name="hid" value="<%=id1%>"><p>Код
валюты <strong><%=RS("kod")%> </strong></p>
<p>Курс<strong> </strong><input type="text" size="14"
name="txtKurs" value="<%=kurs1%>"><strong> </strong></p>
<p><input type="submit" name="B1"
value="Передать изменения"></p>
</form>
</body>
</html>
Приведенный код вполне может быть воспроизведен, и если он вдруг заработает , то мы получим страницу типа той, что изображена на рис.9. Наконец, запрос на обновление оформим как отдельный asp:
Ratesado_submit.asp
<%Session("conn").Execute "update rates set kurs=" & Request.Form("txtKurs") & "where id=" & Request.Form("hid")
Response.Redirect("ratesado.asp")%>
Последний оператор осуществляет автоматический переход на просмотр таблицы курсов. ADO являются универсальным инструментом доступа к данным. Вы можете без изменений использовать интерфейс ADO из данного примера при работе с базами данных на VB, Visual FoxPro и т.д. Наконец, с помощью ADO, в свою очередь, могут быть построены пользовательские компоненты, для обращения к серверу баз данных как со стороны "толстого" (Win32), так и со стороны тонкого (Internet Browser) клиента. Функции обеспечения целостности транзакций, сервисы безопасности и согласованной работы компонент в распределенном приложении может взять на себя Microsoft Transaction Server (cм.рис.11), но это уже тема совсем другого рассказа.