Версия для печати

Архив документации на OpenNet.ru / Раздел "Web мастеру, CGI, Perl, PHP, Apache" (Многостраничная версия)

Серверный JavaScript 1.4. Руководство.


Оригинал: pyramidin.narod.ru
Перевод: Александр Пирамидин
Вперёд | Индекс

Серверный JavaScript 1.4.
Руководство по Использованию.

Перевод выполнил Александр Пирамидин.
Прошу все замечания и предложения направлять по e-mail: a_pyramidin@yahoo.com


В этой книге рассматривается использование ядра и серверного JavaScript версии 1.4. JavaScript это созданный фирмой Netscape межплатформенный объектно-ориентированный язык скриптов (сценариев) для клиентских и серверных приложений.

Оглавление

Введение

Что Нового в Этой Версии?
Поддержка JavaScript 1.4
Изменения в Менеджере Приложений JavaScript
Что Вы Уже Должны Знать
Версии JavaScript
Где Найти Информацию о JavaScript
Обновление Предыдущей Версии
Обратная Совместимость с Предыдущими Версиями
Соглашения по Документам

Глава 1  JavaScript. Обзор.

Что Такое JavaScript?
Ядро, Клиентский и Серверный JavaScript
Ядро JavaScript
Клиентский JavaScript
Серверный JavaScript
JavaScript и Java
Отладка в JavaScript
Visual JavaScript
JavaScript и Спецификация ECMA
Соотношение Между Версиями JavaScript и ECMA
Документация JavaScript и Спецификация ECMA
JavaScript и Технология ECMA

ЧАСТЬ I. Разработка Серверных Приложений.

Глава 2  Введение

Архитектура Приложений JavaScript
Системные Требования
Информация о Конфигурации
Подключение Серверного JavaScript
Защита Менеджера Приложений
Настройка LiveConnect
Локализация Компилятора

Глава 3  Технология Разработки Приложений JavaScript

Основные Этапы Создания Приложения
Менеджер Приложений JavaScript
Создание Исходных Файлов Приложения
Компиляция Приложения
Инсталяция Нового Приложения
URL Приложения
Управление Доступом к Приложению
Модификация Приложения
Удаление Приложения
Старт, Остановка и Рестарт Приложения
Запуск Приложения
Отладка Приложения
Использование Менеджера Приложений для Отладки
Использование URL Отладки
Использование Функции debug
Публикация Приложения
Менеджер Приложений. Детали.
Конфигурация, Установки по Умолчанию.
За Кулисами

ЧАСТЬ II. Возможности Серверного JavaScript.

Глава 4  Быстрый Старт. Образец Приложения.

О Приложениях-Образцах Серверного JavaScript
Hello World
Что Делает Hello
Исходный Скрипт
Модифицирование Hello World
Hangman
Исходные Файлы
Отладка Hangman

Глава 5  Основы Серверного JavaScript

Что Делать и Где
Обзор Процессов Времени Выполнения
Серверный Язык. Обзор.
Прототипы
Использование
Окружение
Классы и Объекты
Внедрение JavaScript в HTML
Тэг SERVER
Обратные Кавычки
Когда Использовать Эту Технику?
Процессинг Времени Выполнения на Сервере
Конструирование HTML-Страницы
Генерация HTML
Очистка Буфера Вывода
Переход к Новому Клиентскому Запросу
Доступ к Переменным CGI
Сообщение Между Сервером и Клиентом
Отправка Сообщений с Клиента на Сервер
Отправка Значений с Сервера Клиенту
Использование "Куков"
Сбор Мусора
Обработка Ошибок в Серверном JavaScript

Глава 6  Обслуживание Сессий

Предопределённые Объекты. Обзор.
Объект request
Свойства
Работа с Картами Изображений
Объект client
Свойства
Уникальное Обращение к Объекту client
Создание Специального Объекта client
Объект project
Свойства
Совместное Использование Объекта project
Объект server
Свойства
Совместное Использование Объекта server
Техника Работы с Объектом client
Сравнение Разных Техник Обслуживания Клиента
Клиентская Техника
Серверная Техника
Период Существования Объекта client
Присоединение Свойств client'а к URL Вручную
Безопасное Использование Объектов с Блокировкой
Использование Lock-Экземпляров
Специальные Lock для Объектов project и server
Как Избежать Мёртвых Блокировок

Глава 7  Дополнительная Функциональность JavaScript

Почтовая Служба
Служба Файловой Системы
Проблемы Безопасности
Создание File-Объекта
Открытие и Закрытие Файла
Блокировка Файлов
Работа с Файлами
Пример
Работа с Внешними Библиотеками
Указания по Написанию Внешних Функций
Идентификация Файлов Библиотек
Регистрация Внешних Функций
Использование Внешних Функций в JavaScript
Манипуляции с Запросами и Ответами
Шапка Запроса
Тело Запроса
Шапка Ответа

ЧАСТЬ III. Служба LiveWire Database Service

Глава 8  Соединение с БД

Взаимодействие с Базами Данных
Соединение с БД
Пулы Соединений с БД
Однопоточные и Многопоточные БД
Рекомендации
Обслуживание Пулов Соединений
Совместное Использование Фиксированного Набора Пулов Соединений
Совместное Использование Массива Пулов Соединений
Индивидуальные Соединения с БД
Обслуживание Соединения по Нескольким Запросам
Ожидание Соединения
Запрашивание Свободного Соединения

Глава 9  Работа с БД

Взаимодействие с Реляционной БД
Автоматическое Отображение Результатов Выполнения Запроса
Выполнение Произвольных Операторов SQL
Манипуляции с Результатами Выполнения Запросов с Помощью Курсоров
Создание Курсора
Отображение Значений Записи
Отображение Выражений и Агрегатных Функций
Навигация с Помощью Курсоров
Работа со Столбцами
Изменение Информации Базы Данных
Обслуживание Транзакций
Методы Управления Транзакциями
Работа с Двоичными Данными
Вызов Хранимых Процедур
Обмен Информацией
Этапы Использования Хранимых Процедур
Регистрация Хранимой Процедуры
Определение Прототипа для Хранимой Процедуры
Выполнение Хранимой Процедуры
Работа с Наборами Результатов
Работа с Возвращаемыми Значениями
Работа с Параметрами Вывода
Исключения Informix и Sybase

Глава 10  Конфигурирование Базы Данных

О Службе LiveWire Database Service
Проверка Конфигурации Вашей БД
Поддерживаемые Клиенты БД и ODBC-Драйверы
DB2
Informix
Удалённый Informix
Локальный Informix
ODBC
ODBC DSN (Только NT)
OpenLink ODBC-Драйвер (Только Solaris)
Visigenic ODBC-Драйвер (Только Unix)
Oracle
Удалённый Oracle
Локальный Oracle
Sybase
Удалённый Sybase
Локальный Sybase
Sybase (Только Unix)

Глава 11  Конвертация Типов Данных

О Конвертации Типов Данных
Работа с Датами и БД
Конвертация Типа Данных Базой Данных

Глава 12  Обработка Ошибок LiveWire

Проверка Ошибочных Условий
Возвращаемые Значения
Число
Объект
Булево
Строка
Пустое
Методы для Работы с Ошибками
Статус-Коды

Глава 13  Приложения-Образцы Videoapp и Oldvideo

О Приложениях Videoapp и Oldvideo
Конфигурирование Окружения
Соединение с БД и Перекомпиляция
Создание БД
Запуск Videoapp
Исходные Файлы
Архитектура Приложения
Модифицирование Videoapp

ЧАСТЬ IV Работа с LiveConnect

Глава 14  LiveConnect. Обзор.

Что Такое LiveConnect?
Работа с Оболочками
Взаимодействие JavaScript и Java
Объект Packages
Работа с Массивами Java
Обращение к Классу и Пакету
Аргументы Типа char
Пример Вызова Java из JavaScript
Взаимодействие Java и JavaScript
Использование Классов LiveConnect
Доступ к Серверному JavaScript
Конвертация Типов Данных
Конвертация из JavaScript в Java
Конвертация из Java в JavaScript

Словарь

Индекс

Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад

Индекс

Английский Алфавит    A  B  C  D  E  F  G  H  I  J  L  M  N  O  P  Q  R  S  T  U  V  W

Русский Алфавит    А  Б  В  Г  Д  З  И  К  М  Н  О  П  Р  С  Т  У  Ф  Х  Ц  Ч  Э  Я

Символы

$NSHOME\js\samples
и CLASSPATH 197
& в URL 116
.html  расширение имени файла 11
.html  расширение имени файла 11
.js  расширение имени файла 11
? в URL 115
\ 180
` (обратная кавычка)
См. обратные кавычки

Английский Алфавит

A

-a  директива компилятора 14
ACTION  атрибут 113
в образце приложения 14
addClient  функция 13, 117, 153, 157
addResponseHeader  функция 14, 118, 121, 185
agent  свойство 130
application/x-www-form-urlencoded  тип содержимого 182, 184
Application Manager
capabilities of 18
и client объект 143
конфигурирование установок по умолчанию 14
отладка приложений 10
рисунок 18
идентификация файлов в библиотек 180
установка приложений 14-57
обзор 18-51
защита 11
запуск приложений 10
специфицирование соединений с БД 194
старт, остановка и рестарт 19
URL приложения 17, 88
статья в справочнике 113
Array объект 15
ASCII 176
статья в справочнике 113
AUTH_TYPE, CGI-переменная 109, 130
auth_type  свойство 109, 130
auth_user  свойство 109, 130

B

Bcc  свойство 168
beginTransaction  метод 104, 229, 270
binary, тип данных 166
binary large объектs/двоичные большие объекты
См. BLOb
bit  тип данных 166
blob  тип данных 154, 265
blob  функция 131
blobImage  метод 131
blobLink  метод 131
Blob объект 11, 265, 266
BLObs
статья в справочнике 113
обзор 130
working with 130-233
Body  свойство 168
Boolean объект 15
booleanValue  метод 112
bugbase, приложение 10
byte  тип данных 165
byteToString  метод 174, 176

C

callC  функция 14, 179, 181
-c  директива компилятора 13
Cc  свойство 168
CGI, статья в справочнике 113
CGI-переменные
доступ к 108-112
AUTH_TYPE 109, 130
CONTENT_LENGTH 111
CONTENT_TYPE 111
GATEWAY_INTERFACE 112
HTTP_ACCEPT 111
HTTP_IF_MODIFIED_SINCE 111
HTTPS 109
HTTPS_KEYSIZE 109
HTTPS_SECRETKEYSIZE 110
PATH_TRANSLATED 110
QUERY_STRING 109, 110, 130
REMOTE_ADDR 110
REMOTE_HOST 110
REMOTE_USER 109, 110, 130
REQUEST_ METHOD 109, 110, 130
SCRIPT_NAME 110
SERVER_NAME 110
SERVER_PORT 110
SERVER_PROTOCOL 109, 110, 130
SERVER_SOFTWARE 112
SERVER_URL 110
char аргументы 198
char  тип данных 165, 266
cipher, приложение 10
CLASSPATH 197
clearError  метод 174, 177
client-mode, поле файла jsa.conf 16
client, объект 11, 96, 101, 105, 117, 132-139, 146, 147
добавление свойств к URL 156-158
создание специального 134
специальный 136-139
описание 132
уничтожение 155-156
получение идентификатора 14
id для обслуживания 134
в образце приложения 14
период существования 132, 127, 154-156
обслуживание 14, 93, 101, 103, 106, 112, 117, 119, 143-158
сравнение техник 144-147
у клиента 147-151
на сервере 151-154
с помощью клиентских кук 148-149
клиентской кодировкой URL 149-151
IP-адресом 152
серверной кукой 152-153
серверной кодировкой URL 153-154
обзор 127
при обработке страницы 101, 102
свойства 133-134
свойства, окончание срока действия 154-155
свойства, превышение на стороне 134
свойства, ограничения на стороне 133
свойства 133
ограничения 136
хранение свойств в объектах project или server 134-135
уникальное обращение к 134-135
client object maintenance, специфицирование 56
client, свойства
присвоение значений 148
Булевы 133
изменение 103
client, запросы
См. запросы
clob, тип данных 154, 265
close, метод 172, 218, 243, 270, 271, 273
colName, свойство 118, 243
columnName, метод 119, 224, 243, 273
столбцы, отображение имён 224
columns, метод 118, 224, 243
commit, статья в справочнике 113
commitTransaction, метод 104, 229, 270
connected, метод 104, 272
connection, метод 171
объектов DbPool 203
Connection, объекты 11, 95, 191, 195, 203, 270, 271, 272, 273, 274
создание 103
error-методы 273, 274
методы 104
storedProc, метод 137
connect, метод 170
CONTENT_LENGTH, CGI-переменная 111
CONTENT_TYPE, CGI-переменная 111
content-length, свойство 185
content types/типы содержимого, обслуживание специальных 182-186
cookie.txt 119
cookies/куки 112, 117
клиентские, статья в справочнике 113
определение 119
статья в справочнике 114
CORBA
статья в справочнике 114
critical section/критический раздел 158
статья в справочнике 114
cursor, метод 104, 271
Cursor, объекты 11, 95, 270, 272, 273
методы 118
обзор 118
свойства 118

D

database, объект 11, 96, 270, 271, 272, 273
ограничения 198
использование 189-247
date, тип данных 165, 266
Date, объект 15, 265, 266
конвертация дат в 263, 264
datetime, тип данных 165, 266
DB2
конфигурирование 153
типы данных 164
регистрация хранимых процедур в 136
прототипы хранимых процедур 137
DB2COMM, переменная окружения254
DB2INSTANCE, переменная окружения254
DB2PATH, переменная окружения254
dbadmin, приложение 10, 250
DbBuiltin, объект 11
DbPool, конструктор 171
DbPool-объекты 15
См. также пулы соединений, пулы БД
добавление свойства в 11
возвращаемое Boolean-значение 272
соединение с БД при помощи 191
метод соединения 203
соединения с 193
создание 194
в массивах пулов соединений 101
не возвращает значение 173
возвращаемые числовые значения 170
возвращаемый объект 271
хранимые процедуры и 137
возвращаемое строковое значение 173
использование 189-247
-d  директива компилятора 13
DDL, статья в справочнике 114
debug, функция 13
Debugger/Отладчик 19
URL отладки, использование 12
decimal, тип данных 165, 266
default page/страница по умолчанию
статья в справочнике 114
специфицирование 16, 64
deleteResponseHeader, функция 14, 118, 185
deleteRow, метод 119, 227, 270
DELETE SQL, оператор 128
destroy, метод 149, 150, 155
DHCP 152
disconnect, метод 170, 273
DML, статья в справочнике 115
DNS 110
double, тип данных 165
double precision, тип данных 165, 266
Dynamic Host Configuration Protocol/Протокол Динамической Конфигурации Хоста 152

E

ECMA, статья в справочнике 115
ECMA-262 10
ECMAScript, статья в справочнике 115
ECMA specification 1
JavaScript-документация и 11
версии JavaScript и 30
терминология 31
email
См. mail
eof, метод 173, 174
errorCode, метод 167
errorMessage, метод 167
error, метод 174, 177
error-статус, для объекта File 176
escape, функция 13, 117
execute, метод 104, 217, 270
exists, метод 174, 176
expiration, метод 149, 155

F

-f  директива компилятора 14
File, класс 106, 170-177
File, объект 11, 95
создание 171, 177
описание 170
методы 173
проблемы безопасности 171
float, тип данных 165, 266
floatValue, метод 112
flush, функция 13, 103, 105, 148, 186
описание 106
flush, метод 106, 176
пример использования 107
FORM, тэг HTML 113
From, свойство 168
Function, объект 95

G

GATEWAY_INTERFACE, CGI-переменная 112
getLength, метод 174, 176
getMember, метод 101
getOptionValueCount, функция 13
getOptionValue, функция 13, 114
getPosition, метод 173, 174
getPostData, метод 184

H

hangman, приложение 10
-h  директива компилятора 13
headers/"шапки" 118, 121
запрос 111
Hello World, приложение 10
history, метод 129
home, поле файла jsa.conf 16
hostname/имя хоста 110
hostname, свойство 142
host, свойство 142
HREF, атрибут 19
HTML 16, 88
атрибуты 12, 98
обусловливание 17
внедрение JavaScript в 96-100
генерация 93
статья в справочнике 115
и JavaScript 15, 96-100
образец исходного кода 73
HTTP 16, 101
аплеты 194
статья в справочнике 115
уровень протокола 109, 110
запрос, См. запросы
информация запроса 103
буфер ответа 303
пользователь 109, 110
HTTP_ACCEPT, CGI-переменная 111
HTTP_IF_MODIFIED_SINCE, CGI-переменная 111
HTTPD-процессы, объекты для 141
httpHeader, метод 111, 113, 121, 183
HTTP, метод 109, 110
HTTPS_KEYSIZE, CGI-переменная 109
HTTPS_SECRETKEYSIZE, CGI-переменная 110
HTTPS, CGI-переменная 109

I

-i  директива компилятора 13
if...else, оператор
в образце приложения 15
image, тип данных 166
imageX, свойство 130, 131
imageY, свойство 130, 131
IMG, тэг HTML 230, 231
index.html
и страница по умолчанию 56
Informix 190
конфигурирование 154-256
типы данных 165, 266
параметры хранимых процедур 238
INFORMIXDIR, переменная окружения 255
INFORMIXSERVER, переменная окружения 255
INFORMIXSQLHOSTS, переменная окружения 255
INPUT, тэг HTML 118
insertRow, метод 119, 227, 270
INSERT SQL, оператор 128
int, тип данных 166
integer, тип данных 165
interval, тип данных 165
IP-адрес 147, 151, 152
статья в справочнике 115
период существования свойств 155
IP-адрес, техника, статья в справочнике 115
ip, свойство 130
ISMAP, атрибут тэга IMG 131
isNaN, функция 13

J

Java
См. также LiveConnect
доступ к JavaScript 100
доступ с LiveConnect 195
массивы в JavaScript 197
вызов из JavaScript 195
классы 198
взаимодействие с JavaScript 193-312
в сравнении с JavaScript 18
пример вызова из JavaScript 198
и JavaScript, взаимодействие 300
JavaScript-исключения и 102
 методы, требующие аргументов типа char 298
объекты, именование в JavaScript 197
оболочки объектов 195
пакеты 198
Java-аплеты, серверные скрипты для 17
JavaArray, объект 195, 297
JavaArray, конвертация типов 309
JavaClass, объект 195, 298
JavaClass, конвертация типов (LiveConnect) 110
JavaObject, объект 196
JavaObject, конвертация типов 309
java-пакеты 197
JavaPackage, объект 196, 298
JavaScript
доступ из Java к 300
исполняемые файлы приложения 19
основы 15-123
клиентский 14
взаимодействие с Java 193-312
в сравнении с Java 18
иллюстрация компонентов 12
ядро 13
отладка 13
разница между серверным и клиентским 22
ECMA-спецификация и 30
подключение 41
пример вызова из Java 104
файлы 18, 92
компиляция 19
сбор мусора 122-123
и HTML 16-100
взаимодействие с Java 295
Navigator 14-25
оболочки объектов 312
обзор 11
процессы времени выполнения 18-90, 100-105
серверный 25-27
серверный, обзор 10-96
задачи на клиенте 16-87
задачи на сервере 16-87
переменные и request-свойства 131
версии и Navigator xv
где может размещаться 91
JavaScript-файлы 92
Java Виртуальная Машина 38
jsa.conf, файл 66
jsac. См. компилятор.
jsaccall.c 179
jsaccall.h 179
jsaccall, приложение 10, 178
JSException, класс 300, 302
js-файлы 18
JSObject, доступ к JavaScript с помощью 301
JSObject, класс 300
jsVersion, свойство 142

L

-l  директива компилятора 13
LD_LIBRARY_PATH, переменная окружения 254, 258, 261
LIBPATH, переменная окружения 254, 258
library, поле файла jsa.conf 16
LiveConnect 12, 95, 293-312
прямой доступ к Java 295
возможности 194
конфигурация 42
конвертация типов данных 105-312
статья в справочнике 115
и HTTP-аплеты 294
Java и JavaScript, взаимодействие 300
и NSAPI-приложения 194
объекты 195
ограничения 194
и компоненты WAI 194
LiveWire, библиотека доступа к БД 38
LiveWire Database Service 187-289
См. также базы данных
системные требования для 10
lock, метод 141, 158-166
в образце приложения 15
Lock, объект 11, 96, 158-166
longdatacompat 154
long, тип данных 166
long raw, тип данных 166

M

mail/почта
MIME 169
отправка с помощью JavaScript 16, 167-170
majorErrorCode, метод 195, 204, 270, 273
majorErrorMessage, метод 195, 204, 273, 274
Math, объект 15
maxdbconnect, поле файла jsa.conf 16
metadata, приложение 11
METHOD, атрибут 113
METHOD, свойство 109, 130
MIME, статья в справочнике 115
MIME-совместимая почта 169
MIME-типы 170
minorErrorCode, метод 195, 204, 270, 271, 274
minorErrorMessage, метод 195, 204, 273
money, тип данных 165, 266
MULTIPLE, атрибут
тэга SELECT 114

N

NAME, атрибут 19, 113
в образце приложения 14
тэга SELECT 114
Navigator
архитектура приложения в JavaScript 36
и JavaScript 14, 25
и JavaScript, поддерживаемые версии xv
Navigator JavaScript
См. клиентский JavaScript
nchar, тип данных 165, 266
NETSCAPE_LIVEWIRE 120, 148
Netscape cookie-протокол 148, 152
статья в справочнике 116
netscape, пакет 297
Netscape web-серверы
поддержка стилей конфигурации 18
архитектура приложения в JavaScript 36
образцы приложений, устанавливаемые вместе с 69
next, метод 119, 221, 223, 241, 243, 272
NSAPI-приложения 194
null, конвертация значений (LiveConnect) 108
number, тип данных 165, 266
Number, объект 15
number, свойство 15
numeric, тип данных 166
nvarchar, тип данных 165, 266

O

object, поле файла jsa.conf 16
Object, объект 15
-o  директива компилятора 13
ODBC
конфигурирование 156-258
типы данных 165
поддерживаемые драйверы 252-253
статья в справочнике 116
прототипы хранимых процедур 237
oldvideo, приложение 10, 277-289
и Informix 178
onClick, обработчик события 114
Open DataBase Connectivity, стандарт
См. ODBC
OpenLink
конфигурирование 157-258
open, метод 172
OPTION, тэг 115
Oracle 190
конфигурирование 158-260
 типы данных 165, 266
параметры хранимых процедур 238
ORACLE_HOME, переменная окружения259, 260
ORACLE_SID, переменная окружения260
outParamCount, метод 139, 245
outParameters, метод 135, 239, 244, 245

P

Packages, объект 15, 297
parseFloat, функция 13
parseInt, функция 13
Pascal, функции 178
PATH_INFO, CGI-переменная 110
PATH_TRANSLATED, CGI-переменная 110
PATH, переменная окружения 254
для компилятора 12
-p  директива компилятора 14
port, свойство 142
post, значение атрибута METHOD 113
примитивное значение, статья в справочнике 116
project, объект 11, 96, 101, 139-141
описание 139
в образце приложения 15
период существования 139, 128, 140
блокирование 141, 159, 162-163, 173
обзор 127-128
свойства 140
совместное использование 141
хранение пулов соединений в 198, 200, 201
protocol, свойство 109, 130, 142

Q

QUERY_STRING, CGI-переменная 109, 110, 130
query, свойство 109, 130

R

raw, тип данных 166
-r  директива компилятора 14
readByte, метод 173, 175
readln, метод 173, 175
read, метод 173, 175
real, тип данных 166
redirect, функция 13, 103, 105, 107-108, 129, 147, 149, 150, 153, 156, 186
описание 107
registerCFunction, функция 13, 179, 180
release, метод 103, 204, 270, 273
REMOTE_ADDR, CGI-переменная 110
REMOTE_HOST, CGI-переменная 110
REMOTE_USER, CGI-переменная 109, 110, 130
REQUEST_METHOD, CGI-переменная 109, 110, 130
request, объект 11, 96, 101, 105, 112, 129-131, 183, 184
создание 129
описание 129
пример создания свойства113
и формы 131
в образце приложения 14
период существования 126, 129
обзор 126-127
в процессинге страниц 101, 102
свойства 109, 130-131
свойства и переменные JavaScript 131
сохранение свойств 108
установка свойств элементами формы 113
response/ответ, манипуляции с шапками 94, 185
resultSet, метод 134, 239, 240, 271
Resultset, объект 11, 95, 233, 271, 272, 273
См. также результирующие наборы
 методы 243
returnValue, метод 135, 239, 244, 245
return-значения хранимых процедур 245
rollbackTransaction, метод 104, 229, 270
rowid, тип данных 166

S

SCRIPT_NAME, CGI-переменная 110
скрипты, изменение свойств клиента 103
SCRIPT, тэг 18, 92
См. также клиентские скрипты
прямая замена в 117
когда использовать?
SELECT, SQL-оператор 119, 220, 223, 225
SELECT, тэг 13, 114
sendmail, приложение 10
SendMail, класс 167-170
SendMail, объект 11, 96
send, метод 167
serial, тип данных 165
SERVER_NAME, CGI-переменная 110
SERVER_PORT, CGI-переменная 110
SERVER_PROTOCOL, CGI-переменная 109, 110, 130
SERVER_SOFTWARE, CGI-переменная 112
SERVER_URL, CGI-переменная 110
server-client, взаимодействие112-122
server, объект 11, 96, 101, 141-143
описание 141
период существования 142 , 128
блокирование 159, 162-163, 173
обзор 128
свойства 141-142
совместное использование данных 143
SERVER, тэг 18, 87, 88, 92, 96, 97-98, 100
См. также серверные скрипты
в образце приложения 13, 74
когда использовать? 100
Session Management Service 17, 101, 125-166
статья в справочнике 116
обзор объектов 126-129
setPosition, метод 173, 174
SHLIB_PATH, переменная окружения 254, 255, 258
однопоточные БД 196
smalldatetime, тип данных 166
smallfloat, тип данных 165
smallint, тип данных 165, 266
smallmoney, тип данных 166
Smtpserver, свойство 168
SQL 190
См. также операторы
обработка ошибок269-274
выполнение 117
статья в справочнике 116
SQL_BIGINT, тип данных 166
SQL_BINARY, тип данных 166
SQL_CHAR, тип данных 166
SQL_DATE, тип данных 166
SQL_DECIMAL, тип данных 166
SQL_DOUBLE, тип данных 166
SQL_FLOAT, тип данных 166
SQL_INTEGER, тип данных 166
SQL_LONGBINARY, тип данных 166
SQL_LONGVARCHAR, тип данных 166
SQL_NUMERIC, тип данных 166
SQL_REAL, тип данных 166
SQL_SMALLINT, тип данных 166
SQL_TIME, тип данных 166
SQL_TIMESTAMP, тип данных 166
SQL_VARBINARY, тип данных 166
SQL_VARCHAR, тип данных 166
SQLTable, метод 104, 216, 270
ssjs_generateClientID, функция 14, 135, 207
ssjs_getCGIVariable, функция 14, 108, 109, 130
ssjs_getClientID, функция 14, 135, 152, 153
start, поле файла jsa.conf 16
static, статья в справочнике 117
storedProcArgs, метод 137, 270, 271
storedProc, метод 104, 237, 271
Stproc, объект 11, 95, 233, 235, 271
См. также хранимые процедуры
создание 137
 методы 139
string, тип данных 165, 266
String, объект 15
stringToByte, метод 174, 176
стили, конфигурации 58, 63
Subject, свойство 168
sun, пакет 297
Sybase 190
конфигурирование 160-262
 типы данных 164, 266
прототипы хранимых процедур 137
SYBASE, переменная окружения 261

T

TCP-порт 110
text/html, content type/тип содержимого 182
text, тип данных 165, 266
time, тип данных 165
timestamp, тип данных 165
tinyint, тип данных 166
TNS_ADMIN, переменная окружения 259
To, свойство 168
toString, метод 112

U

unescape, функция 13
unlock, метод 141, 158-166
в образце приложения 15
updateRow, метод 119, 227, 270
UPDATE SQL, оператор 128
uri, поле файла jsa.conf 16
uri, свойство 130
URL-кодированные переменные
и объект request 131
восстановление значений 117
URL-кодирование
См. также клиентская кодировка URL, серверная кодировка URL
обслуживание объекта client с помощью 147, 149, 151
URL 110
добавление client-свойств к 156-158
добавление информации к 13
приложения 17
изменение 107-108
и обслуживание client 149-151, 153-154
используемые соглашения xviii
создание 147
отладки 12
динамическая генерация 115
информация о кодировке в 115-122
escaping-символы в 93
статья в справочнике 117
включение спецсимволов 117
модифицирование 112
и функция redirect 107
перенаправление в 13
и перезагрузка страницы 117
и Session Management-объекты 128
для старта и остановки приложений 19

V

VALUE, атрибут 118
varbinary, тип данных 166
varchar2, тип данных 166
varchar, тип данных 165, 266
-v  директива компилятора 13
VDBCINI, переменная окружения 258
videoapp, приложение 10, 277-289
и Informix 178
и ODBC 178
и SQL Server 178
video, приложение
См. приложение videoapp
viewer, приложение 10
Visigenic, конфигурирование 158
Visual JavaScript 1

W

WAI-компоненты 294
web-файлы 19, 60
построение 17
определение 11
статья в справочнике 117
перемещение 19
специфицирование пути 16, 64
writeByte, метод 173, 175
write, функция 13, 93, 97, 105, 156, 171
с обратными кавычками 98
и обслуживание client 150
описание 106
и flush 106
с тэгом SERVER 97
writeln, метод 173, 175
write, метод 173, 175
WWW, статья в справочнике 117


Русский Алфавит

А

авторизация 101
активное приложение
статья в справочнике 113

арены, при сборе "мусора" 122

Б

байт-коды 19
построение 17
статья в справочнике 113
база данных, доступ 87
база данных, имя 194
база данных, клиентские библиотеки, конфигурирование 149-262
база данных, поддерживаемые клиенты 252-253
база данных, проверка конфигурации 250-251
база данных, пулы соединений
См. пулы соединений
база данных, имя сервера 194
база данных, сервер
в JavaScript, архитектура приложения 36
база данных, тип 194
база данных, транзакции
См. транзакции
базовый URL приложения
статья в справочнике 113
базы данных 187-289
См. также LiveWire Database Service
конфигурирование 149-262
соединение с 195
конвертация типов данных 163-266
и даты 164
обработка ошибок 269-274
советы по обслуживанию соединений и потоков 197
многопоточные 196
однопоточные 196
типичное взаимодействие 190
проверка соединения 195
безопасность
внешние библиотеки и 178
File-объект и 171
библиотека времени выполнения 37
библиотеки С 178
вызов 17
библиотеки C++ 178
библиотеки, внешние 178-182
библиотеки динамической компоновки (.dll) 178
блокировка 158-166
Булевы выражения 134
Булев тип, конвертация (LiveConnect) 107
буфер вывода 102
очистка 13, 106-107

В

версии JavaScript xv
взаимодействие между клиентом и сервером 112-122
встроенное максимальное количество соединений с БД 194
внешние библиотеки 178-182
вызов 17
идентификация файлов 180
безопасность 178
специфицирование 16, 64
внешние функции
вызов 179
определение 178
пример использования 181
статья в справочнике 115
советы по написанию 179
регистрация 180
использование в JavaScript 181
где использовать? 178

встроенные/внешние функции 178-182

Г

глобальный объект 11

Д

данные
конвертация форматов 176
разделение между сервером и клиентом 112
данные, совместное использование 87, 96, 101, 127, 141, 143, 158-166, 173, 195, 198
данные, сохранение 87
даты
конвертация в объекты Date 263
и БД 264
вставка в БД 264
двоичный формат 176
директории
используемые соглашения xviii

документация, прочая xvi-xvii

З

записи, отображение значений 220
запрос, поток 103
запросы
изменение 93, 107-108
шапка 118
манипуляции с необработанными данными 182-186
перенаправление 116
совместное использование соединения 105
прерывание выполнения 107
специализирование вывода 216
отображение 216-217
манипулирование телом 184-185
"шапки" 111, 113, 121
манипулирование 183-184
запросы к базе данных
и функция flush 106

И

имя приложения 17
изменение 18
специфицирование 56
инсталяция, параметы
конфигурирование 14
инсталяция приложения 14
исключения
обработка в Java 102

исходные файлы 13

создание 11
компоненты 51

исходный скрипт, пример 73

К

кавычки, знаки
с обратным слэшем 100
порядок 19
карты изображений 131
использование 131
классы
Java 198
LiveConnect 100

клиент

характеристики 16
взаимодействие с сервером 112
статья в справочнике 113
обслуживание объекта client на стороне клиента 147-151
препроцессинг данных на 16, 114, 118

клиент-серверное взаимодействие 112-12

использование кук для 119-121

клиентские "куки" 148-149

статья в справочнике 113
время существования свойств 154
обслуживание объекта client с помощью 106, 119, 146, 147

клиентские скрипты

взаимодействие с сервером 17
генерация 118
отправка значений в 117
когда использовать 17

клиентский JavaScript 12, 24, 8

статья в справочнике 113
иллюстрация 14
период существования объекта 17
обзор 14

кодирование клиентского URL 103, 107, 112, 117, 147, 149-151

статья в справочнике 113
кодировка свойств запроса в URL 116
кодировка серверного URL 107, 112, 117, 151, 153-154
статья в справочнике 116
период существования свойств 155
конечный сервер/сервер публикаций
определение 19
статья в справочнике 114
обновление файлов на 19
компилятор 17
опции 13
и переменная окружения PATH 42
использование 12-54
компоненты среды выполнения 37
конфигурация, стили 18, 63
корневая директория 17
куки, протокол 146, 148, 152
См. также клиентские куки

курсоры

создание 119
специализация функций отображения 116
определение количества столбцов 124
отображение агрегатных функций 123
отображение имён столбцов 124
отображение выражений 123
отображение значений записей 220
статья в справочнике 114
навигация в 123
обзор 118
обновляемые 119, 225-227, 232
использование 218-227

М

маршрутизация на сервере 17
массивы
Java 197
математические константы и функции 164
"мёртвая" блокировка 163-166
статья в справочнике 114

методы

close 172
destroy 155
expiration 155
flush 106
history 129
open 172
setPosition 174
static 117
многопоточность
и Sybase 162
многопоточные БД 196
мультимедиа
использование BLOb'ов 130

Н

начальная страница 132, 198
и объект request 129
статья в справочнике 115
специфицирование 56, 64
необходимые навыки xv
не рекомендуется, статья в справочнике 115
новые возможности xi

О

обновление приложения xvii-xviii
обновляемый курсор
статья в справочнике 117
оболочки
для Java объектов 195
для JavaScript объектов 112
обработка ошибок для LiveWire 169-274
обработчики событий 12
прямая подмена 117
onClick 114
образцы приложений 19-83
Hangman 16-83
Hello World 11-76
обратная совместимость xviii
обратные кавычки 17, 98-100
для включения JavaScript 98
когда использовать 100

объекты

добавление свойств к 11
JavaScript в Java 100
период существования 126
LiveConnect 195
остановленная транзакция, статья в справочнике 117
ответы, манипуляции с необработанными данными 182-186
откат, статья в справочнике 116

П

пакеты, Java 198
пакеты Netscape
См. пакеты
параметры вывода
хранимых процедур 245
параметры хранимых процедур 138
передаваемый SQL, выполнение 217
переменные окружения, доступ к 109
перенос приложений xvii-xviii
период существования свойства 154
платформа разработки, определение 19
получение значения атрибута METHOD 113
потоки
и базы данных196
и Java 103
приложения
архитектура 15-39
bugbase, образец приложения 10
построение 17-48
cipher, образец приложения 10
компиляция xviii, 52-54
конфигурация 10-43
создание 16
создание исходных файлов 51
dbadmв образец приложения 10
отладка 10-63
удаление 59
публикация 39, 63
и выгрузка файлов 113
hangman, образец приложения 10
и HTML 18
инсталяция 54-57
jsaccall, образец приложения 10
metadata, образец приложения 11
oldvideo, образец приложения 10
задачи, распределение 17
публикация 15
ограничение доступа к 18, 63
запуск 18, 60
в период выполнения 19
образец 19-83
sendmail, образец приложения 10
совместное использования данных 139, 141
старт, остановка и рестарт 59
типы операторов 18
системные требования для 39
videoapp, образец приложения 10
viewer, образец приложения 10
world, образец приложения 10

подтверждение, промпт, конфигурирование 14

проверка ввода 87
прототипы 11
хранимые процедуры и 137
прототипы объектов 11
процессинг времени выполнения 97, 100-105
пример 19
"птички"
См. обратные кавычки
публикация, статья в справочнике 114
пулы баз данных
См. DbPool-объекты
пулы соединений
См. также объекты DbPool
как свойство объекта project 201
обслуживание 198
совместное использование массива ... 201
совместное использование фиксированного набора 199
хранение с объектом project 198, 200

Р

рабочий сервер
определение 39
статья в справочнике 115
обновление файлов с 19
разметка и очистка 123
режимы доступа к файлам 172
результирующие наборы 139
См. также объект Resultset
создание 140
Resultset, объект 139
ряд текущий 118
статья в справочнике 114

С

сбор мусора в JavaScript 122-123
свойства
static 117
сервер
функции администрирования 101
авторизация 101
характеристики 16
взаимодействие с клиентом 117
обслуживание объекта client на 151-154
процессы, объекты для 141
рестарт 179, 180
серверные "куки" 146, 151, 152-153
статья в справочнике 116
период существования свойств 155
серверные объекты
период существования 87
серверные скрипты
взаимодействие с клиентом 17
когда использовать? 17
серверный JavaScript 12, 25-27
подключение 11
выполнение 105
статья в справочнике 116
иллюстрация 15, 26
сервер публикаций/конечный сервер
определение 19
статья в справочнике 114
обновление файлов на 19
сессия, ключ 109
скрытие элементов формы 117
соглашения по документам xviii-xix
соединения
подходы 191-204
DbPool-объекты 193
отсоединение 195
установление 191-204
запрос объекта 195, 208
захват нескольких клиентских запросов 205
специфицирование количества 16, 64, 194
хранение 134
ожидание 207
соединения с базой данных
См. соединения
сообщения об ошибках, запрашивание 195
спецсимволы в URL 117
списки выбора 114
среда разработки, её компоненты 19
ссылки
для BLOb-данных 231
создание 19
статус приложения, определённый 10
страница HTML
конструирование 18, 101, 102, 105-108
отправка клиенту 105, 147
страница по умолчанию
статья в справочнике 114
специфицирование 16, 64

строки

разбор 93
конвертация типов (LiveConnect) 108

Т

типы данных
Boolean, конвертация 307
конвертация для LiveWire 163-266
конвертация в LiveConnect 105-312
Informix 166
JavaArray, конвертация 309
JavaClass, конвертация 310
JavaОбъект, конвертация 309
в JavaScript 18
конвертация JavaScript в Java 306
конвертация Java в JavaScript 312
null-конвертация 308
конвертация чисел 306
ODBC 165
Oracle 165
другие виды конвертации 311
конвертация строк 308
Sybase 164, 266
транзакции
выполнение 194
управление 129
статья в справочнике 117
обслуживание 127-230
обзор 127
откат 194
область видимости 129
транзакция текущая, статья в справочнике 114
тэги HTML
FORM 113
IMG 130, 231
INPUT 118

У

указатели 174
уникальный идентификатор 14
упакованные десятеричные, нотация 164
утилита трассировки 11, 62, 63
конфигурирование 14

Ф

файл, форматы 176
файл, I/O (ввод-вывод) 177
файлы
доступ в JavaScript 170-177
закрытие 172
получение информации для 176
блокировка 173
открытие 172
позиционирование в 174
чтение из 175
запись в 175
выгрузка 183
фиксированная десятеричная нотация 164
форма, значения по умолчанию 117
формы
и обслуживание client 147
клиентские скрипты для 17
значения по умолчанию 117
GET, метод 183
скрытые элементы 117
POST, метод 184
процессинг/обработка 13
и объект request 126
операторы 14
переменные 131
функции 12
debug 11
redirect 107
write 17, 98
функции C
вызов 14
регистрация 13

функции отладки 11

Х

хранимые процедуры 133-247
См. также объект Stproc
аргументы 135
определение прототипов для 137
выполнение 137
в DB2 136
параметры вывода 245
параметры для 138
регистрация 136
результирующие наборы 134
return-значения 135, 245
этапы использования 135

Ц

цели, создание 19

Ч

числа
конвертация в символы 174, 176
идентификация 93
хранение 263
конвертация типов (LiveConnect) 106

Э

элементы формы
скрытые 114, 117, 118
использование в качестве свойства запроса 113

Я

ядро JavaScript 13, 90
статья в справочнике 114
якоря, создание 19
Оглавление | Назад

Дата последнего обновления: 29 сентября 1999 г.

╘ Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 22
Доступ к Сервису CORBA

В этой главе рассматривается использование LiveConnect для доступа к распределённым объектам CORBA. С помощью LiveConnect Вы можете получить доступ к Java; через Java - соединяться с CORBA-объектами, используя Netscape Internet Service Broker for Java.

В главе имеются следующие разделы:

О Сервисе CORBA


Netscape Internet Service Broker for Java (ISB for Java) это брокер запроса объектов фирмы Netscape. ISB for Java устанавливает соединения внутри себя и с другими брокерами запроса объектов/object request brokers (ORB) путём использования протокола Internet InterORB Protocol (IIOP).

ISB for Java даёт Вашим приложениям JavaScript доступ к распределённой объектной модели CORBA, опубликованной в ORB, работающем на основе IIOP (включая сам ISB for Java). Эти объекты могут быть частью распределённого приложения. Чтобы получить доступ к такому распределённому объекту, Вы обязаны иметь Java-stub/основу, и этот stub-класс обязан быть в пути Вашей CLASSPATH. В свою очередь, Вы можете использовать Java и LiveConnect для экспонирования частей Вашего серверного приложения JavaScript как распределённых объектов CORBA.

За пределами данного учебника остаётся описание создания CORBA-исполняемых распределённых объектов  с использованием ISB for Java, а также то, как делать Java-стабы для таких объектов. Об этом см. учебник Netscape Internet Service Broker for Java Programmer's Guide.

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

Рисунок 22.1   Приложение JavaScript CORBA-клиент

Как видно на рисунке, среды запуска Java и JavaScript находятся вместе на одном web-сервере. Они взаимодействуют путём использования LiveConnect стандартным способом, описанным ранее в этой главе. Методы, вызываемые в оболочке стаба в JavaScript, дают в результате вызов методов объекта Java-стаба в Java. Стаб использует Java ORB для взаимодействия с удалённым сервисом. В данной архитектуре серверный процесс объекта может проходить только на машине, которая имеет ORB, и может быть написан на любом языке.

Приложение-образец flexi иллюстрирует это. В нём FlexiServer это отдельное приложение Java, содержащее реализации нескольких распределённых объектов. Этот пример обсуждается в разделе "Приложение-Образец Flexi".

После того как поработаете с flexi, прочтите в разделе "Альтернативные Публикации" обсуждение более сложных альтернатив публикации.

Приложение-Образец Flexi


Приложение flexi иллюстрирует использование серверного JavaScript для доступа к удалённому сервису, запущенному на ORB с включённым протоколом IIOP, а также показывает удалённый сервис, написанный целиком на Java с использованием ISB for Java. И исходные файлы, и исполняемые файлы приложения flexi установлены в директории $NSHOME\js\samples\flexi.

A flexible spending account (FSA)/гибко расходуемый счёт это счёт, на котором служащие могут хранить доллары предоплаты, используемые для медицинских расходов. Служащие обычно подписываются на этот план через администратора плана и выбирают сумму в долларах, которую они хотят хранить на своих счетах. Если служащий осуществляет затраты на медицинские цели, он отправляет запрос, который, если одобрен, вызывает снятие суммы со счёта и перевод её служащему.

Приложение flexi предоставляет поддержку обслуживания FSA. В этом приложении администратор имеет следующие опции:

Для служащего имеются следующие опции:

CORBA. Клиентский и Серверный Процессы


Рисунок 22.2 показывает две основные части flexi. Они реализуют клиента и сервис CORBA.

Рисунок 22.2   Приложение-Образец flexi

Клиент CORBA это приложение на серверном JavaScript, известное как flexi. Это приложение реализует пользовательские интерфейсы администратора и служащего, описанные ранее. Оно соединяется с объектом FSA-Admin (описанном далее) в отдельном процессе или даже на отдельном компьютере. Приложение затем использует этот и другие объекты, возвращаемые из FSA-Admin, для выполнения большинства своих операций.

Сервер CORBA это отдельное Java-приложение, работающее из оболочки/shell. Оно содержит реализации всех интерфейсов, определённых в IDL-файле Flexi.idl. Это приложение под названием FlexiServer реализует основную функциональность системы FSA. После старта это приложение создаёт экземпляр объекта, реализующий интерфейс ::FSA::Admin, и регистрирует его под именем "FSA-Admin." Клиенты этого сервиса (такие как приложение flexi на JavaScript) получают доступ к этому объекту, разрешая сначала своё имя. Клиенты используют этот объект для создания других объектов и для получения удалённых ссылок на них.

Старт FlexiServer


FlexiServer это отдельное приложение Java. Оно может работать только на машине, имеющей JDK 1.0.2. В Enterprise Server 3.01 и в FastTrack Server 3.01 Вы можете также запускать его на машине с JDK 1.1.2. Прежде чем запустить FlexiServer, Вы должны убедиться, что среда работы корректна.

Из оболочки, где Вы запускаете FlexiServer, убедитесь, что Ваша переменная окружения PATH содержит $JDK\bin и что CLASSPATH включает следующее:


...
$NSHOME\js\samples\flexi
$NSHOME\wai\java\nisb.zip
$JDK\lib\classes.zip

Здесь $JDK это директория, в которой установлен JDK, а $NSHOME это директория, в которой установлен Ваш web-сервер.

Если среда корректна, Вы можете стартовать FlexiServer так:


cd $NSHOME\js\samples\flexi\impl
java FlexiServer

Вы должны увидеть такое сообщение:


Started FSA Admin: Admin[Server,oid=PersistentId[repId=IDL:Flexi/Admin:1.0,objectName=FSA-Admin]]

С этого момента FlexiServer стартовал как сервис CORBA и зарегистрировал в ORB объект с интерфейсом ::FSA::Admin и именем FSA-Admin. FlexiServer работает в фоновом режиме, ожидая запросов на обслуживание.

Старт Flexi


Вы обязаны стартовать FlexiServer до старта flexi, поскольку стартовая страница flexi пытается соединиться с FlexiServer.

Добавьте $NSHOME\js\samples\flexi в CLASSPATH Вашего web-сервера. О том, как это сделать, см. "Установка LiveConnect".

Используя Application Manager, установите приложение flexi JavaScript, как описано в разделе "Установка Нового Приложения". Параметры, устанавливаемые Вами для flexi, показаны в следующей таблице.

Таблица 22.1  Установки Приложения Flexi
Установка Значение

Name


flexi

Web File Path/Путь к web-файлу


$NSHOME\js\samples\flexi\flexi.web

Default Page/Страница по Умолчанию


fsa.html

Initial Page/Начальная Страница


start.html

Client Object Maintenance/Обслуживание Объекта сlient


client-cookie

Использование Flexi


Чтобы стартовать flexi, Вы можете запустить его из Application Manager или ввести следующий URL:


http://server-name/flexi

Страница по умолчанию позволяет пользователю идентифицировать себя как администратора или как служащего. Чтобы быстрее прочувствовать то, как работает это приложение, следуйте этому сценарию:

  1. Администратор создаёт для пользователя баланс.
  2. Служащий выбирает счёт.
  3. Служащий отправляет запрос.
  4. Администратор выбирает счёт служащего.
  5. Администратор принимает запрос, что уменьшает баланс счёта служащего, и отправляет чек на запрошенную сумму.
  6. Служащий выбирает счёт.
  7. Служащий просматривает статус счёта.
  8. Администратор выбирает счёт служащего.
  9. Администратор удаляет запрос.

Система может обрабатывать только один запрос служащего в единицу времени. После удаления запроса может быть отправлен новый запрос.

Исходные Файлы


В таблице показаны первичные файлы и директории для flexi.

Таблица 22.2  Файлы и Директории Приложения Flexi

flexi.idl

Файл, определяющий интерфейс с удалённым сервисом, включая Admin, Account, Claim.


Flexi\

Директория, содержащая код, сгенерированный из Flexi.idl программой idl2java. Эта директория содержит каркасы и стабы (каркасы\основы) интерфейсов.


impl\

Директория, содержащая Java-реализации всех интерфейсов, определённых во Flexi.idl. Она также содержит класс FlexiServer, реализующий main-программу приложения Java, которое работает как сервис.


*.html

Файлы, реализующие серверное приложение JavaScript. Сюда входит также web-файл приложения, flexi.web.

Просмотрите эти файлы, чтобы добиться полной ясности в вопросах работы приложения. Здесь обсуждаются лишь некоторые детали.

Установка FlexiServer как CORBA-Сервера


Функция main отдельного Java-приложения реализована в flexi\impl\FlexiServer.java. Его код таков:


import org.omg.CORBA.*;

class FlexiServer
{
   public static void main(String[] args) {
   try {
      // Инициализируются orb и boa.
      org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
      org.omg.CORBA.BOA boa = orb.BOA_init();


      // Создаётся серверный объект.
       Admin __admin = new Admin();

      
// Информирует boa, что серверный объект готов.
       boa.obj_is_ready(__admin);

      
// Регистрируется имя объекта с именем сервиса.
       // Сначала определяется хост имени сервиса, по умолчанию это <localhost>:80.
       String _nameServiceHost = null;
      if (args.length > 0) {
         // Принимается, что первый arg это имя хоста имени
         // сервиса. Ожидаемый формат: <hostname>:<port>
          _nameServiceHost = args[0];
      }


      else {
          String _localHostName = null;
          try {
            _localHostName=
                java.net.InetAddress.getLocalHost().getHostName();
             _nameServiceHost = _localHostName + ":80";
          }
          catch (java.net.UnknownHostException e) {
             System.out.println("Couldn't determine local host;
             can't register name.");
          }
      }

  
    String _regURL = "http://" + _nameServiceHost + "/FSA-Admin";
       System.out.println("Registering Admin object at URL: " + _regURL);

      // Регистрируется серверный объект.
      netscape.WAI.Naming.register(_regURL, __admin);
      System.out.println("Started FSA Admin: " + __admin);

      boa.impl_is_ready();
   }

   catch (org.omg.CORBA.SystemException e)
{
      System.err.println(e);
      }
   }
}

Этот код инициализирует ORB и создаёт экземпляр класса Admin. Затем экземпляр регистрируется как распределённый объект с URL в форме http:// host : port /FSA-Admin. По умолчанию host это имя хоста, на котором запущен FlexiServer, а port равен 80. Вы можете поставить Ваши собственные значения для host:port   путём передачи их как аргументов для FlexiServer при его старте. Чтобы использовать локальный хост, но другой номер порта, Вам нужно изменить исходный код и перекомпилировать его. Если код имеет соответствующее имя, он регистрирует объект, используя метод register объекта netscape.WAI.Naming. Дополнительно см. книгу Netscape Internet Service Broker for Java Reference Guide.

Наконец, код печатает сообщение на консоль и ожидает запросы от CORBA-клиентов. В данном случае единственным CORBA-клиентом, который знает о нём, является приложения flexi на языке JavaScript.

Установка flexi как CORBA-Клиента


Файл start.html это начальная страница приложения JavaScript flexi. Эта страница использует LiveConnect для инициализации ISB for Java и установления соединения с FSA-Admin.


<server>
// Инициализируется orb.
project.orb = Packages.org.omg.CORBA.ORB.init();

// Устанавливается соединение с сервисом "FSA-Admin".
// По умолчанию принимается, что name service запущен на текущем сервере.
nameHost = "http://" + server.hostname;
serviceName = "/FSA-Admin";
serviceURL = nameHost + serviceName;

// Разрешается имя и получается ссылка на стаб Admin.
project.fsa_admin = Packages.Flexi.AdminHelper.narrow(
netscape.WAI.Naming.resolve(serviceURL));

</server>

Первый оператор инициализирует ISB for Java, вызывая static-метод init Java-класса org.omg.CORBA.ORB. Он сохраняет возвращённый объект как свойство объекта project, так что он доступен для всего приложения.

Второй набор операторов определяет URL, который использовался для регистрации объекта FSA-Admin. Если Вы использовали при регистрации этого объекта другой URL (как описано в последнем разделе), Вам нужно сделать соответствующие изменения в этих операторах. URL, используемый в CORBA-сервере, обязан быть точно тем же, что и URL, используемый в CORBA-клиенте.

Код затем вызывает метод resolve объекта netscape.WAI.Naming для установления соединения с объектом Admin, который был зарегистрирован FlexiServer как FSA-Admin. Наконец, он вызывает метод narrow объекта AdminHelper для приведения полученного объекта к соответствующему типу Java-объекта. Этот Java-метод возвращает Java-объект, соответствующий распределённому объекту. Машина выполнения JavaScript обёртывает этот Java-объект как JavaScript-объект и сохраняет его как свойство объекта project. Теперь Вы можете вызывать методы и получать доступ к свойствам этого возвращённого объекта, как и любого другого Java-объекта. Другие страницы flexi работают через этот объект.

И ещё раз - о том, как работают CORBA-объекты, см. книгу  Netscape Internet Service Broker for Java Reference Guide.

Использование Объекта Admin для Администрирования и Просмотра Новых Счетов


Код во flexi создаёт другие объекты, кроме объекта Admin, и осуществляет к ним доступ во FlexiServer. Эти объекты создаются путём вызовов метода объекта Admin. Например, если служащий отправляет запрос, новый запрос создаётся в account-empl.html следующим оператором:


__claim = __account.submitClaim(
parseFloat(request.claimAmount),
   request.serviceDate,
request.providerName,
   request.details);

Этот код вызывает метод submitClaim объекта Account для создания нового запроса служащего. Реализация этого метода в файле impl\Account.java создаёт новый Claim-объект, который регистрируется в ORB и возвращается:


public Flexi.Claim submitClaim(float amount, String serviceDate,
   String providerName, String details)
{
Claim __clm = new Claim(this, amount, serviceDate,
       providerName, details);
   org.omg.CORBA.ORB.init().BOA_init().obj_is_ready(__clm);
   _current_clm = __clm;
System.out.println("***Created a new claim: " + __clm);
   return __clm;
};

Альтернативные Публикации


Имеются две альтернативы для публикации распределённых CORBA-объектов, представляющие интерес при работе с серверным JavaScript:

В этих альтернативных вариантах CORBA-клиент и CORBA-сервер оба работают в одном процессе web-сервера.

С этой точки зрения, если CORBA-клиент не является приложением JavaScript, первый вариант пригоден для тех же целей, что и в случае, когда CORBA-сервер запущен как отдельный процесс.

Однако второй вариант, создающий распределённый объект в приложении JavaScript, реально делает это приложение сервисом CORBA. Рисунок 22.3 иллюстрирует эти альтернативы.

Рисунок 22.3   Приложение JavaScript как CORBA-сервер

Ещё раз: среды выполнения Java и JavaScript находятся вместе на одном web-сервере. Они взаимодействуют через использование LiveConnect стандартным способом, описанным ранее в этой главе. В это случае, однако, процессы Java и JavaScript действуют вместе как CORBA-сервис. Этот сервис затем взаимодействует с CORBA-клинтом через ISB for Java стандартным способом. Образец-приложение bank это пример приложения JavaScript, реализующего CORBA-сервис.

В данном случае CORBA-клиент может находиться на любой машине, имеющей ORB с IIOP, и может быть написан на любом языке. Интересно то, что CORBA-клиент может быть клиентским приложением Java (и через LiveConnect на клиенте - клиентским приложением JavaScript). Это даёт совершенно другой способ взаимодействия клиентского приложения JavaScript с серверным приложением JavaScript.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 11
Конвертация Типов Данных

В этой главе рассматривается, как машина выполнения JavaScript на сервере конвертирует более сложные типы данных, используемые в реляционных БД, и простые типы.

В главе имеются следующие разделы:

О Конвертации Типов Данных


В БД имеется богатый набор типов данных. Машина выполнения JavaScript на сервере конвертирует эти типы данных в значения JavaScript, строки или числа. Число в JavaScript хранится как значение двойной точности с плавающей точкой. Вообще машина выполнения конвертирует символьные типы данных в строки, числовые типы данных - в числа, а даты - в Date -объекты JavaScript. Она также конвертирует null-значения в JavaScript null.

Примечание

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

Работа с Датами и Базами Данных


Значения даты, запрошенные из базы данных, конвертируются в Date -объекты JavaScript. Чтобы вставить значение даты в БД, используйте Date -объект JavaScript так:


cursorName.dateColumn = dateObj

Здесь cursorName это курсор, dateColumn это столбец, соответствующий дате, а dateObj это Date -объект JavaScript. Вы создаёте Date -объект, используя оператор new и Date -конструктор:


dateObj = new Date(dateString)

где dateString это строка, представляющая дату. Если dateString - пустая строка, создаётся Date -объект для текущей даты. Например:


custs.orderDate = new Date("Jan 27, 1997")
Примечание:

Базы Данных DB2 имеют типы данных time и timestamp. Эти типы конвертируются в тип Date в JavaScript.


ПРЕДУПРЕЖДЕНИЕ!
LiveWire Database Service не может обрабатывать даты после 5 февраля 2037 года. Дополнительно о работе с датами в JavaScript см. "Объект Date."

Конвертация Типов Данных Базой Данных


В следующей таблице показана конвертация, выполняемая машиной выполнения JavaScript для баз данных DB2.

Таблица 11.1  Конвертация Типов Данных DB2
Тип Данных DB2 Тип Данных JavaScript

char(n), varchar(n), long varchar, clob(n)

string

integer, smallint

integer

decimal, double

double

date, time, timestamp

Date

blob

Blob

В следующей таблице дана конвертация БД Informix.

Таблица 11.2  Конвертация Типов Данных Informix
Тип Данных Informix Тип Данных JavaScript

char, nchar, text, varchar, nvarchar

string

decimal(p,s), double precision, float, integer, money(p,s), serial, smallfloat, smallint

number

date, datetime 1

Date

byte

Blob

interval

Не поддерживается

1

Тип даты Informix datetime имеет точность переменных, определяемых пользователем. Серверный JavaScript выводит данные datetime в формате от YEAR до SECOND. Если datetime -переменная была определена с другой точностью, такой как от MONTH до DAY, она может быть отображена некорректно. В данном случае дата не нарушится некорректным отображением.

ODBC транслирует типы данных продавца в типы данных ODBC. Например, в Microsoft SQL Server тип данных varchar конвертируется в ODBC-тип SQL_VARCHAR. Дополнительно см. документацию ODBC SDK.
В следующей таблице показана конвертация, выполняемая машиной JavaScript для баз данных ODBC.

Таблица 11.3  Конвертация Типов Данных ODBC
Тип Данных ODBC Тип Данных JavaScript

SQL_LONGVARCHAR, SQL_VARCHAR, SQL_CHAR

string

SQL_SMALLINT, SQL_INTEGER, SQL_DOUBLE, SQL_FLOAT, SQL_REAL, SQL_BIGINT, SQL_NUMERIC, SQL_DECIMAL

number

SQL_DATE, SQL_TIME, SQL_TIMESTAMP

Date

SQL_BINARY, SQL_VARBINARY, SQL_LONGBINARY

Blob

В следующей таблице показана конвертация, выполняемая машиной выполнения JavaScript для баз данных Oracle.

Таблица 11.4  Конвертация Типов Данных Oracle

Тип Данных Oracle Тип Данных JavaScript

long, char(n), varchar2(n), rowid

string

number(p,s), number(p,0), float(p)

number

date

Date

raw(n), long raw

Blob

В следующей таблице показана конвертация, выполняемая машиной выполнения JavaScript для баз данных Sybase.

Таблица 11.5  Конвертация Типов Данных Sybase

Тип Данных Sybase Тип Данных JavaScript

char(n), varchar(n), nchar(n), nvarchar(n), text

string

bit, tinyint, smallint, int, float(p), double precision, real, decimal(p,s), numeric(p,s), money, smallmoney

number 1

datetime, smalldatetime

Date

binary(n), varbinary(n), image

Blob

1

Sybase-клиент ограничивает числовые типы данных 33 цифрами. Если Вы вставляете число JavaScript с большим количеством цифр в БД Sybase, Вы можете получить ошибку.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 8
Соединение с Базой Данных

В этой главе обсуждается использование службы LiveWire Database Service для соединения Вашего приложения с реляционными базами данных DB2, Informix, ODBC, Oracle или Sybase. Показано, как выбрать наилучшую методологию для Вашего приложения.

В главе имеются следующие разделы:

Взаимодействие с Базами Данных


Ваше JavaScript-приложение, запущенное на сервере Netscape Enterprise Server, может использовать LiveWire Database Service для доступа к БД серверов Informix, Oracle, Sybase и DB2 и серверов, использующих стандарт Open Database Connectivity (ODBC). Ваше приложение, запущенное на сервере Netscape FastTrack Server, может получать доступ только к БД на серверах, использующих ODBC.

В последующих обсуждениях предполагается, что Вы уже знакомы реляционными БД и Structured Query Language (SQL).

Прежде чем создать приложение JavaScript с использованием LiveWire, база или базы данных, к которым Вы планируете подключаться, должны уже существовать на сервере БД. Также Вы должны знать их структуру. Если Вы создаёте совершенно новое приложение, включающее БД, необходимо создать БД и заполнить её данными (как минимум в форме прототипа) до создания приложения.

До того как Вы попытаетесь использовать LiveWire, убедитесь, что Ваша рабочая среда сконфигурирована соответственно. О том, как конфигурировать, см. Главу 10, "Конфигурирование Вашей Базы Данных." Вы можете также использовать приложение-образец videoapp, описанное в Главе 13, "Приложения-Образцы Videoapp и Oldvideo," для изучения некоторых возможностей LiveWire.

Обычно для того чтобы взаимодействовать с БД, необходимо выполнить следующие общие действия:

  1. Использовать объект database или создать объект DbPool для установки пула соединений БД. Это обычно выполняется на начальной странице приложения, если только оно не требует установления специального соединения.
  2. Подключить пул к БД. Это также обычно выполняется на начальной странице приложения.
  3. Затребовать соединение из пула. Это выполняется неявно при использовании объекта database или явно - при использовании метода connection объекта DbPool.
  4. Если Вы изменяете информацию в БД, начинается транзакция. Транзакции БД обсуждаются в разделе "Обслуживание Транзакций ".
  5. Создать курсор или вызывать хранимую процедуру для работы с информацией из БД. Здесь может происходить вывод результатов выполнения запроса или обновление содержимого БД. Закройте открытый курсор, результирующий набор или хранимую процедуру после окончания их использования. Курсоры обсуждаются в разделе "Обслуживание Результатов Выполнения Запроса с Помощью Курсоров"; хранимые процедуры обсуждаются в разделе "Вызов Хранимых Процедур".
  6. Подтвердить транзакцию или выполнить откат.
  7. Освободить соединение с БД (если используете объекты Connection).

В этой главе обсуждаются первые три пункта действий. В Главе 9, "Работа с БД", обсуждаются остальные шаги.

Соединение. Подходы.


Есть два основных способа соединения с БД с помощью сервиса LiveWire Database Service. Это объекты DbPool и Connection, либо объект database.

Соединение с Помощью Объектов DbPool и Connection


При этом подходе Вы создаёте пул соединений для работы с реляционной БД. Вы создаёте экземпляр класса DbPool,а затем получаете доступ к объектам Connection через этот объект DbPool. Объекты DbPool и Connection распределяют между собой работу по соединению с БД и обслуживанию набора соединений и доступ к БД через соединение.

Это весьма гибкий подход. Ваше приложение может иметь несколько пулов соединений, каждый со своей собственной конфигурацией БД и пользователя. Каждый пул может иметь несколько соединений при такой конфигурации. Это даёт одновременный доступ к нескольким БД или к одной БД из нескольких бюджетов. Вы можете также ассоциировать пул непосредственно с приложением, а не с отдельным клиентским запросом, и иметь таким образом транзакции, захватывающие несколько клиентских запросов. Это ассоциирование выполняется путём присвоения пула свойству объекта project и удаления этого присвоения после окончания работы с пулом.

Соединение с Объектом database


При этом подходе Вы используете предопределённый объект database для соединения с БД при наличии единственной конфигурации соединения БД и пользователя. Объект database выполняет все действия по работе с БД. Можно представить этот объект как database единый пул соединений с БД.

Этот подход несколько проще, так как используется только один объект database, а не несколько объектов DbPool и Connection. Однако при этом теряется гибкость первого подхода. Если Вы используете только объект database и хотите соединиться с разными БД или разными бюджетами, Вы обязаны отключиться от одной конфигурации, для того чтобы подключиться к другой. Также, при использовании объекта database, одна транзакция не может захватить несколько клиентских запросов, а соединения с несколькими БД-источниками не могут быть установлены одновременно.

Как описано в последующих разделах, Вы должны ответить на два основных вопроса, когда решаете, как устанавливать соединения с БД:

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

Таблица 8.1  Рассмотрение создания пулов БД
Сколько конфигураций БД? Где соединение с пулом? Где отключение пула? Какой объект(ы) содержит пул? Должен ли Ваш код хранить пул и соединение? Как Ваш код хранит пул и соединение в объекте project?

1, используется всеми клиентами

Начальная страница приложения

Нигде

database

Нет

--

1, используется всеми клиентами

Начальная страница приложения

Нигде

1 DbPool object

Да

DbPool: Именованное свойство;

Connection: 1 массив

Фиксированный набор, используется всеми клиентами

Начальная страница приложения

Нигде

N DbPool-объектов

Да

DbPool: Именованное свойство;

Connection: N массивов

Отдельный пул для каждого клиента

Клиентская страница запроса

Зависит от 1

Многие объекты DbPool

Только если соединение захватывает клиентские запросы

DbPool: 1 массив;

Connection: 1 массив

1

Если отдельное соединение не захватывает клиентские запросы, Вы можете соединять и отсоединять пул на каждой странице, в которой нужнó соединение. В этом случае пул не сохраняется в промежутке времени между запросами. Если отдельное соединение захватывает клиентские запросы, соединяйте на первой клиентской странице, которой необходимо соединение, и отсоединяйте на последней такой странице. Это может привести к появлению незанятых соединений/idle, и Ваше приложение должно будет обработать такую ситуацию.

Пулы Соединений с БД


Если Вы хотите использовать объект database, Вам не нужно создавать его. Это предопределённый объект, предоставляемый машиной выполнения JavaScript. Если Вам нужны дополнительные возможности класса DbPool, Вы создаёте экземпляр класса DbPool и соединяете этот объект с конкретной БД, которая создаёт пул соединений.

Вы можете создать общий DbPool-объект и специфицировать позднее информацию соединения (используя метод connect), или можете специфицировать информацию соединения при создании пула. Общий DbPool-объект не имеет никаких доступных соединений в момент его создания. Исходя из этого, Вам может понадобиться установить соединение при создании этого объекта. Если Вы используете объект database, Вы всегда обязаны устанавливать соединение путём вызова метода database.connect.


connect (dbtype, serverName, userName, password, 
   databaseName, maxConnections, commitFlag);

При создании соединения Вы можете специфицировать следующую информацию, либо при создании DbPool-объекта, либо при вызове метода connect объекта DbPool или database:

Например, следующий оператор создаёт новый пул БД из 5 соединений с БД Oracle. В этом пуле неподтверждённые транзакции откатываются:


pool = new DbPool ("ORACLE", "myserver1", "ENG", "pwd1", "", 5);

Приложение-образец dbadmin позволяет Вам экспериментировать с соединениями с различными БД как разным пользователям.

Для многих приложений Вы, возможно, захотите выполнять совместное использование набора соединений несколькими клиентами, или чтобы соединение захватывало несколько клиентских запросов. В этих случаях Вы должны устанавливать соединение на начальной странице Вашего приложения. Это позволит исключить возможные проблемы в тех случаях, когда отдельные клиенты выполняют совместные соединения с БД.

Однако для некоторых приложений каждый клиент должен выполнять своё собственное соединение. Как сказано в разделе "Совместное Использование Массива Пулов Соединений," клиенты могут совместно использовать объекты. Если это так, убедитесь, что блокировки используются для управления совместным использованием данных, как указано в разделе "Безопасное Использование Объектов с Помощью Блокировки".

В следующей таблице показаны методы объектов DbPool и database для обслуживания пула соединений. (Объект database использует другие методы, рассмотренные ранее, для работы с соединением с БД.)

Таблица 8.2 Методы объектов DbPool и database для обслуживания пулов соединений

connect

Соединяет пул с определённой конфигурацией БД и пользователя.

connected

Проверяет, соединён ли пул и все его соединения с базой данных.

connection

(Только DbPool) Запрашивает доступный Connection-объект из пула.

disconnect

Отсоединяет все соединения пула от БД.

majorErrorCode

Главный код ошибки, возвращаемый сервером БД или ODBC.

majorErrorMessage

Главное сообщение об ошибке, возвращаемое сервером БД или ODBC.

minorErrorCode

Вторичный код ошибки, возвращаемый библиотекой продавца.

minorErrorMessage

Вторичное сообщение об ошибке, возвращаемое библиотекой продавца.

Однопоточные и Многопоточные Базы Данных


LiveWire поддерживает многопоточный доступ к БД. То есть она поддерживает наличие более чем одного потока доступа к одной БД в единицу времени. Отсюда ясно, для чего нужен пул соединений с более чем одним соединением. Однако библиотеки БД некоторых производителей не являются многопоточными. Для таких БД не имеет значения, сколько соединений имеется в Вашем пуле, так как только одно соединение может устанавливаться с БД в единицу времени.

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

Таблица 8.3  Многопоточность БД-клиентов на разных платформах
Sybase Informix Oracle DB2 ODBC 1

NT

Есть

Есть

Есть

Есть

Есть

Sun Solaris

Есть

Есть

Есть

Нет

Нет

HP-UX

Есть

Есть

Нет

Нет

Нет

IBM AIX

Есть

Есть

Нет

Есть

Нет

SGI IRIX

Нет

Нет

Нет

Не поддерживается

Нет

Digital Unix

Есть

Есть

Нет

Не поддерживается

Не поддерживается

1

Все многопоточные тесты для ODBC были сделаны на MS SQL Server. Если Вы используете другой драйвер ODBC, узнайте у производителя, является ли драйвер многопоточным.

Советы


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

Ограничения на использование транзакций для клиентских библиотек БД, которые не являются многопоточными:

Обслуживание Пулов Соединений


В любой данный момент времени соединённый объект DbPool или database и все соединения пула ассоциированы с определённой конфигурацией базы данных. То есть всё, что находится в пуле, соединено с определённым сервером БД как отдельный пользователь с отдельным паролем и с определённой БД.

Если Ваше приложение всегда использует одну конфигурацию, то можно использовать единственный объект DbPool или использовать объект database и соединяться однократно. В этом случае Вы должны выполнить соединение на начальной странице Вашего приложения.

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

Если Вы используете объект database и несколько соединений, то выбора у Вас нет. Вы обязаны соединяться, отсоединяться и повторно соединяться с объектом database каждый раз, когда Вам нужно изменить что-либо в конфигурации. Вы делаете это под управлением клиентских запросов. В этой ситуации убедитесь, что используются блокировки, как указано в разделе "Совместное Использование Объектов с Блокировкой," чтобы получать исключительный доступ к объекту database. Иначе другой клиентский запрос может отключить объект до того, как текущий клиентский запрос закончит с ним работу. Хотя Вы и можете использовать объект database таким образом, лучше будет всё-таки использовать объекты DbPool.

Если Вы используете объекты DbPool и несколько конфигураций, Вы также должны соединяться, отсоединяться и повторно соединяться с объектом DbPool. Однако с объектами DbPool у Вас появится больше возможностей. Вы можете создавать столько пулов, сколько нужно, и ставить их под контроль объекта project. (См. в Главе 6, "Обслуживание Сессий" информацию об объекте project.) Использование нескольких пулов более эффективно и обычно надёжнее, чем многократное использование единственного пула (как с объектом database , так и с единственным объектом DbPool).

При определении того, как обслуживать пулы, Вы обязаны учитывать два фактора: ко скольки конфигурациям будут иметь доступ пулы и нужно ли будет одному соединению захватывать несколько клиентских запросов. Если у Вас небольшое количество возможных конфигураций, Вы можете создать отдельные пулы для каждой. В разделе "Совместное Использование Фиксированного Набора Пулов Соединений" обсуждается этот подход.

Если у Вас имеется очень большое или заранее не известное количество конфигураций (например, если все пользователи БД получают свои индивидуальные ID), нужно предусмотреть два варианта. Если одного соединения достаточно для выполнения одного клиентского запроса, Вы можете создавать отдельные пулы на клиентской странице.

Однако иногда соединение должно захватывать несколько клиентских запросов (например, если одна транзакция в БД захватывает несколько клиентских запросов). Возможно также, что Вы просто не хотите повторно соединяться с БД на каждой странице приложения. Если это так, Вы можете создать массив пулов, который используется совместно. В разделе "Совместное Использование Массива Пулов Соединений" обсуждается этот подход.

Независимо от используемого подхода, если Вам больше не нужно отдельное соединение в пуле, зачистите ресурсы, используемые этим соединением, чтобы оно стало доступным для других пользователей. Чтобы выполнить это, закройте все открытые курсоры, хранимые процедуры и результирующие наборы. Верните соединение обратно в пул. (Вы не должны освобождать соединение, если используете объект database.)

Если Вы не освободили соединение, то при попытке отсоединить пул система будет ожидать, перед тем как реально отсоединиться, возникновения одного из двух условий:

Если Вы создаёте отдельные пулы БД для каждого пользователя, убедитесь, что пул отсоединён, до того как закончить с ним работу. О курсорах см "Манипуляции с Результатами Выполнения Запросов с Помощью Курсоров". О хранимых процедурах и результирующих наборах см. "Вызов Хранимых Процедур".

Совместное Использование Фиксированного Набора Пулов Соединений


Часто в приложении небольшой набор пулов соединений используется всеми пользователями данного приложения. Например, Вашему приложению нужно соединяться с тремя различными БД или с одной БД, которая использует 4 пользовательских ID, соответствующих 4 разным департаментам. Если у вас имеется небольшой набор возможных конфигураций соединения, Вы можете создать отдельный пул для каждой конфигурации. Для этого используйте объекты DbPool.

Тогда необходимо, чтобы пул работал в течение всего периода существования приложения, а не просто в течение периода существования клиента или отдельного клиентского запроса. Вы можете реализовать это, создав каждый пул БД как свойство объекта project. Например, начальная страница приложения может содержать эти операторы:


project.engpool = new DbPool ("ORACLE", "myserver1", "ENG",
   "pwd1", "", 5, true);
project.salespool = new DbPool ("INFORMIX", "myserver2", "SALES",
   "pwd2", "salsmktg", 2);
project.supppool = new DbPool ("SYBASE","myserver3","SUPPORT",
   "pwd3", "suppdb", 3, false);

Эти операторы создают три пула для различных групп пользователей приложения.
Пул project.eng содержит 5 соединений Oracle и подтверждает любую неподтверждённую транзакцию при высвобождении соединения обратно в пул.
Пул project.sales имеет два соединения Informix и откатывает любую неподтверждённую транзакцию при окончании соединения.
Пул project.supp имеет три соединения Sybase и откатывает любую неподтверждённую транзакцию при окончании соединения.

Вы должны создавать такой пул как часть начальной страницы приложения. Эта страница выполняется только при старте приложения. На страницах, доступных пользователям, Вы не создаёте пул и не изменяете соединение. Вместо этого эти страницы определяют, к какой группе принадлежит текущий пользователь, и используют уже установленное соединение из соответствующего пула. Например, в следующем коде определяется, какую БД использовать (на основе значения свойства userGroup объекта request), в БД ищется некоторая информация, которая выводится пользователю, а затем соединение освобождается:


if (request.userGroup == "SALES") {
   salesconn = project.salespool.connection("A sales connection");
   salesconn.SQLTable ("select * from dept");
   salesconn.release();
}

Вы можете также создать пул и изменить соединение на странице, доступной пользователю. В этом случае Вы должны быть осторожны, так как несколько пользователей, осуществляющих одновременный доступ к этой странице, не должны мешать друг другу. Например, только один пользователь должен иметь возможность создавать пул, используемый всеми остальными пользователями. О надёжности совместного использования информации см. раздел "Надёжное Совместное Использование Объектов с Помощью Блокировки".

Совместное Использование Массива Пулов Соединений


В разделе "Совместное Использование Фиксированного Набора Пулов Соединений" описано, как Вы можете применить свойства объекта project для совместного использования фиксированного набора пулов соединений. Этот подход используется, если Вам в процессе разработки уже известно количество необходимых пулов соединений и Вам нужно только небольшое количество соединений.

Часто нельзя предугадать заранее количество необходимых пулов соединений. В других случаях это возможно, но это количество недопустимо велико. Например, предположим, что для каждого потребителя, имеющего доступ к Вашему приложению, приложение проверяет пользовательский профиль на предмет определения того, какую информацию из БД вывести. Вы можете дать каждому потребителю уникальный пользовательский идентификатор ID для БД. Такое приложение требует, чтобы каждый пользователь имел свой набор параметров соединений (соответствующий различным пользовательским ID в БД) и, соответственно, разные пулы соединений.

Вы можете создать объект DbPool и соединять и отсоединять его на каждой странице приложения. Это будет работать, только если одно соединение не должно захватывать несколько клиентских запросов. Иначе эта ситуация должна обрабатываться по-разному.

Для данного приложения, вместо создания фиксированного набора пулов соединений на начальной странице приложения или пула на каждой клиентской странице, Вы создаёте одно свойство объекта project, которое будет содержать массив пулов соединений. Доступ к элементам этого массива осуществляется по ключу на базе определённого пользователя.
Во время инициализации Вы создаёте массив, но не помещаете в него элементы (поскольку никто ещё не пытался использовать приложение), как показано здесь:


project.sharedPools = new Object();

Когда пользователь впервые стартует приложение, оно получает идентифицирующий пользователя ключ. На основе этого ключа приложение создаёт объект пула DbPool и сохраняет его в массиве пулов. Имея данный пул соединений, оно может либо соединяться на каждой странице, либо устанавливать соединение так, как описано в разделе "Обслуживание Соединения по Запросам." Следующий код создаёт пул либо получает уже созданный, проверяет его соединение и работает затем с БД:


// Генерируется уникальный индекс для обращения к данному клиенту, если это
// ещё не было сделано на другой странице. О функции ssjs_generateClientID см.
// "Уникальное Обращение к Объекту client". if client.id == null {
   client.id = ssjs_generateClientID();
}

// Если пула для данного клиента ещё нет, он создаётся
// и производится его соединение с БД. project.lock();
if (project.sharedPools[client.id] == null) {
   project.sharedPools[client.id] = new DbPool ("ORACLE",
      "myserver", user, password, "", 5, false);
}
project.unlock();

// Для удобства устанавливается переменная для этого пула.

var clientPool = project.sharedPools[client.id];

// Теперь у Вас есть пул: посмотрим, соединён ли он. Если нет, попытаемся соединить его.
// Если это не удаётся, перенаправляем на специальную страницу,
// чтобы проинформировать пользователя.
project.lock();
if (!clientPool.connected()) {
   clientPool.connect("ORACLE", "myserver", user, password,
      "", 5, false);
   if (!clientPool.connected()) {
      delete project.sharedPools[client.id];
      project.unlock();
      redirect("noconnection.html");
   }
}
project.unlock();

// Если Вы дошли до этого места, Вы успешно соединились и
// можете работать с БД.
clientConn = clientPool.connection();
clientConn.SQLTable("select * from customers");
// ... другие операции с БД ...

// Всегда освобождайте соединение, если оно Вам больше не нужно.

clientConn.release();
}

Когда пользователь в следующий раз войдёт в приложение (например, с другой страницы приложения), он использует тот же самый код и получит сохранённый пул соединений и (возможно, сохранённый,) объект Connection из объекта project.

Если Вы используете ssjs_generateClientID и сохраняете ID в объекте client, Вам может понадобиться защита от вторжения через доступ к этому ID и, следовательно, к закрытой информации.

ПРИМЕЧАНИЕ:

Объект sharedConns, использованный в этом примере кода, не является предопределённым объектом JavaScript. Он просто создан в этом примере и может иметь другое имя по Вашему выбору.

Индивидуальные Соединения с Базой Данных


Как только Вы создали пул соединений, клиентская страница может получить доступ к индивидуальному соединению из пула. Если Вы используете объект database, соединение в данном объекте является неявным; то есть Вы используете методы объекта database для доступа к соединению. Если, однако, Вы используете объекты DbPool, соединение инкапсулируется в объекте Connection, который Вы получаете через вызов метода объекта DbPool. Например, в следующем пуле:


project.eng = new DbPool ("ORACLE", "myserver", "ENG", "pwd1", "", 5);

Вы можете получить соединение из пула с помощью такого вызова метода:


myconn = project.eng.connection ("My Connection", 60);

Оба параметра метода являются необязательными. Первый это имя соединения (используется при отладке); второй это целое число, обозначающее таймаут в секундах. В этом примере, если пул имеет доступное соединение или если оно становится доступным в течение 60 секунд, это соединение присваивается переменной myconn. Если соединение не становится доступным в течение указанного периода, этот метод возвращается без соединения. Дополнительно об ожидании получения соединения из пула см. раздел "Ожидание Соединения". О том, что делать, если соединение не получено, см. "Запрашивание Незанятого Соединения".

Если Вы закончили использование соединения, возвратите его в пул путём вызова метода release объекта Connection. (Если Вы используете объект database, Вам не нужно самостоятельно освобождать соединение). Прежде чем вызвать метод release, закройте все открытые курсоры, хранимые процедуры и результирующие наборы. Если Вы вызываете метод release, система ожидает, когда всё закроется, и возвращает затем соединение в пул базы данных. После этого соединение доступно следующему пользователю. Об использовании курсоров см. "Манипуляции с Результатами Запросов с Помощью Курсоров". О хранимых процедурах и результирующих наборах см. "Вызов Хранимых Процедур".

После получения соединения (через объект database или объект Connection), Вы можете работать с БД. В таблице резюмированы методы объектов database и connection для работы с единственным соединением. Объект database имеет и другие методы для обслуживания пула соединений, рассмотренные в разделе "Обслуживание Пулов Соединений."

Таблица 8.4  Методы Объектов database и Connection для Работы с Единственным Соединением
Метод Описание

cursor

Создаёт курсор БД для специфицированного оператора SQL SELECT.

SQLTable

Отображает результаты выполнения запроса. Создаёт таблицу HTML для результата выполнения оператора SQL SELECT.

execute

Выполняет специфицированный оператор SQL. Используется для операторов SQL, отличных от запросов/queries.

connected

Возвращает true, если пул БД (и, следовательно, данное соединение) соединён с БД.

release

(Только для Connection) Освобождает соединение обратно в пул.

beginTransaction

Начинает транзакцию SQL.

commitTransaction

Подтверждает текущую транзакцию SQL.

rollbackTransaction

Выполняет откат текущей транзакции SQL.

storedProc

Создаёт объект хранимой процедуры и запускает специфицированную хранимую процедуру БД.

majorErrorCode

Важнейший код ошибки, возвращаемый сервером БД или ODBC.

majorErrorMessage

Сообщение о важнейшей ошибке, возвращаемое сервером БД или ODBC.

minorErrorCode

Второй по значению код ошибки, возвращаемый библиотекой производителя.

minorErrorMessage

Второе по значению сообщение о важнейшей ошибке, возвращаемое библиотекой производителя.

Обслуживание Соединения по Нескольким Запросам


В некоторых случаях может понадобиться, чтобы единственное соединение захватывало несколько клиентских запросов. То есть Вы сможете использовать одно соединение на нескольких страницах HTML.

Обычно вы используете свойства объекта client для информации, захватывающего клиентские запросы. Однако значение свойства объекта client не может быть объектом. Исходя из этого, Вы не можете сохранять пул соединений БД в объекте client. Вместо этого Вы используете пул соединений, хранимый в объекте project, обслуживая их так, как описано в данном разделе. Если вы используете этот подход, Вам может понадобиться кодирование пользовательской информации, по соображениям безопасности.

ПРЕДУПРЕЖДЕНИЕ!

Будьте особенно осторожны при использовании такого подхода, поскольку сохранение соединения таким способом делает его недоступным для других пользователей. Если все соединения окажутся недоступны, новые запросы будут ожидать явного освобождения соединения или таймаута соединения. Это особенно проблематично для однопоточных библиотек БД. (Об установлении соединений так, что они будут запрашиваться, если не заняты в течение продолжительного времени, см. "Запрашивание Незанятого Соединения").

 В следующем примере соединение и транзакция захватывают несколько клиентских запросов. Код сохраняет соединение как свойство объекта sharedConns, который сам является свойством объекта project. Объект sharedConns не является предопределённым объектом JavaScript. Он просто создан в данном примере и может иметь другое имя, по Вашему выбору.

Поскольку один пул используется всеми клиентами, Вы должны создавать объект sharedConns и создавать и соединять сам пул на начальной странице приложения примерно таким кодом:


project.sharedConns = new Object();
project.sharedConns.conns = new Object();
project.sharedConns.pool = new DbPool ("SYBASE", "sybaseserver",
   "user", "password", "sybdb", 10, false);

Затем на первой клиентской странице, получающей доступ к пулу, следуйте такой стратегии:


// Генерируется уникальный индекс для обращения к данному клиенту, если он ещё
// не сгенерирован на другой странице.
if client.id == null {
   client.id = ssjs_generateClientID();
}

// Для удобства устанавливается переменная для данного пула. 

var clientPool = project.sharedConns.pool;

// Проверяется, соединён ли пул. Если нет, перенаправляется
// на специальную страницу для информирования пользователя.
project.lock();
if (!clientPool.connected()) {
   delete project.sharedConns.pool;
   project.unlock();
   redirect("noconnection.html");
}
project.unlock();

// Соединение получается из пула и сохраняется в объекте project.

project.sharedConns.conns[client.id] = clientPool.connection();
var clientConn = project.sharedConns.conns[client.id];

clientConn.beginTransaction();
cursor = clientConn.cursor("select * from customers", true");
// ... другие операции с БД ...
cursor.close();

}

Заметьте, что эта страница не выполняет откат или подтверждение транзакции. Соединение остаётся открытым, и транзакция продолжается. (Транзакции рассматриваются в разделе "Обслуживание Транзакций").
Вторая HTML-страница запрашивает соединение, базируясь на значении client.id, и продолжает работать с БД так:


// Запрашивается соединение.

var clientConn = project.sharedConns.conns[client.id];

// ... Выполняются ещё какие-нибудь операции с БД ...
// Здесь, если операции с БД успешно прошли, okay устанавливается в 1.
// Если была ошибка при работе с БД, okay устанавливается в 0. В конце
// подтверждается или откатывается транзакция на основе этого значения.
if (okay)
   clientConn.commitTransaction();
else
   clientConn.rollbackTransaction();

// Соединение возвращается в пул.
clientConn.release();

// Избавляемся от значения свойства объекта. Оно Вам больше не нужно. 
delete project.sharedConns.conns[client.id];

В этом примере объект sharedConns сохраняет единственный объект DbPool и соединения для данного пула, которые используются в данный момент. Ситуация может быть значительно сложнее. Если у Вас имеется фиксированный набор пулов БД, Вы можете определить отдельный объект для хранения соединений каждого пула.
Если у вас имеется массив пулов и каждому пулу необходимы соединения, захватывающие несколько запросов, Вам необходимо создать массив объектов, каждый из которых сохраняет пул и массив его соединений. Как ответвление, вместо немедленного перенаправления в том случае, если пул не соединён, клиентская страница может сделать новую попытку установить соединение.

Если Вы используете ssjs_generateClientID и храните ID в объекте client, Вам понадобится защита от вторжения и получения доступа к ID и, следовательно, к закрытой информации.

Ожидание Соединения


В пуле, созданном объектом DbPool, соединений имеется фиксированное количество соединений. Если в момент попытки доступа все соединения заняты, Ваше приложение ожидает освобождения соединения в течение специфицированного периода таймаута. Вы можете управлять периодом ожидания.

Предположим, Вы определили следующий пул из 3 соединений:


pool = new DbPool ("ORACLE", "myserv", "user", "password", "", 3);

Предположим далее, что три клиента одновременно получают доступ к приложению и каждый использует одно из трёх соединений. Четвёртый клиент теперь запрашивает соединение через следующий вызов:


myconnection = pool.connection();

Этот клиент обязан ждать, пока один из трёх клиентов не освободит соединение. В данном случае, поскольку вызов connection не специфицирует таймаут, клиент ждёт освобождения соединения неопределённо долго, а затем возвращает это соединение.

Вы можете специфицировать различные периоды таймаута, задавая аргументы метода connection. Второй аргумент метода connection это период таймаута в секундах. Если Вы специфицируете таймаут 0, система ждёт бесконечно долго. Например, следующий код ожидает соединения только 30 секунд перед таймаутом:


myconnection = pool.connection ("Name of Connection", 30);

Если в течение специфицированного периода соединение не освобождается, метод возвращает null, и в сообщение об ошибке устанавливается сообщение о наименьшей ошибке. Вы можете получить это сообщение, вызвав метод minorErrorMessage объекта pool. Если Вы вызываете таймаут из connection, Вам может понадобиться освободить соединение, отключив одно из уже установленных. Дополнительно см. "Запрашивание Свободного Соединения".

Запрашивание Свободного Соединения


Если Ваше приложение запрашивает соединение из объекта DbPool, оно может не получить его. Доступные опции в этот момент зависят от архитектуры Вашего приложения.

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

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

Вы можете вручную запросить соединение, зачистив его и освободив в пул БД. Чтобы сделать это, напишите функции типа нижеследующих:

Ваше приложение может использовать эти функции так:

  1. Когда Вы получаете новое соединений, вызывайте Bucket для создания объекта bucket.
  2. На любой странице, получающей доступ к соединению, вызывайте MarkBucket для обновления штампа времени.
  3. Если приложение делает паузу (таймаут), пытаясь получить соединение их пула, вызывайте RetrieveConnection для поиска незанятых соединений, закройте все открытые курсоры, подтвердите или откатите работающие транзакции и верните незанятые соединения обратно в пул.
  4. Если соединение было возвращено в пул, попытайтесь получить соединение из пула.

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

Создание Bucket

Функция bucket содержит соединение и штамп времени. Этот образец конструктора функции принимает соединение в качестве единственного параметра:


// Конструктор для Bucket

function Bucket(c)
{
   this.connection = c;
   this.lastModified = new Date();
}

Вы можете вызвать эту функцию для создания bucket для соединения, когда Вы получаете соединение из пула соединений. Вы можете добавить другие свойства для соединения bucket. Например, Ваше приложение может содержать курсор, который захватывает клиентские запросы. Тогда Вы можете использовать свойство для добавления курсора в bucket, так чтобы можно было закрыть открытый курсор при запрашивании соединения. Вы сохраняете курсор в bucket во время его создания, как видно из следующего оператора:


myBucket.openCursor = 
   myBucket.connection.cursor("select * from customer", true);
Пометка Объекта Bucket

Функция MarkBucket принимает объект Bucket в качестве параметра и устанавливает в поле lastModified текущее время.


function MarkBucket(bucket)
{
   bucket.lastModified = new Date();
}

Вызывайте MarkBucket на каждой странице приложения, которая использует соединение, содержащееся в bucket. Это восстанавливает в lastModified значение текущей даты и предотвращает появление незанятых соединений.

Запрашивание Старых Соединений

RetrieveConnections сканирует массив объектов Bucket, ищет buckets соединения, штамп времени которых установлен ранее некоторого определённого времени. Если соединение найдено, функция вызывает CleanBucket (описан далее) для возвращения соединения в пул БД.


// Запрашиваются соединения, не занятые в течение специфицированного количества минут.

function RetrieveConnections(BucketArray, timeout)
{
   var i;
   var count = 0;
   var now;

   now = new Date();


   // Этот цикл выполняется для каждого bucket в массиве.
   for (i in BucketArray) {


 // Вычисляется разница во времени между текущей/now и последней/last
 // модифицированной датой. Эта разница выражается в миллисекундах.
// Если она больше значения timeout, вызывается функция зачистки.

      
if ((now - i.lastModified)/60000) > timeout) {
CleanBucket(i);

// Избавляется от bucket, поскольку он больше не используется.
  delete i;

count = count + 1;
      }
   }  return count;
}
Зачистка Bucket

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


function CleanBucket(bucket)
{
   bucket.openCursor.close();
   bucket.connection.rollbackTransaction();
   bucket.connection.release();
}

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

Направление Их Всех в Пул

Следующий пример кода использует уже определённые функции для запрашивания соединений, к которым не обращались в течение 10 минут. Сначала создаётся совместно используемый массив соединений и пул БД с 5 соединениями:


if ( project.sharedConns == null ) {
   project.sharedConns = new Object();
   project.sharedConns.pool = new DbPool ("ORACLE", "mydb",
      "user", "password", "", 5, false);
   if ( project.sharedConns.pool.connected() ) {
      project.sharedConns.connections = new Object();
   }

else {
      delete project.sharedConns;
   }
}

Теперь используем следующий код для попытки получения соединения. После зачистки пула генерируется клиентский ID, который затем используется как индекс в массиве соединений. Далее пытаемся получить соединение. Если возникает таймаут, вызываем RetrieveConnections для возвращения старого соединения в пул.
Если RetrieveConnections возвращает соединение в пул, пытаемся получить соединение вновь. Если всё ещё не можем получить соединение, выполняется перенаправление на другую страницу с информацией, что свободных соединений нет. Если запрашивается соединение, сохраняем его в новом bucket соединения и сохраняем этот bucket соединения в совместно используемом массиве соединений.


if ( project.sharedConns != null ) {
   var pool = project.sharedConns.pool;

   // Этот код запускается, только если пул уже соединён.
   // Если нет, возможно, Вам нужен код для соединения.
   if ( pool.connected() == true ) {

      // Генерируется клиентский ID. 
      client.id = ssjs_generateClientID();

      // Попытка получить соединение.
      var connection = pool.connection("my connection", 30);

      // Если соединение null, тогда ничего не будет доступно
      // в течение специфицированного лимита времени. Пытаемся запросить старые соединения.

      if (connection == null) {

         // Запрашиваются соединения, не используемые в течение последних 10 минут.
var count = RetrieveConnections(project.sharedConns.connections, 10);

         // Если count не равен 0, делаем какое-нибудь соединение доступным.
if (count != 0){
connection = pool.connection("my connection", 30);
    // Если connection всё ещё null, отказываемся.
      if (connection == null)
        redirect("nofreeconnections.html");
      }
         else {
            // Отказываемся.
         redirect("nofreeconnections.html");
       }}

      // Если Вы не дошли досюда, Вы получили соединение и можете продолжить работу.
      // Поместите это connection в новый bucket, стартуйте транзакцию,
      // получайте курсор, сохраняйте его в bucket и продолжайте работу.
      project.sharedConns.connections[client.id] =         new Bucket(connection);
 connection.beginTransaction();
project.sharedConns.connections[client.id].cursor =
connection.cursor("select * from customer", true);

      // Помечаем bucket соединения как использованный.
      MarkBucket(project.sharedConns.connections[client.id]);

   // Операторы Базы Данных.
   ...
}

На следующей странице многостраничной транзакции выполняются операции БД по этому соединению. После последней операции БД по соединению помечается bucket соединения:


var Bucket = project.sharedConns.connections[client.id];


if ( Bucket == null) {

   // Повторное соединение.
}

else {

   // Взаимодействие с БД.
...

   // Последняя операция БД на странице.
   row = Bucket.cursor.next();
   row.customerid = 666;
 Bucket.openCursor.insertRow("customer");

   // Помечается bucket соединения как использованный на данной странице.

   MarkBucket(Bucket);
}
Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 9
Работа с Базой Данных

В этой главе обсуждается работа с реляционными базами данных DB2, Informix, ODBC, Oracle и Sybase. Рассматривается, как запрашивать информацию из БД и использовать её в приложении, как работать с транзакциями и как выполнять хранимые процедуры.

Не забывайте, что, если Ваше приложение работает на Netscape FastTrack Server, а не на Netscape Enterprise Server, оно может иметь доступ только к серверам БД, использующим стандарт ODBC.

В главе имеются следующие разделы:

Взаимодействие с Реляционной Базой Данных


Сервис LiveWire Database Service даёт возможность взаимодействовать с реляционной БД различными способами.
Вы можете:

Об установке и обслуживании соединений БД см. Главу 8, "Соединение с Базой Данных".

Автоматическое Отображение Результатов Выполнения Запроса


Наиболее простым и быстрым способом отобразить результаты выполнения запросов к БД является использование метода SQLTable объекта database или объекта Connection. Метод SQLTable принимает оператор SQL SELECT и возвращает HTML-таблицу. Каждый ряд и столбец в запросе это ряд и столбец таблицы. Таблица HTML имеет также заголовочную ячейку для каждого столбца таблицы БД.

Метод SQLTable не даёт Вам возможности управлять форматированием вывода. Кроме того, если вывод содержит объект Blob, этот объект не выводится как изображение. (Об использовании blob см. раздел "Работа с Бинарными Данными"). если Вы хотите специализировать вывод, используйте курсор БД для создания Вашей собственной функции вывода/отображения. См. также "Манипуляции с Результатами Выполнения Запросов с Помощью Курсоров".

В качестве примера: если myconn это Connection -объект, следующий оператор JavaScript отображает результат выполнения запроса к БД в виде таблицы:


myconn.SQLTable("select * from videos");

Вот первая часть таблицы, которая могла бы быть сгенерирована этим оператором:
 

Title ID Year Category Quantity On Hand Synopsis

A Clockwork Orange

1

1975

Science Fiction

5

3

Little Alex and his droogies stop by the Miloko bar for a refreshing libation before a wild night on the town.

Philadelphia Story

1

1940

Romantic Comedy

Katherine Hepburn and Cary Grant are reunited on the eve of her remarriage, with Jimmy Stewart for complications.

Выполнение Произвольных Операторов SQL


Метод execute объекта database или объекта Connection даёт приложению возможность выполнять произвольный оператор SQL. Использование execute называется выполнением передаваемого SQL, поскольку этот метод передаёт SQL непосредственно на сервер.

Вы можете использовать execute для выполнения оператора SQL любого языка определения данных/data definition language (DDL) или языка манипулирования данными/data manipulation language (DML), поддерживаемого сервером БД. Примером могут служить операторы CREATE, ALTER и DROP. Хотя Вы можете использовать execute для выполнения любого оператора SQL, Вы не можете с помощью этого метода возвращать данные.

Обратите внимание, что execute служит для выполнения стандартных операторов SQL, а не для выполнения расширений SQL, поставляемых некоторыми производителями БД. Например, Вы не можете вызвать функцию Oracle describe или функцию Informix load из метода execute.

Для выполнения передаваемых операторов SQL просто задайте оператор SQL как параметр метода execute. Например, Вам нужно удалить таблицу из БД, на которую имеется ссылка в свойстве oldtable объекта project. Чтобы выполнить это, Вы можете использовать такой вызов метода:


connobj.execute("DROP TABLE " + project.oldtable);
Важно!

При использовании execute Ваш SQL-оператор обязан строго соответствовать требованиям синтаксиса SQL данного сервера БД. Например, некоторые серверы требуют, чтобы каждый оператор SQL заканчивался символом "точка с запятой". Дополнительно см. документацию к Вашему серверу БД.
Если Вы не стартуете транзакцию явно, единственный оператор подтверждается автоматически. Об управлении транзакциями см. "Обслуживание Транзакций".

Для выполнения некоторых операций, таких как создание и удаление таблиц, Вам могут понадобиться права доступа, предоставляемые администратором базы данных. См. документацию Вашего сервера БД и обратитесь к администратору сервера БД.

Манипуляции с Результатами Выполнения Запросов с Помощью Ку́рсоров


Часто Вам необходимо не просто отобразить таблицу с результатами выполнения запроса, но изменить форматирование этих результатов или даже выполнить какую-нибудь их обработку. Для манипуляций результатами выполнения запроса Вы работаете с курсором БД, возвращаемым запросом к БД. Для создания экземпляра класса Cursor вызовите метод cursor объекта database или объекта Connection, передав ему оператор SQL SELECT в качестве параметра.

Вы можете представить курсор как виртуальную таблицу с рядами и столбцами, специфицированный по запросу. Курсор предполагает также понятие текущего ряда, который в реальности является указателем на ряд виртуальной таблицы. Когда Вы выполняете операции с курсором, они обычно воздействуют на текущий ряд.

По окончании работы, закройте курсор БД путём вызова его метода close. Соединение с БД не может быть освобождено, пока не закрыты все ассоциированные с ним курсоры. Например, если Вы вызываете метод release объекта Connection и это соединение имеет ассоциированный курсор, который не был закрыт, соединение не будет освобождено, пока курсор не будет закрыт.

В таблице обобщены методы и свойства класса Cursor.

Таблица 9.1  Свойства и Методы Класса Cursor
Метод или Свойство Описание

colName

Свойства, соответствующие каждому столбцу курсора. Имя каждого свойства colName   это имя столбца в БД.

close

Закрывает курсор.

columns

Возвращает количество столбцов в курсоре.

columnName

Возвращает имя столбца в курсоре.

next

Делает следующий ряд курсора текущим рядом.

insertRow

Вставляет новый ряд в специфицированную таблицу.

updateRow

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

deleteRow

Удаляет текущий ряд специфицированной таблицы.

Полную информацию об этих методах см. в описании класса Cursor в книге "Серверный JavaScript. Справочник" .

Создание Курсора


Как только приложение установило соединение с БД, Вы можете создать курсор путём вызова метода cursor ассоциированного объекта database или Connection. Создание объекта Cursor также открывает курсор в БД. Вам не нужно выполнять отдельную команду open.

Можно предоставить следующую информацию при создании объекта Cursor:

Например, следующий оператор создаёт курсор для записей таблицы CUSTOMER. Записи содержат столбцы id, name и city и упорядочены по значениям столбца id.


custs = connobj.cursor ("select id, name, city
   from customer order by id");

Этот оператор устанавливает в переменную custs объект Cursor. Запрос SQL может вернуть следующие ряды:


1 Sally Smith Suva
2 Jane Doe Cupertino
3 John Brown Harper's Ferry

Затем Вы можете получить доступ к этой информации через использование методов Cursor-объекта custs. Этот объект имеет свойства id, name и city, соответствующие столбцам виртуальной таблицы.

Когда Вы первоначально создаёте Cursor-объект, указатель позиционируется сразу перед первым рядом виртуальной таблицы. В последующих разделах рассматривается, как получить информацию из виртуальной таблицы.

Вы можете также использовать оператор конкатенации строк (+) и строковые переменные (такие как значения свойств client или request) при конструировании оператора SELECT. Например, следующий вызов использует ранее сохранённый customer ID для последующей специализации запроса:


custs = connobj.cursor ("select * from customer where id = "
 + client.customerID);

При попытке создания Cursor-объекта Вы можете столкнуться с различными проблемами. Например, если оператор SELECT в вызове метода cursor обращается к несуществующей таблице, БД возвращает ошибку, и метод cursor возвращает null вместо Cursor-объекта. В этой ситуации Вы должны использовать методы majorErrorCode и majorErrorMessage для определения возникшей ошибки.

В качестве второго примера, предположим, что оператор SELECT обращается к существующей таблице, в которой нет рядов. В этом случае БД может не возвратить ошибку, а метод cursor возвратит верный Cursor -объект. Однако, поскольку этот объект не содержит рядов, при первой попытке использования метода next в этом объекте он возвратит false. Ваше приложение должно проверять возможность возникновения такой ситуации.

Отображение Значений Записи


Когда Вы создаёте курсор, он получает свойство colName   для каждого именованного столбца виртуальной таблицы (отличное от свойств, соответствующих агрегатным функциям), как определено оператором SELECT. Вы можете получать доступ к значениям текущего ряда, используя эти свойства. В вышеприведённом примере курсор имеет свойства для столбцов id, name и city. Вы можете вывести значения для первого возвращённого ряда, используя следующие операторы:


// Создаётся Cursor-объект.


custs = connobj.cursor ("select id, name, city
   from customer order by id");

// Прежде чем продолжить, убедитесь, что курсор действительно был возвращён
// и не было ошибки БД.
if ( custs && (connobj.majorErrorCode() == 0) ) {

   
// Получаем первый ряд.


   custs.next();

   
// Отображаем значение.


   write ("<B>Customer Name:</B>" + custs.name + "<BR>");
   write ("<B>City:</B> " + custs.city + "<BR>");
   write ("<B>Customer ID:</B> " + custs.id);

   //Закрываем курсор.


   custs.close();
}

Сначала текущим рядом является первый ряд таблицы. Выполнение метода next передвигает текущий ряд на первый ряд таблицы. Например, предположим, что это первый ряд курсора:


1 Sally Smith Suva

Тогда предыдущий код выведет:

Customer Name: Sally Smith
City: Suva
Customer ID: 1


Вы можете обращаться к свойствам Cursor -объекта (или, в действительности, объекта JavaScript) как к элементам массива. Элемент массива с индексом [0] соответствует первому столбцу, элемент массива с индексом [1] соответствует второму столбцу, и так далее.

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


write ("<B>Customer Name:</B> " + custs[1] + "<BR>");
write ("<B>City:</B> " + custs[2] + "<BR>");
write ("<B>Customer ID:</B> " + custs[0]);

Эта техника особенно применима внутри циклов. Например, Вы можете создать Cursor -объект с названием custs и вывести результат выполнения запроса в виде таблицы HTML с помощью следующего кода:


// Создаётся Cursor-объект.


custs = connobj.cursor ("select id, name, city from customer order by id");

// Прежде чем продолжить, убедитесь, что курсор действительно был возвращён
// и не было ошибки БД.
if ( custs && (connobj.majorErrorCode() == 0) ) {
    write ("<TABLE BORDER=1>");
   // Отображаем имена столбцов как заголовки.
   write("<TR>");
   i = 0;
   while ( i < custs.columns() ) {
      write("<TH>", custs.columnName(i), "</TH>");
      i++;
   }
   write("</TR>");

   // Отображаем каждый ряд виртуальной таблицы.


   while(custs.next()) {
      write("<TR>");
      i = 0;
      while ( i < custs.columns() ) {
         write("<TD>", custs[i], "</TD>");
         i++;
      }
   write("</TR>");
   }
   write ("</TABLE>");

   // Закрываем курсор.


   custs.close();
}

Этот код может вывести примерно такую таблицу:

ID NAME CITY

1

Sally Smith

Suva

2

Jane Doe

Cupertino

3

John Brown

Harper's Ferry

В примере использованы методы, обсуждаемые в последующих разделах.

Отображение Выражений и Агрегатных Функций


Операторы SELECT могут запрашивать значения, не являющиеся столбцами в БД, такие как агрегатные значения и выражения SQL. Для таких значений Cursor -объект не имеет именованного свойства. Вы можете получить к ним доступ только через использование свойства индекса массива Cursor -объекта для данного значения.

В следующем примере создаётся курсор с именем empData, делается переход к первому ряду этого курсора и затем отображается значение, запрошенное агрегатной функцией MAX. Выполняется также проверка того, что  результаты из БД верны, перед тем как использовать их:


empData = connobj.cursor ("select min(salary), avg(salary),
   max(salary) from employees");
if ( empData && (connobj.majorErrorCode() == 0) ) {
   rowexists = empData.next();
   if (rowexists) { write("Highest salary is ", empData[2]); }
}

Во втором примере создаётся курсор с именем empRows для подсчёта количества рядов в таблице, выполняется переход к ряду в этом курсоре, а затем отображается количество рядов параллельно с выполнением проверки на верность данных:


empRows = connobj.cursor ("select count(*) from employees");
if ( empRows && (connobj.majorErrorCode() == 0) ) {
   rowexists = empRows.next();
   if (rowexists) { write ("Number of rows in table: ", empRows[0]); }
}

Навигация с Помощью Курсоров


Сначала указатель курсора позиционируется перед первым рядом виртуальной таблицы. Метод next используется для перемещения между записями виртуальной таблицы. Этот метод передвигает указатель на следующий ряд и возвращает true, когда следующий ряд виртуальной таблицы найден. Если следующего ряда нет, next возвращает false.

Например, предположим, что виртуальная таблица имеет столбцы с названиями title, rentalDate и dueDate. Следующий код использует next для итерации по рядам и отображения значений столбцов в таблице:


// Создаём курсор.


custs = connobj.cursor ("select * from customer");

// Проверяем курсор и отсутствие ошибок БД.
if ( custs && (connobj.majorErrorCode() == 0) ) {

   
write ("<TABLE>");

   // Итерация по рядам с отображением значений.


   while (custs.next()) {
       write ("<TR><TD>" + custs.title + "</TD>" +
          "<TD>" + custs.rentalDate + "</TD>" +
          "<TD>" + custs.dueDate + "</TD></TR>");
   }

   write ("</TABLE>");


   // Всегда закрывайте курсоры по окончании работы!


   custs.close();
}

Этот код даст на выходе:

Clockwork Orange

6/3/97

9/3/97

Philadelphia Story

8/1/97

8/5/97

Вы не всегда можете находиться в нужном месте в курсоре. Например, предположим, что Вы создаёте курсор и, пока Вы работаете с ним, кто-то добавляет ряд в таблицу. В зависимости от установок БД, этот ряд может появиться в Вашем курсоре. Исходя из этого, когда это удобно (как при обновлении рядов), Вы можете сделать так, чтобы Ваш код проверял, находится ли указатель в нужном ряду.

Работа со Столбцами


Метод columns класса Cursor возвращает количество столбцов в курсоре. Этот метод не принимает параметров:


custs.columns()

Вы можете использовать этот метод, если нужно итерировать по каждому столбцу курсора.

Метод columnName класса Cursor возвращает имя столбца виртуальной таблицы. Этот метод принимает параметр - целое число, специфицирующее порядковый номер столбца, начиная с 0. Первым столбцом виртуальной таблицы является столбец 0, вторым - столбец 1, и так далее.

Например, следующее выражение присваивает имя первого столбца курсора custs переменной header:


header = custs.columnName(0)

Если Ваш оператор SELECT использует шаблон (*) для выбора всех столбцов таблицы, метод columnName не гарантирует, что порядок присвоения номеров столбцам будет тем же. То есть, предположим, у Вас есть оператор:


custs = connobj.cursor ("select * from customer");

Если таблица customer имеет 3 столбца, ID, NAME и CITY, Вы не сможете заранее предугадать, который из этих столбцов будет custs.columnName(0). (Конечно, есть гарантия, что последовательные вызовы columnName дадут аналогичный результат). Если порядок для Вас важен, можно жёстко кодировать имена в операторе выборки, как здесь:


custs = connobj.cursor ("select ID, NAME, CITY from customer");

В этом операторе, custs.columnName(0) это ID, custs.columnName(1) это NAME, а custs.columnName(2) это CITY.

Изменение Информации Базы Данных


Вы можете использовать обновляемый курсор для модифицирования таблицы на основе текущего ряда курсора. Чтобы запросить обновляемый курсор, добавьте дополнительный параметр true при создании курсора, как в этом примере:


custs = connobj.cursor ("select id, name, city from customer", true)

Чтобы курсор был обновляемым, оператор SELECT обязан быть обновляемым запросом (запросом, позволяющим производить обновление). Например, оператор не может запрашивать ряды из более чем одной таблицы или содержать условие GROUP BY, а также обычно он обязан запрашивать ключевые значения таблицы. Дополнительно о конструировании обновляемых запросов см. документацию производителя БД.

Когда курсоры используются для внесения изменений в Вашу БД, Вы всегда должны работать в рамках явной транзакции. Вы делаете это через использование методов beginTransaction, commitTransaction и rollbackTransaction, как указано в разделе "Обслуживание Транзакций." Если в таких ситуациях Вы не используете явные транзакции, Вы можете получать ошибки из Вашей БД.

Например, Informix и Oracle возвращают сообщения об ошибке, если Вы используете курсор без явной транзакции. Oracle возвращает Error ORA-01002: fetch out of sequence; Informix возвращает Error -206: There is no current row for UPDATE/DELETE cursor.

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

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

В следующем примере обновляемый курсор вычисляет премию для продавцов, выполнивших норму. Затем этой информацией обновляется БД:


connobj.beginTransaction ();

emps = connobj.cursor(

   "select * from employees where dept='sales'", true);


// Прежде чем продолжить, убедитесь, что курсор действительно был возвращён
// и не было ошибки БД.
if ( emps && (connobj.majorErrorCode() == 0) ) {


// Производится итерация по рядам курсора с обновлением информации на базе
// return-значения функции metQuota.


   while ( emps.next() ) {
      if (metQuota (request.quota, emps.sold)) {
         emps.bonus = computeBonus (emps.sold);
      }
      else emps.bonus = 0;
      emps.updateRow ("employees");
   }

   // После выполнения - закрывается курсор и подтверждается транзакция.
   emps.close();
   connobj.commitTransaction();
}
else {
   // Если курсор для работы отсутствовал, транзакция откатывается.
   connobj.rollbackTransaction();
}

Этот пример создаёт обновляемый курсор для всех employees/служащих департамента Sales. Производится итерация по рядам курсора через использование определяемой пользователем функции JavaScript metQuota, для того чтобы определить, выполнил ли служащий норму. Эта функция использует значение свойства quota объекта request (возможно, установленное в форме на клиентской странице) и столбец sold курсора для выполнения этого определения. Код затем устанавливает соответствующую премию и вызывает updateRow для модифицирования таблицы employees. Когда пройдены все ряды курсора, подтверждается транзакция. Если вызов метода cursor не вернул никакого курсора, транзакция откатывается.

Помимо метода updateRow, Вы можете использовать методы insertRow и deleteRow для вставки нового ряда или удаления текущего. При использовании deleteRow не нужно присваивать никакого значения, поскольку этот метод просто удаляет весь ряд.

Если Вы используете insertRow, значения, присваиваемые столбцам, используются для нового ряда. Если перед этим Вы вызвали метод next курсора, то текущие значения в ряду используются для столбцов без присвоенных значений; иначе столбцы будут иметь значения null. Также, если некоторые столбцы таблицы не вошли в курсор, insertRow вставляет null в эти столбцы. Место расположения вставляемого ряда зависит от библиотеки производителя БД. Если Вам нужен доступ к ряду после вызова метода insertRow, Вы обязаны сначала закрыть имеющийся курсор, а затем открыть новый.

ПРИМЕЧАНИЕ:

В DB2 имеется тип данных Time. JavaScript не имеет соответствующего типа данных. Поэтому Вы не можете обновлять ряды значениями, использующими тип данных DB2 Time.

Обслуживание Транзакций


Транзакция это несколько действий с базой данных, выполняемых вместе. Либо все эти действия выполняются успешно, либо все вместе терпят неудачу. Если эти действия выполняют (окончательно) изменения БД, говорится, что транзакция подтверждена. Вы можете также выполнить откат /roll back транзакции, т.е. не подтвердить её; это отменяет все выполненные действия.

Транзакции важны для поддержания целостности и структуры данных. В то время как различные серверы БД реализуют механизм транзакций с некоторыми отличиями, сервис LiveWire Database Service предоставляет одни и те же методы для обслуживания транзакций на всех БД. Проверьте в документации продавца БД информацию о согласованности данных и уровнях изоляции транзакций.

Вы можете использовать явный контроль транзакции над выполнением любого набора действий. Например, акции, модифицирующие БД, должны проходить под управлением транзакций. Это акции, соответствующие операторам SQL INSERT, UPDATE и DELETE. Транзакции могут также использоваться для контролирования согласованности данных.

Для большинства БД, если Вы не выполняете явного управления транзакциями, машина выполнения использует фоновый механизм БД - autocommit/автоподтверждение, когда каждый оператор в БД рассматривается как отдельная транзакция. Каждый оператор подтверждается или откатывается немедленно на основе успеха или неуспеха выполнения каждого отдельного оператора. Явное управление транзакциями переопределяет работу этого механизма по умолчанию.

В некоторых БД, таких как Oracle, autocommit это явный механизм, который LiveWire включает для каждого отдельного оператора. В других БД, таких как Informix, autocommit это поведение по умолчанию, если Вы не создаёте транзакцию. В общем, LiveWire скрывает эти различия и переводит приложение в режим autocommit, если приложение не использует beginTransaction для явного старта транзакции.

Для ANSI-БД Informix, LiveWire не использует autocommit. Для этих БД приложение всегда использует транзакции, даже если никогда явно не вызывает beginTransaction. Приложение обязано использовать commitTransaction или rollbackTransaction для завершения транзакции.

ПРИМЕЧАНИЕ:

Настоятельно советуем всегда использовать явный контроль транзакций при выполнении изменений в БД. Это гарантирует, что изменения будут сделаны или отменены вместе. Кроме того, при использовании обновляемых курсоров Вы также всегда должны использовать явные транзакции для контроля за целостностью Ваших данных в период между чтением данных (с помощью next) и их изменением (с помощью insertRow, updateRow или deleteRow).
Как указано в разделе "Изменение Информации Базы Данных", использование явного контроля транзакций и обновляемых курсоров необходимо для того, чтобы исключить ошибки в некоторых БД, таких как Oracle и Informix.

Использование Методов Управления Транзакциями


Используйте следующие методы объектов database или Connection для явного управления транзакциями:

Сервис LiveWire Database Service не поддерживает вложение транзакций. Если Вы вызовете beginTransaction несколько раз до подтверждения или отката первой открытой Вами транзакции, Вы получите ошибку.

Для объекта database максимум области видимости транзакции ограничен текущим клиентским запросом (HTML-страницей) в приложении. Если приложение существует на странице до вызова метода commitTransaction или rollbackTransaction, то транзакция автоматически подтверждается или откатывается на основе установок параметра commitflag, задаваемого при соединении с БД.

Для объектов Connection область видимости транзакции ограничена периодом существования этих объектов. Если Вы освобождаете соединение или закрываете пул соединений до вызова методов commitTransaction или rollbackTransaction, то транзакция автоматически подтверждается или откатывается на основе установок параметра commitflag, задаваемого при соединении с БД методом connect или в конструкторе DbPool.

Если текущая транзакция отсутствует (то есть, если приложение не вызывало beginTransaction), вызовы методов commitTransaction и rollbackTransaction могут привести к ошибке в БД.

Транзакция может работать с разными объёмами данных. Пример из раздела "Изменение Информации Базы Данных" создаёт одну транзакцию для модифицирования всех рядов курсора. Если в Вашем курсоре небольшое количество рядов, такой подход будет оправданным.

Если, однако, Ваш курсор возвращает тысячи рядов, Вы можете обработать этот курсор в нескольких транзакциях. Такой подход снизит размер транзакций и улучшит доступ к информации.

Если Вы разбиваете Ваш процесс на несколько транзакций, убедитесь, что вызов next и ассоциированный вызов updateRow или deleteRow происходят внутри одной транзакции. Если Вы получаете ряд в одной транзакции, завершаете её, а затем пытаетесь обновить или удалить ряд, Вы можете получить ошибку в БД.

Выбор способа обработки транзакции зависит от целей Вашего приложения. Нужно обратиться к документации создателя БД для получения информации о том, как использовать транзакции для данного типа БД.

Работа с Двоичными/Бинарными Данными


Двоичные данные для мультимедиа-содержимого, такого как изображение или звуковой файл, хранятся в БД в виде большого двоичного объекта/binary large object (BLOb). Можно использовать технику двух видов для обработки бинарных данных в приложениях JavaScript:

Если Вам не нужно хранить BLOb-данные в БД, Вы можете хранить в БД имена файлов и осуществлять доступ к этим файлам в Вашем приложении с помощью стандартных тэгов HTML. Например, если Вы хотите вывести изображение в каждом ряду таблицы БД, Вы можете создать в таблице столбец с названием imageFileName, содержащий имя нужного файла изображения. Затем можно использовать такое выражение HTML для показа изображения в каждом ряду:


<IMG SRC=`mycursor.imageFileName`>

Когда курсор проходит по таблице, имя файла в тэге IMG изменяется на ссылку на соответствующий файл.

Для того чтобы Вы могли манипулировать реальными двоичными данными в Вашей БД, машина выполнения JavaScript распознаёт значения столбца, являющиеся BLOb-данными. То есть, когда программа создаёт объект Cursor, если один из столбцов таблицы БД содержит BLOb-данные, программа создаёт Blob -объект для соответствующего значения в объекте Cursor. Вы можете затем использовать методы Blob -объектов для отображения этих данных. Также, если нужно вставить BLOb-данные в БД, программа предоставляет Вам для использования глобальную функцию.

В таблице показаны методы и функции для работы с BLOb-данными.

Таблица 9.2  Методы и Функции для Работы с Blob'ами
Метод или Функция Описание

blobImage

Метод, используемый при отображении BLOb-данных, хранимых в БД. Возвращает тэг HTML IMG для специфицированного типа изображения (GIF, JPEG и т.д.).

blobLink

Метод, используемый при создании ссылки, которая указывает на BLOb-данные гиперссылкой. Возвращает гиперссылку HTML на BLOb.

blob

Глобальная функция, используема для вставки или обновления данных в ряду, содержащем BLOb-данные. Присваивает BLOb-данные столбцу в курсоре.

Метод blobImage вызывает BLOb из БД, создаёт временный файл специфицированного формата и генерирует HTML-тэг IMG, который ссылается на временный файл. Машина выполнения удаляет временный файл после генерации страницы и отправки её клиенту.

Метод blobLink вызывает BLOb-данные из БД, создаёт временный файл и генерирует гипертекстовую ссылку HTML на этот временный файл. Машина выполнения удаляет временный файл после того как пользователь щёлкнет на ссылке или через 60 секунд после того как запрос будет выполнен.

Следующий пример иллюстрирует использование blobImage и blobLink для создания временных файлов. В данном случае таблица FISHTBL содержит 4 столбца: ID(ентификатор), name/имя и два изображения. Одно из них является уменьшенной копией/thumbnail изображения; другое - большим изображением. Код записывает HTML для отображения имени, уменьшенной копии и ссылки на большое изображение.


cursor = connobj.cursor ("select * from fishtbl");

if ( cursor && (connobj.majorErrorCode() == 0) ) {
   while (cursor.next()) {
      write (cursor.name);
      write (cursor.picture.blobImage("gif"));
      write (cursor.picture.blobLink("image\gif", "Link" + cursor.id));
      write ("<BR>");
   }
   cursor.close();
}

Если FISHTBL содержит ряды для 4 рыб, пример может дать на выходе такой HTML:


Cod <IMG SRC="LIVEWIRE_TEMP9">
<A HREF="LIVEWIRE_TEMP10">Link1 </A> <BR>
Anthia <IMG SRC="LIVEWIRE_TEMP11">
   <A HREF="LIVEWIRE_TEMP12">Link2 </A> <BR>
Scorpion <IMG SRC="LIVEWIRE_TEMP13">
   <A HREF="LIVEWIRE_TEMP14">Link3 </A> <BR>
Surgeon <IMG SRC="LIVEWIRE_TEMP15">
<A HREF="LIVEWIRE_TEMP16">Link4 </A> <BR>

Если Вам нужно добавить BLOb-данные в БД, используйте глобальную функцию blob. Она вводит BLOb-данные в столбец в обновляемом курсоре. В противоположность blobImage и blobLink, функция blob является функцией верхнего уровня, а не методом.

Следующие операторы вставляют BLOb-данные в столбцы ряда, а затем обновляют этот ряд таблицы FISHTBL в БД. В курсоре имеется единственный ряд.


// Начало транзакции.


database.beginTransaction();

// Создание курсора.


fishCursor = database.cursor ("select * from fishtbl where
   name='Harlequin Ghost Pipefish'", true);


// Убедимся, что курсор создан.


if ( fishCursor && (database.majorErrorCode() == 0) ) {

   // Позиционируем указатель на ряд.
   rowexists = fishCursor.next();


   if ( rowexists ) {

      
// Присваиваем/вставляем blob-данные.
fishCursor.picture = blob ("c:\\data\\fish\\photo\\pipe.gif");

      // Обновляем ряд.
       fishCursor.updateRow ("fishtbl");

      
// Закрываем курсор и подтверждаем изменения.


      fishCursor.close();
      database.commitTransaction();
   }
   else {
      // Иначе закрываем курсор и выполняем откат транзакции.
      fishCursor.close();
      database.rollbackTransaction();
   }
}
else {
   // Иначе вообще не получаем курсор; откатываем транзакцию.
database.rollbackTransaction();
}

Помните, что backslash (\) это escape-символ в JavaScript. Исходя из этого, Вы обязаны использовать двойной обратный слэш в именах файлов NT, как было в данном примере.

Вызов Хранимых Процедур


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

Сервис LiveWire Database Service предоставляет два класса для работы с хранимыми процедурами: Stproc и Resultset. используя методы этих классов, Вы можете вызывать хранимые процедуры и манипулировать результатами их  работы.

Обмен Информацией


Работа хранимых процедур имеет отличия на разных БД, поддерживаемых сервисом LiveWire Database Service. Самое важное для LiveWire - это отличия в передаче информации в и из хранимой процедуры в приложении на JavaScript. Вы всегда используете параметры ввода хранимой процедуры для передачи информации в хранимую процедуру.

Концептуально имеются несколько способов, которыми можно запросить информацию из хранимой процедуры. Не всегда производитель БД даёт возможность запрашивать информацию любым их этих способов.

Результирующие Наборы


Хранимая процедура может выполнять один или более операторов SELECT, запрашивая информацию из БД. Вы можете представить эту информацию как виртуальную таблицу, очень похожую на курсор "только для чтения". (О курсорах см. раздел "Манипулирование Результатами Выполнения Запросов с Помощью Курсоров").

LiveWire использует класс Resultset как контейнер рядов, возвращаемых одним оператором SELECT хранимой процедуры. Если хранимая процедура допускает наличие нескольких операторов SELECT, Вы получите отдельные объекты Resultset для каждого оператора SELECT. Метод resultSet класса Stproc используется для получения результирующего набора объектов, а затем методы этих объектов используются для манипулирования результирующим набором.

БД различных производителей возвращают результирующий набор по-разному:

Параметры Вывода и  Ввода/Вывода


Помимо стандартных параметров ввода, некоторые производители БД разрешают вводить другие типы параметров для хранимых процедур. Параметры вывода хранят информацию при возвращении из хранимой процедуры и параметры ввода/вывода, передающие и возвращающие информацию.

Для большинства БД Вы используете методы outParamCount и outParameters класса Stproc для доступа к параметрам вывода и ввода/вывода. Informix, однако, не разрешает параметры вывода и ввода/вывода. Соответственно, Вы не должны использовать методы outParamCount и outParameters с хранимыми процедурами Informix.

Return-Значения


Как и вызов функции, хранимая процедура может иметь возвращаемое/return значение. Для Oracle и Sybase это return-значение является дополнением к возвращаемому результирующему набору.

Метод returnValue класса Stproc используется для доступа к return-значению. Однако return-значения для хранимой процедуры Informix используются для генерации её результирующего набора. Поэтому returnValue всегда возвращает null для хранимых процедур Informix. Помимо этого, return-значения недоступны для хранимых процедур ODBC и DB2.

Этапы Использования Хранимых Процедур


После установки соединения с БД этапы использования хранимой процедуры в Вашем приложении несколько различаются для разных БД:

  1. (Только DB2) Хранимая процедура регистрируется в соответствующих системных таблицах. (Это выполняется вне JavaScript.)
  2. (DB2, ODBC и Sybase) Определяется прототип для Вашей хранимой процедуры.
  3. (Все БД) Выполняется хранимая процедура.
  4. (Все БД) Создаётся resultSet -объект и получаются данные из этого объекта.
  5. (DB2, ODBC и Sybase) Выполнение завершается доступом к return-значению.
  6. (DB2, ODBC, Oracle и Sybase) Выполнение завершается получением параметров вывода.

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

В следующих разделах эти этапы рассматриваются по отдельности.

Регистрация Хранимой Процедуры


Этот этап выполняется только в DB2.

В DB2 имеются различные системные таблицы, в которые Вы можете записать Вашу хранимую процедуру. В общем, вставка хранимой процедуры в эти таблицы не обязательна. Однако, для того чтобы использовать Вашу хранимую процедуру с LiveWire, Вы обязаны создать вхождения в этих таблицах. Этот этап выполняется вне приложения JavaScript.

Для обычного DB2-сервера Вы обязаны создать системную таблицу DB2CLI.PROCEDURES и ввести в неё Ваши DB2-хранимые процедуры. DB2CLI.PROCEDURES это таблица-псевдокаталог.

Если Ваш DB2 предназначен для IBM MVS/EA версии 4.1 или более поздней, Вы обязаны определить имена Ваших хранимых процедур в таблице-каталоге SYSIBM.SYSPROCEDURES.

Не забывайте, что Вы используете C, C++ или другой язык для написания DB2-хранимой процедуры. Типы данных, которые Вы используете в этих языках, не соответствуют типам данных, доступным в DB2. Следовательно, если Вы добавляете хранимую процедуру в DB2CLI.PROCEDURES или в SYSIBM.SYSPROCEDURES, убедитесь, что записаны соответствующие типы данных DB2 для параметров хранимой процедуры, а не типы данных исходных языков.

Информацию о типах данных DB2 и о том, как сделать вхождения в таблицах, см. в документации по DB2.

Определение Прототипа для Хранимой Процедуры


Этот этап относится только к пользовательским и системным хранимым процедурам DB2, ODBC и Sybase. Вам не нужно определять прототип хранимых процедур БД Oracle или Informix.

Для DB2, ODBC и Sybase программа не может определить в процессе выполнения, предназначен определённый параметр для ввода, вывода, или для того и другого. Соответственно, после того как Вы подключились к БД, Вы обязаны создать прототип, предоставляющий информацию о хранимой процедуре, которую Вы хотите использовать, через метод storedProcArgs объекта database или DbPool.

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

В прототипе Вы предоставляете имя хранимой процедуры и тип каждого из её параметров. Параметр обязан быть: для ввода/input (IN), вывода/output (OUT), а для ввода и вывода - (INOUT).
Например, чтобы создать прототип для хранимой процедуры newhire, имеющей два параметра ввода и один параметр вывода, можно использовать такой вызов метода:


poolobj.storedProcArgs("newhire", "IN", "IN", "OUT");

Выполнение Хранимой Процедуры


Этот этап применяется ко всем хранимым процедурам.

Для выполнения хранимой процедуры Вы создаёте Stproc -объект, используя метод storedProc объектов database или Connection. Создание такого объекта автоматически вызывает хранимую процедуру. При создании объекта хранимой процедуры Вы специфицируете имя процедуры и любые параметры процедуры.

Например, у Вас есть хранимая процедура newhire, принимающая параметры - строку и целое число. Следующий вызов метода создаёт spObj -объект хранимой процедуры и вызывает хранимую процедуру newhire:


spObj = connobj.storedProc("newhire", "Fred Jones", 1996);

В общем, Вы обязаны предоставить значения для всех параметров ввода/вывода для хранимой процедуры. Если хранимая процедура имеет значение по умолчанию, определённое для одного из её параметров, Вы можете использовать директиву "/Default/" для специфицирования этого значения по умолчанию. Аналогично, если хранимая процедура может принимать null-значение одного из своих параметров, Вы можете специфицировать это null-значение либо директивой "/Null/", либо передав само null-значение.

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


spobj = connobj.storedProc("demosp", "Param_1", "Param_2", 1);

Альтернативно, чтобы передать null для второго параметра и использовать значение по умолчанию для третьего параметра, Вы можете использовать один из следующих операторов:


spobj = connobj.storedProc("demosp", "Param_1", "/Null/", "/Default/");
spobj = connobj.storedProc("demosp", "Param_1", null, "/Default/");
ПРИМЕЧАНИЕ:

 В Informix значения по умолчанию обязаны появляться только после всех специфицированных значений. Например, Вы не можете использовать /Default/ для второго параметра процедуры, а затем специфицировать значение для третьего параметра.
 Вы можете также использовать директивы "/Default/" и "/Null/" для параметров ввода/вывода.

В Oracle хранимая процедура может принимать ref -курсоры как параметры input/output или как output-параметры. Например, у Вас имеется хранимая процедура Oracle под названием proc1, принимающая 4 параметра: ref -курсор, целочисленное значение, другой ref -курсор и другое целочисленное значение.

Вызов этой хранимой процедуры из SQL Plus может выглядеть так:


execute proc1 (refcursor1, 3, refcursor2, 5);

Однако, если Вы вызываете эту процедуру из приложения JavaScript, Вы не предоставляете ref -курсор-параметры. Вместо этого эквивалент может быть таким:


spobj = connobj.storedProc("proc1", 3, 5);

О параметрах вывода см. "Работа с Параметрами Вывода." Параметры вывода не могут быть null; однако Вы можете присвоить null-значение параметрам ввода или ввода/вывода.

В таблице дано резюме по методам объекта хранимой процедуры.

Таблица 9.3 Stproc - методы
Метод Описание

resultSet

Возвращает следующий результирующий набор для хранимой процедуры.

Для Informix Вы можете иметь нуль или более результирующих наборов. Для других БД Вы можете иметь нуль, один или более результирующих наборов.

returnValue

Запрашивает return-значение хранимой процедуры.

Для Informix, DB2 и ODBC этот метод всегда возвращает null.

outParameters

Возвращает специфицированный параметр вывода.

Поскольку хранимые процедуры Informix не используют параметры вывода, не используйте этот метод с Informix.

outParamCount

Возвращает количество параметров вывода.

Для Informix этот метод всегда возвращает 0, поскольку хранимые процедуры Informix не используют параметров вывода.

Работа с Результирующими Наборами


Этот этап применяется ко всем хранимым процедурам.

Как указано в разделе "Результирующие наборы", разные БД возвращают результирующие наборы разными способами. Например, у Вас имеется таблица CUSTINFO со столбцами id, city и name. В Sybase Вы можете использовать такую процедуру для получения первых 200 рядов таблицы:


create proc getcusts as
begin
   select id, name, city from custinfo where custno < 200
end

Если CUSTINFO является таблицей Informix, эквивалентная процедура в Informix может быть:


create procedure getcusts returning int, char(15), char(15);
define rcity, rname char (15);
define i int;

foreach
    select id, name, city into i, rname, rcity
       from custinfo
      where id < 200;


   return i, rname, rcity with resume;
end foreach;
end procedure;

Если CUSTINFO - таблица Oracle, эквивалентная процедура Oracle может быть:


create or replace package orapack as
   type custcurtype is ref cursor return custinfo%rowtype
end orapack;

create or replace
custresultset (custcursor inout orapack.custcurtype)
as begin
   open custcursor for select id, name, city from custinfo
      where id < 200
end custresultset;

Во всех случаях Вы создаёте resultSet -объект для получения информации из хранимой процедуры. Вы делаете это через использование метода resultSet объекта хранимой процедуры так:


resObj = spObj.resultSet();

Как и для Cursor -объектов, resultSet -объекты содержат текущий ряд, то есть ряд, на котором стоит указатель в результирующем наборе. Вначале указатель позиционирован перед первым рядом результирующего набора. Чтобы увидеть значения рядов результирующего набора, Вы используете метод next для перемещения указателя по рядам результирующего набора, как показано в следующем примере:


spobj = connobj.storedProc("getcusts");


if ( spobj && (connobj.majorErrorCode() == 0) ) {


   // Создаётся новый resultSet-объект.
    resobj = spobj.resultSet();

   // Перед тем как продолжить, убедитесь, что Вы получили результирующий набор.


   if ( resobj && (connobj.majorErrorCode() == 0) ) {

      // Сначала перемещает указатель resultSet-объекта к первому
    // ряду результирующего набора, а затем циклически проходит по рядам.
       while (resObj.next())
      {
          write("<TR><TD>" + resObj.name + "</TD>");
         write("<TD>" + resObj.city + "</TD>");
          write("<TD>" + resObj.id + "</TD></TR>");
      }
      resobj.close();
   }
}

До тех пор, пока в результирующем наборе имеется следующий ряд, метод next возвращает true и перемещает указатель к следующему ряду. Если указатель достиг последнего ряда результирующего набора, метод next возвращает false.

Предыдущий пример работает с хранимой процедурой Sybase. В этом случае resultSet -объект содержит именованное свойство для каждого столбца результирующего набора. Для процедур Informix и DB2, по контрасту, объект не содержит именованных столбцов. В этом случае Вы можете получить значения, ссылаясь на позицию столбца. Так, для Informix и DB2 Вы можете использовать такой код для вывода аналогичной информации:


spobj = connobj.storedProc("getcusts");


if ( spobj && (connobj.majorErrorCode() == 0) ) {

   
// Создаётся новый resultSet-объект.


   resobj = spobj.resultSet();

   // Перед тем как продолжить, убедитесь, что Вы получили результирующий набор.
   if ( resobj && (connobj.majorErrorCode() == 0) ) {


      // Сначала перемещает указатель resultSet-объекта к первому
    // ряду результирующего набора, а затем циклически проходит по рядам.
      while (resObj.next())
      {
          write("<TR><TD>" + resObj[1] + "</TD>");
          write("<TD>" + resObj[2] + "</TD>");
          write("<TD>" + resObj[0] + "</TD></TR>");
       }
      resobj.close();
   }
}

Вы можете использовать позицию столбца для результирующих наборов любой БД, а не только с Informix и DB2. Вы можете использовать имя столбца для хранимой процедуры всех типов БД, а не только Informix или DB2.

Несколько Результирующих Наборов


Хранимая процедура Sybase, Oracle, DB2 или ODBC может создавать несколько результирующих наборов. В этом случае хранимая процедура предоставляет один resultSet -объект для каждого набора.
Предположим, Ваша хранимая процедура выполняет такие операторы SQL:



select name from customers where id = 6767
select * from orders where id = 6767

Вы можете использовать несколько resultSet -объектов, генерируемых этими операторами, таким образом:


// Этот оператор нужен для DB2, ODBC и Sybase. 
poolobj.storedProcArgs("GetCustOrderInfo","IN");


spobj = connobj.storedProc("GetCustOrderInfo",6767);


if ( spobj && (connobj.majorErrorCode() == 0) ) {

   
resobj1 = spobj.resultSet();


   // Перед тем как продолжить, убедитесь, что результирующий набор существует.
   if ( resobj1 && (connobj.majorErrorCode() == 0) ) {


      // Первый результирующий набор возвращает только один ряд. 
      // Убедитесь, что ряд содержит данные.
       rowexists = resobj1.next();
      if ( rowexists )
         write("<P>Customer " + resobj1.name +
             " has the following orders:</P>");
      resobj1.close();

      // Второй результирующий набор возвращает один ряд для каждого заказа,
      // помещённого пользователем. Убедитесь, что ряды содержат данные.


      resobj2 = spobj.resultSet();
       var i = 0;

      
if ( resobj2 && (connobj.majorErrorCode() == 0) ) {
          write("\nOrder# Quantity Total</P>");
          while(resobj2.next()) {
             write(resobj2.orderno + " " + resobj2.quantity
                + " " + resobj2.Totalamount + "</P>");
            i++;
          }
         resobj2.close();
         write("Customer has " + i + " orders.</P>");
      }
      else write("Customer has no orders.</P>");
   }
}


spobj.close();

В качестве примера использования нескольких ref-курсоров Oracle в хранимой процедуре см. описание класса Resultset в книге Серверный JavaScript. Справочник .

Методы и Свойства Результирующего Набора


В таблице дано резюме по методам и свойствам класса Resultset.

Таблица 9.4 Resultset - методы и свойства
Метод или Свойство Описание

colName

Свойства, соответствующие каждому столбцу результирующего набора. Имя каждого свойства это имя столбца в БД.

Поскольку хранимые процедуры Informix и DB2 не возвращают именованных столбцов, эти свойства не создаются для хранимых процедур Informix или DB2.

columns

Возвращает количество столбцов результирующего набора.

Для Informix этот метод возвращает количество return-значений для одного ряда.

columnName

Возвращает имя столбца в результирующем наборе.

Поскольку хранимые процедуры Informix и DB2 не имеют ассоциированных имён столбцов, не используйте этот метод для хранимых процедур этих БД.

close

Удаляет Resultset -объектobject.

next

Делает следующий ряд результирующего набора текущим рядом. Возвращает false, если текущий ряд является последним рядом результирующего набора; иначе возвращает true.

resultSet -объект является объектом "только для чтения"/read-only, объектом последовательного стиля/sequential-style. Исходя из этого, класс не имеет методов insertRow, deleteRow и updateRow, определённых для Cursor -объектов.

Когда Можно Использовать Результирующие Наборы


Объект resultSet не является бесконечно действующим. Вообще, когда хранимая процедура стартует, не допускается никакое взаимодействие между клиентом БД и сервером БД, пока хранимая процедура не завершит выполнение. Есть три ситуации, когда результирующий набор является недействующим:

  1. Если Вы создаёте результирующий набор как часть транзакции, Вы обязаны закончить использование результирующего набора в течение выполнения этой транзакции. Если Вы подтвердили транзакцию или выполнили её откат, Вы не сможете получать данные из результирующего набора и не сможете получить дополнительные результирующие наборы. Например, следующий код не допускается:
  2. 
    database.beginTransaction();
    spobj = database.storedProc("getcusts");
    resobj = spobj.resultSet();
    database.commitTransaction();
    // Неверно! Результирующий набор больше не действует!
    col1 = resobj[0];
  3. Для Sybase, ODBC и DB2 Вы обязаны запросить resultSet -объекты до вызова методов returnValue или outParameters объекта хранимой процедуры. Если Вы вызвали один из этих методов, Вы не сможете больше получать данные из результирующего набора и не сможете получить дополнительные результирующие наборы. См. о работе этих методов раздел "Работа с Return-Значениями".
  4. 
    spobj = database.storedProc("getcusts");
    resobj = spobj.resultSet();
    retval = spobj.returnValue();
    // Неверно! Результирующий набор больше не действует!
    col1 = resobj[0];
  5. Для Sybase Вы обязаны запросить resultSet -объекты до вызова методов cursor или SQLTable ассоциированного соединения. Как только Вы вызовете cursor или SQLTable, результирующий набор станет недоступен. Например, следующий код неверен:
  6. 
    spobj = database.storedProc("getcusts");
    resobj = spobj.resultSet();
    curobj = database.cursor ("select * from orders");
    // Неверно! Результирующий набор больше не доступен!
    col1 = resobj[0];
  7. Для ODBC соблюдаются несколько иные ограничения. Вы также обязаны работать с resultSet -объектами до вызова методов cursor или SQLTable ассоциированного соединения. В ODBC, если Вы получаете курсор, выполняете доступ к результирующему набору, а затем используете курсор, Cursor -объект становится недоступным. Например, следующий код неверен:
  8. 
    spbobj = database.storedProc("getcusts");
    resobj = spobj.resulSet();
    curobj = database.cursor ("select * from orders");
    col1 = resobj[0]; // Неверно! Курсор больше не доступен.
    curobj.next();

Работа с Return-Значениями


Этот этап относится к хранимым процедурам Sybase и Oracle. Для процедур Informix, ODBC и DB2 метод returnValue всегда возвращает null.

Если Ваша хранимая процедура возвращает значение (return value), Вы можете получить к нему доступ с помощью метода returnValue.

В DB2, ODBC и Sybase Вы обязаны использовать хранимые процедуры и курсоры последовательно. Вы не можете их перемешивать. Исходя из этого, Вы обязаны дать системе знать, что Вы закончили использование хранимой процедуры, прежде чем сможете работать с курсором. Это выполняется через вызов метода returnValue объекта хранимой процедуры. Этот метод выдаёт return-значение хранимой процедуры (если она его имеет) и завершает выполнение хранимой процедуры. Вы должны также закрыть все объекты, относящиеся к хранимым процедурам, когда завершаете их использование.

ПРИМЕЧАНИЕ:

Для DB2, ODBC и Sybase Вы обязаны запросить resultSet -объекты до вызова метода returnValue. После того как Вы вызвали returnValue, Вы больше не сможете получить данные из результирующего набора и не сможете получить какие-либо дополнительные результирующие наборы. Вы должны вызывать returnValue после того, как обработали результирующий набор, но до запроса параметров вывода.

Работа с Параметрами Вывода


Этот этап касается хранимых процедур  Sybase, Oracle, DB2 или ODBC. Для процедур Informix методы, обсуждаемые здесь, не применяются.

Чтобы определить количество параметров вывода процедуры (включая параметры и вывода, и ввода/вывода), Вы используете метод outParamCount. Вы можете работать с параметрами вывода хранимой процедуры, используя метод outParameters объекта. Если outParamCount возвращает 0, хранимая процедура не имеет параметров вывода. В этой ситуации не вызывайте outParameters.

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


id = 100;
getNameProc = connobj.storedProc("getName", id);
returnValue = getNameProc.returnValue();
if (returnValue == 1)
    write ("Name of employee is " + getNameProc.outParameters(0));
else
   write ("No employee with id = " + id);

Предположим, хранимая процедура имеет один параметр ввода, один параметр ввода/вывода и один параметр вывода. Далее примем, что вызов хранимой процедуры отсылает значение параметра ввода и параметра ввода/вывода, как показано здесь:


spobj = connobj.storedProc("myinout", 34, 56);

Метод outParameters возвращает любые параметры ввода/вывода до того как возвратит первый параметр вывода.

В предыдущем примере, если Вызывается outParameters(1), возвращается значение, возвращаемое хранимой процедурой. И наоборот, если вызывается outParameters(0), метод возвращает 56. Это значение, переданное хранимой процедуре в позиции параметра ввода/вывода.

ПРИМЕЧАНИЕ:

Параметры вывода не могут быть null; однако Вы можете присвоить null-значение параметра ввода или ввода/вывода. В DB2, ODBC и Sybase Вы обязаны запрашивать resultSet -объекты и использовать метод returnValue до того, как вызываете outParameters. После того как Вы вызвали returnValue или  outParameters, Вы больше не сможете получить данные из результирующего набора и не сможете получить какие-либо дополнительные результирующие наборы. Вы должны вызывать outParameters после обработки результирующего набора и любых return-значений.

Исключения Informix и Sybase


Хранимые процедуры Informix и Sybase могут возвращать коды ошибки, используя механизм исключений. После того как Вы запустили процедуру на выполнение, Вы можете запрашивать эти коды ошибок и сообщения об ошибках, используя методы majorErrorCode и majorErrorMessage ассоциированного объекта database или Connection.

Например, у Вас имеется хранимая процедура Informix:


create procedure usercheck (user varchar(20))
if user = 'LiveWire' then
raise exception -746, 0, 'User not Allowed';
endif
end procedure

Если Вы запустите эту процедуру на выполнение, Вы сможете проверять, появилась ли ошибка, а затем получить доступ к коду ошибки и сообщению о ней:


spobj = connobj.storedProc("usercheck");


if ( connobj.majorErrorCode() ) {
   write("The procedure returned this error code: " +
      connobj.majorErrorCode());
   write("The procedure returned this error message: " +
       connobj.majorErrorMessage());
}
Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 10
Конфигурирование Базы Данных

В этой главе рассматривается настройка Вашей Базы Данных для запуска со службой LiveWire Database Service. Вы должны прочесть эту главу и  раздел "Информация Конфигурации" перед тем как использовать LiveWire с Вашими JavaScript-приложениями.

ПРИМЕЧАНИЕ:

Могут понадобиться изменения в клиентах БД. Дополнительно см. Enterprise Server 4.x Release Notes .

В этой главе имеются следующие разделы:

О Службе LiveWire Database Service


Одновременно с версиями 3.x и 4.x Netscape-серверов Вы обязаны установить клиентскую библиотеку БД (и к тому же - определённую версию), если хотите использовать LiveWire Database Service. Вы также обязаны сконфигурировать эту клиентскую библиотеку для работы с LiveWire.

Netscape-серверы не поставляются вместе клиентскими библиотеками БД. Вам нужно связаться с поставщиком Вашей БД на предмет получения соответствующей библиотеки. Вам необходимо установить и сконфигурировать клиентские библиотеки только тех БД, которые Вы будете использовать.

Если Вы устанавливаете БД на другую машину (не на ту, где установлен web-сервер), Вы обязаны иметь установленную клиентскую библиотеку БД на машине с web-сервером. Вы обязаны получить соответствующее лицензионное разрешение от поставщика Вашей БД. Netscape не сделает это за Вас.

Требования по конфигурированию Вашей БД могут отличаться в зависимости от того, находятся ли БД и web-сервер на одной или на разных машинах. Если они на одной машине, последующая информация будет касаться локальной конфигурации; если на разных машинах - удалённой конфигурации.

В этой главе рассмотрены только те аспекты установки клиента БД, которые имеют отношение к использованию с LiveWire. Для получения общей информации об установке клиента БД обратитесь к соответствующей документации поставщика БД.

Проверка Конфигурации Вашей БД


После выполнения установки, описанной в данной главе, Вы можете использовать приложение-образец dbadmin для проверки правильности работы Вашего соединения с БД. Вы используете это приложение JavaScript для соединения с Вашим сервером БД и выполнения различных несложных задач, таких как выполнение оператора SELECT и отображение результатов или отправки произвольных SQL-команд серверу.

Поскольку dbadmin может использоваться для модификации и удаления таблиц БД, доступ к ней автоматически ограничен, если Вы выбрали защищённый режим Application Manager. Дополнительно об ограничении Application Manager см. "Управление Доступом к Приложению".

Первое, что Вы обязаны сделать при использовании dbadmin, это соединиться с БД. Выберите Connect to Database. Появится форма, показанная на Рисунке 10.1, где вы можете ввести информацию о соединении. Введите параметры и щёлкните Connect, чтобы попытаться установить соединение с сервером. О параметрах соединения см. "Пулы Соединений Базы Данных", а также описание метода connect в книге Серверный JavaScript. Справочник .

Рисунок 10.1 Страница соединения dbadmin

Если соединение установилось, появляется страница Execute Query. Это означает, что ваша БД соответствующим образом сконфигурирована для работы с LiveWire Database Service. Если соединиться не удалось, появится страница Database Connect Error. В этом случае убедитесь, что Вы следовали инструкциям по конфигурированию конкретной БД и "железа".

Поддерживаемые Клиенты БД и ODBC-Драйверы


В следующей таблице дано резюме по конкретным поставщикам БД, поддерживаемых на каждой платформе Netscape Enterprise Server 3.x (относительно Netscape Enterprise Server 4.0 см. замечания Enterprise Server 4.0 Release Notes).
Данные поставщики БД не поддерживаются сервером Netscape FastTrack Server.

Таблица 10.1  Клиентские библиотеки поставщиков БД, поддерживаемые на каждой платформе сервером Netscape Enterprise Server
Поставщик БД AIX DEC Irix 6.2 >HP-UX 11.0 Solaris 2.5.1/2.6 Windows NT 4.0 w/ SP4
DB2 CAE 2.1.2

Не поддерживается

Не поддерживается

V5.2

V5.2

V5.2

Informix

Informix Client 7.22

Informix Client 7.22

Informix Client 7.22

SDK 2.10 (ESQL 9.16)

SDK 2.10 (ESQL 9.16)

SDK 2.10 TC1 (ESQL 9.16)

Microsoft ODBC

ODBC Mgr Visigenic 2.0

Не поддерживается

ODBC Mgr Visigenic 2.0

Не поддерживается

Поддерживается только на Solaris 2.5.1

MS SQL Server 6.5 (драйвер 3.60)

SQL Anywhere 5.5 (драйвер 5.00)

MS Access 7.0 (драйвер 3.51.171300)

Oracle 1

Oracle Client 7.3.x

Oracle Client 7.3.x

Oracle Client 7.3.x

Oracle Client

8.0.5

Oracle Client

8.0.5

Oracle Client 8.0.5

Sybase

Open

Client

/C 11.1

Open

Client

/C 11.1

Open

Client

/C 11.1

11.1.1

11.1.1

11.1.1

1 Версия Oracle SQL*Net 1.1 больше не поддерживается.

В следующей таблице дано резюме по поддержке ODBC в Windows NT для Netscape Enterprise Server и Netscape FastTrack Server.

Таблица 10.2  Поддержка ODBC в Windows NT
ODBC-Компонент Windows NT 4.0 SP4

ODBC Manager

MS ODBC Manager 3.51 MCAD 2.0 SP2

ODBC-Драйверы

MS SQL Server 6.5

MS SQL Server Driver 3.60 (sqlsrv32.dll)

MS Access 7.0

MS Access Driver 3.51.171300 (odbcjt32.dll)

Sybase SQL Anywhere 5.5

Sybase SQL Anywhere Driver 5.00.0003 (wod50t.dll)

Обратите внимание, что ODBC не поддерживается на платформах Unix.

ПРИМЕЧАНИЕ:

Visigenic больше не обновляет свои существующие ODBC-драйверы или SDK. Вместо этого Visigenic избрал INTERSOLV для предоставления пути для обновления этих драйверов и продуктов. (См. http://www.intersolv.com/ newsstand/pr9711191.html). Visigenic предоставит документ, покрывающий различия между драйверами Visigenic и INTERSOLV ODBC. В таблице перечислены возможности поддерживаемых ODBC-драйверов для NT.

Таблица 10.3  Возможности ODBC-драйверов в NT
SQL-БД Соединение SQL passthrough/пропуск Курсор "Только для чтения" Обновляемый курсор Хранимые процедуры

MS-SQL Server 6.5

Да

Да

Да

Да

Да

Sybase SQL Anywhere

Да

Да

Да

Да

Не проверено

Access

Да

Да

Да

Нет

N/A

Обратите внимание, что ODBC не поддерживается на платформах Unix.

DB2


Для использования DB2-сервера у вас должен быть Netscape Enterprise Server. Вы не можете получить доступ к DB2 из Netscape FastTrack Server.

Все платформы: Установить DB2-клиент версии 2.1.2. Для  Solaris Вам нужен APAR #JR10150. См. DB2-документацию http://www.software.ibm.com/data/db2/ .

Если серверы БД и web находятся на разных машинах: Чтобы определить возможность соединения с DB2-сервером, вы можете выполнить следующую команду из командной строки DB2:


DB2 TERMINATE # эта команда даёт возможность работы команды catalog
DB2 CONNECT TO имяБД USERID idпользователя USING пароль

Если вы используете в приложении типы данных BLOB или CLOB, вы обязаны установить опцию longdatacompat в Вашем файле $DB2PATH/db2cli.ini в 1. Например:


[Database name]
longdatacompat=1

Если Вы сделали изменения в файле db2cli.ini, Вы обязаны рестартовать Ваш web-сервер, чтобы они начали действовать.

Только для Unix: Вы обязаны установить следующие переменные окружения/environment variables:


DB2INSTANCE

Специфицирует имя порта соединения, определённое и на сервере, и на клиенте. Это имя имеется также и в файле конфигурации dbm для параметра конфигурации SVCENAME.


DB2PATH

Специфицирует директорию верхнего уровня, в которой установлен DB2.

Например: /home/$DB2INSTANCE/sqllib


DB2COMM

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

DB2COMM=TCPIP


PATH

Обязана включать пути $DB2PATH/misc:$DB2PATH/adm:$DB2PATH/bin


LD_LIBRARY_PATH

(Solaris и Irix) Обязана включать директорию DB2 lib. Например, на Solaris обязана включать /opt/IBMdb2/v2.1/lib.


SHLIB_PATH

(HP-UX) Обязана включать директорию DB2 lib.


LIBPATH

(AIX) Обязана включать директорию DB2 lib.

Informix


При использовании сервера Informix Вы обязаны иметь Netscape Enterprise Server. Вы не можете получить доступ к Informix из Netscape FastTrack Server.

Если серверы БД и web находятся на разных машинах, следуйте инструкциям раздела "Удалённый Informix."

Если серверы БД и web находятся на одной машине, следуйте инструкциям раздела "Локальный Informix."

Удалённый Informix


Только для Unix: Установите Informix ESQL/C Runtime Client 7.22 (называемый также Informix I-Connect), а затем установите следующие переменные окружения:


INFORMIXDIR

Специфицирует верхнюю директорию, в которой установлен Informix.


INFORMIXSERVER

Специфицирует имя Informix-сервера по умолчанию.


INFORMIXSQLHOSTS

Специфицирует путь файла sqlhosts, если Вы поместили его куда-нибудь кроме $INFORMIXDIR/etc/sqlhosts. Эту переменную устанавливать не нужно, если Вы оставили файл sqlhosts в этой директории.


SHLIB_PATH

(HP-UX) Обязана содержать $INFORMIXDIR/lib и $INFORMIXDIR/lib/esql.

Вы обязаны также изменить $INFORMIXDIR/etc/sqlhosts, чтобы оно соответствовал имени службы в файле /etc/services. О том, как это сделать, см. документацию Informix.

Только для NT: Установите Informix ESQL/C Runtime Client 7.20 (называемый также Informix I-Connect.) В процессе установки все необходимые переменные окружения также устанавливаются. Вы используете подходящую утилиту Informix для ввода нужной информации об удалённом сервере, с которым Вы хотите устанавливать соединение.

Если Ваш web-сервер запускается как System, убедитесь, что у вас запущен regcopy.exe.

Все платформы: В зависимости от используемой службы имён, Вам может понадобиться также отредактировать соответствующий файл - добавить IP-адрес удалённой хост-машины, с которой Вы соединяетесь. В NT это файл winnt\system32\drivers\etc\hosts ниже директории NT SystemRoot. На Unix это файл /etc/hosts.

В той же директории добавьте следующую строку к файлу services:




ifmx_srvc
 
port
/tcp # Informix Online Server

где ifmx_srvc это имя Вашей службы, а port - номер порта. Номер порта обязан совпадать с номером порта на удалённой машине, который прослушивается Informix-сервером. Чтобы эта строка начала действовать, Вы обязаны либо вставить как минимум один пробел после tcp, либо поместить комментарий в конце этой строки. Например, если Ваша служба Informix называется ifmx1 и номер порта 1321, Вы добавляете следующую строку:


ifmx1 1321/tcp # Informix Online Server

Локальный Informix


Если вы устанавливаете Informix локально, Вы обязаны установить клиента Informix до установки Informix-сервера.

Только для Unix: Если Вы используете 7.22 Online Server для Unix, процесс инсталяции создаёт соответствующую структуру директорий и файл sqlhosts. Вы обязаны установить переменные окружения, как для удалённого сервера.

Только для NT: Вы должны установить Online Server 7.20. Это установит также и клиента; дополнительные шаги не нужны. Если Ваш web-сервер запускается как System, убедитесь, что у вас запущен regcopy.exe.

ODBC


Все платформы: О возможностях и об используемых ODBC-драйверах см. "Поддерживаемые Клиенты БД и ODBC-Драйверы."

Вам необходимо иметь соответствующие ODBC-драйверы для БД, с которой Вы устанавливаете соединение. Также необходимо иметь дополнительные файлы ODBC-соединений/connectivity.

Большинство программных продуктов, предоставляющие ODBC connectivity, поддерживают ODBC-драйвер или драйверы и ODBC connectivity.

Только для NT: В настоящее время Netscape сертифицирован с ODBC Manager версии 2.5. Если у вас имеется доступ к ODBC-драйверу, но не к файлам ODBC connectivity, Вы можете получить их в MS ODBC SDK. Чтобы получить обновлённые файлы для Access, Foxpro и Excel, Вам может понадобиться патч WX1350 от Microsoft.

Только для Unix: Для ODBC на Unix вы можете использовать драйвер от Visigenic либо от OpenLink. Если Вы используете драйвер от Visigenic, следуйте инструкциям раздела "Visigenic ODBC-Драйвер (только Unix)." Если Вы используете драйвер от OpenLink, следуйте инструкциям раздела "OpenLink ODBC-Драйвер (только Solaris)."

ODBC Data Source Names/Имена Источников Данных (только NT)


Могут быть созданы два типа источников данных:

Источник данных описывает параметры соединения для каждой БД, необходимые для ODBC connectivity. Источник данных определяется чрез использование ODBC-администратора. Если ODBC установлен, администратор также устанавливается. Каждый ODBC-драйвер требует различной информации для определения источника данных.

OpenLink ODBC-Драйвер (только Solaris)


Установите брокер запросов OpenLink Workgroup Edition ODBC Driver на сервер БД. Он должен быть запущен, до того как Вы сможете соединиться с БД с использованием агента запросов OpenLink.

Установите агента запросов (request agent) в клиенте OpenLink Generic ODBC версии 1.5 на клиентской машине БД.

Переименуйте или скопируйте файл драйвера менеджера агента запросов из libiodbc.so в libodbc.so в директории $ODBCDIR/lib, где $ODBCDIR это директория, в которой установлен ODBC.

Когда Вы устанавливаете Ваш сервер, Вы делаете так, чтобы он запускался как некоторый пользователь: root, nobody или конкретный пользователь сервера. Выбранный Вами пользователь должен иметь домашнюю директорию, которую, возможно, понадобится создать. Например, по умолчанию домашняя директория для пользователя nobody на Irix это /dev/null. Если Вы устанавливаете Ваш сервер на Irix как nobody, Вы обязаны создать для пользователя nobody другую домашнюю директорию.

В этой домашней директории Вы обязаны иметь файл .odbc.ini. Например, если сервер запускается как root, этот файл находится в директории (/).

Установите следующие переменные окружения:


LD_LIBRARY_PATH

(Solaris и Irix) Добавляет размещение ODBC-библиотек к данной переменной.


UDBCINI

Специфицирует местонахождение файла .odbc.ini.

Visigenic ODBC-Драйвер (только Unix)


При установке сервера он запускается как пользователь: root, nobody или определённый пользователь сервера. Выбранный вами пользователь должен иметь существующую домашнюю директорию, которую, возможно, понадобится создать. Например, домашняя директория по умолчанию для пользователя nobody в системе Irix это /dev/null. Если Вы устанавливаете Ваш сервер в Irix как nobody, Вы обязаны дать пользователю nobody другую домашнюю директорию.

В этой домашней директории обязан находиться файл .odbc.ini. Например, если Вы запускаете сервер как root, этот файл находится в корневой директории (/).

Установите следующие переменные окружения:


LD_LIBRARY_PATH

(Solaris и Irix) Добавьте местонахождение ODBC-библиотек в данную переменную. В предыдущем примере это может быть /u/my-user/odbcsdk/lib.


SHLIB_PATH

(HP-UX) Добавьте местонахождение ODBC-библиотек в данную переменную.


LIBPATH

(AIX) Добавьте местонахождение ODBC-библиотек в данную переменную.

ПРИМЕЧАНИЕ:

Visigenic больше не обновляет свои существующие ODBC--драйверы и SDK. Вместо этого Visigenic избрал INTERSOLV для предоставления обновлённого пути для этих драйверов и продуктов. (См. http://www.intersolv.com/ newsstand/pr9711191.html). Visigenic будет предоставлять документ, проясняющий операционные различия между ODBC-драйверами Visigenic и INTERSOLV.

Oracle


Чтобы использовать сервер Oracle, Вы обязаны иметь Netscape Enterprise Server. Вы не можете получить доступ к Oracle из Netscape FastTrack Server.

Если БД и web-сервер находятся на разных машинах, следуйте инструкциям раздела "Удалённый Oracle."

Если БД и web-сервер находятся на одной машине, следуйте инструкциям раздела "Oracle Local."

Только для Unix: Убедитесь, что Вы можете соединиться с Вашей БД Oracle через SQL*Net. Если Вы закончили инсталяцию, Вы можете использовать loopback-тест для проверки корректности соединения. Например, из sqlplus Вы можете попытаться соединиться с Вашей БД с помощью следующей команды:


connect username/password@service_name

Или из командной строки Unix:


sqlplus username/password@service_name

В этих командах Вы используете service_name из Вашего файла tnsnames.ora.

Удалённый Oracle


Только для NT: Вы обязаны установить клиентское программное обеспечение Oracle 7.3.2 для NT. Клиенты Oracle 7.1 и 7.2 не поддерживаются. Вы обязаны также создать файлы конфигурации Oracle, используемые соответствующей утилитой конфигурирования Oracle.

Только для Unix: Прежде чем Вы сможете подключиться к Oracle под Irix, Вы обязаны иметь соответствующие патчи для Irix. См. в Enterprise Server 3.x Release Notes информацию о необходимых патчах.

Вы обязаны установить клиентов Oracle 7.3.x для Unix. Клиенты Oracle 7.1 и 7.2 не поддерживаются.

Вы обязаны установить следующие переменные окружения:


ORACLE_HOME

Специфицирует директорию верхнего уровня, в которой установлен Oracle.


TNS_ADMIN

Специфицирует место размещения файлов конфигурации, например, $ORACLE_HOME/network/admin. После инсталяции Oracle создаёт файлы конфигурации под /var/opt/oracle. Если listener.ora и tnsnames.ora находятся в этой директории, Вам может не понадобиться устанавливать TNS_ADMIN, поскольку по умолчанию Oracle использует /var/opt/oracle.

Если эти переменные не установлены надлежащим образом, Oracle возвращает код ошибки ORA-1019 при первой попытке установления соединения. Об обработке ошибок см. Главу 12, "Обработка Ошибок для LiveWire."

Локальный Oracle


Только для Unix: Прежде чем Вы сможете подключиться к Oracle под Irix, Вы обязаны иметь соответствующие патчи для Irix. См. в Enterprise Server 3.x Release Notes информацию о необходимых патчах.

Все платформы: Вы обязаны установить Oracle Workgroup Enterprise Server 7.3.2 (NT) или Enterprise Server 7.3.x (Unix). Клиенты Oracle 7.1 и 7.2 не поддерживаются. Уточните у вашего поставщика сервера, совместима ли Ваша версия Oracle-сервера с Oracle-клиентом.

Вы обязаны установить следующие переменные окружения:


ORACLE_HOME

Специфицирует директорию верхнего уровня, в которой установлен Oracle.


ORACLE_SID

Специфицирует Oracle System Identifier (Системный Идентификатор).

Если у Вас локальный сервер БД Oracle, Вы обязаны передавать пустую строку в качестве второго аргумента методу connect объектов database или DbPool или конструктору DbPool. Таким образом, эти методы используют значение переменной окружения ORACLE_SID. Например:


database.connect ("ORACLE", "" "user", "password", "");

Об инсталяции Oracle см. дополнительно документацию по Oracle.

Sybase


Чтобы использовать сервер Sybase, Вы обязаны иметь Netscape Enterprise Server. Вы не можете получить доступ к Sybase из Netscape FastTrack Server.

Если БД и web-сервер находятся на разных машинах, следуйте инструкциям раздела "Удалённый Sybase."

Если БД и web-сервер находятся на одной машине, следуйте инструкциям раздела "Локальный Sybase."

Кроме того, если Вы используете Unix-платформу, и Sybase имеет многопоточный драйвер для этой платформы, следуйте инструкциям раздела "Sybase (только для Unix)." См. в Enterprise Server 3.x Release Notes список Unix-платформ, на которых Sybase имеет многопоточный драйвер.

Удалённый Sybase


Только для Unix: Установите следующие переменные окружения:


SYBASE
Директория верхнего уровня, в которой установлен Sybase.

LD_LIBRARY_PATH

(DEC) Обязана содержать $SYBASE/lib.

Для Solaris Вы обязаны также следовать инструкциям раздела "Sybase (только для Unix)."

Все платформы: Вы обязаны установить SYBASE Open Client/C. Поддерживаемые поставщики перечислены в разделе "Поддерживаемые Клиенты БД и ODBC-Драйверы."

Вы можете использовать подходящую утилиту Sybase для ввода в файл sql.ini (NT) и файл interfaces (все платформы) информации об удалённом сервере, с которым Вы хотите установить соединение. Дополнительно см. документацию Sybase.

Локальный Sybase


Только для Unix: Установите следующие переменные окружения:


SYBASE
Директория верхнего уровня, в которой установлен Sybase.
LD_LIBRARY_PATH

(DEC) Обязана содержать $SYBASE/lib.

Для Solaris Вы обязаны также следовать инструкциям раздела "Sybase (только для Unix)."

Все платформы: Установите Sybase SQL Server версии 11.1; клиентская часть устанавливается вместе с сервером. Поддерживаемые версии перечислены в разделе "Поддерживаемые Клиенты БД и ODBC-Драйверы."

Вы можете использовать подходящую утилиту Sybase для ввода в файл sql.ini (NT) и файл interfaces (все платформы) информации об удалённом сервере, с которым Вы хотите установить соединение. Дополнительно см. документацию Sybase.

Sybase (только для Unix)


На некоторых Unix-платформах Sybase имеет и однопоточный, и многопоточный драйверы. Если Sybase имеет многопоточный драйвер для конкретной Unix-машины, Вы обязаны использовать этот многопоточный драйвер с LiveWire. На этих платформах Ваш web-сервер будет вести себя непредсказуемо с однопоточным драйвером. Это требование применяется как для локальных, так и для удалённых соединений. оно не применяется к Windows-платформам.

См. в Enterprise Server 3.x Release Notes список Unix-платформ, на которых Sybase имеет многопоточный драйвер.

Чтобы убедиться в том, что Вы используете многопоточный драйвер, вы обязаны отредактировать Ваш файл $SYBASE/config/libtcl.cfg. Он содержит пару строк, которые включают однопоточный, либо многопоточный драйвер. Вы обязаны иметь одну из этих строк закомментированную, а другую активную. Например, на Solaris найдите эти строки:


[DRIVERS]
;libtli.so=tcp unused ; Это беспоточный tli-драйвер.
libtli_r.so=tcp unused ; Это поточный tli-драйвер.

Удостоверьтесь, что строка для однопоточного драйвера закомментирована, а строка многопоточного драйвера - не закомментирована. Имена файлов различаются на разных платформах, но эти строки всегда расположены в разделе DRIVERS и всегда закомментированы, чтобы различать однопоточный и многопоточный драйверы.

ПРИМЕЧАНИЕ:

Если вы хотите использовать утилиту Sybase isql, Вы обязаны использовать беспоточный tli -драйвер. В этом случае строка для libtli_r.so обязана быть закомментирована. Об использовании этого драйвера см. документацию по Sybase.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 12
Обработка Ошибок LiveWire

В этой главе рассмотрены типы ошибок, которые могут появиться при работе с реляционными БД.

В главе имеются следующие разделы:

Проверка Ошибочных Условий


При написании приложения на языке JavaScript Вы должны знать о различных ошибках. В тех случаях, когда Вы используете LiveWire Database Service для взаимодействия с реляционной БД, ошибки могут возникать по разным причинам. Например, SQL-операторы могут не выполняться из-за ограничений ссылочной целостности/referential integrity, потери привилегий доступа, блокировки записи или таблицы в многопользовательской БД и т.д. Если акция терпит неудачу, сервер БД возвращает сообщение об ошибке с указанием причины.

Ваш код должен проверять наличие ошибок и обрабатывать их соответствующим образом.

Return-Значения


Return-значение методов объектов LiveWire может указывать, имеется ошибка или нет. Методы могут возвращать значения различных типов. В зависимости от типа Вы можете получать различную информацию о возможных ошибках.

Число


Если метод возвращает число, return-значение может представлять число либо статус-код. Например, Cursor.columns возвращает количество столбцов в курсоре, а Cursor.updateRow возвращает число, обозначающее наличие или отсутствие ошибки.

Методы Cursor.columns и Resultset.columns возвращают числовое значение.

Следующие методы возвращают число, обозначающее статус-код:


Connection.beginTransaction
Connection.commitTransaction
Connection.execute
Connection.majorErrorCode
Connection.minorErrorCode
Connection.release
Connection.rollbackTransaction
Connection.SQLTable

Cursor.close
Cursor.deleteRow
Cursor.insertRow
Cursor.updateRow

database.beginTransaction
database.connect
database.commitTransaction
database.disconnect
database.execute
database.majorErrorCode
database.minorErrorCode
database.rollbackTransaction
database.SQLTable
database.storedProcArgs

DbPool.connect
DbPool.disconnect
DbPool.majorErrorCode
DbPool.minorErrorCode
DbPool.storedProcArgs

Resultset.close

Stproc.close

Если числовое return-значение метода указывает статус-код, 0 означает успешное выполнение, а ненулевое число указывает на ошибку. Если статус-код ненулевой, Вы можете использовать методы majorErrorCode и majorErrorMessage ассоциированного объекта Connection, database или DbPool для того, чтобы найти информацию об ошибке. В некоторых случаях методы minorErrorCode и minorErrorMessage предоставляют дополнительную информацию об ошибке. О return-значениях этих методов см. "Методы Работы с Ошибками".

Объект


Если метод возвращает объект, он может быть либо реальным объектом, либо null. Если метод возвращает null, возможно, возникла ошибка JavaScript. В большинстве случаев, если ошибка возникла в БД, метод возвращает верный объект, но программа устанавливает код ошибки.

Глобальная функция blob возвращает объект. Кроме того, следующие методы также возвращают объект:


Connection.cursor
Connection.storedProc
database.cursor
database.storedProc
DbPool (constructor)
DbPool.connection
Stproc.resultSet

Создаёте ли Вы курсор, результирующий набор или хранимую процедуру, Вы должны проверять и существование созданного объекта, и возможное наличие кода ошибки. Вы можете использовать методы majorErrorCode и majorErrorMessage для тестирования ошибки.

Например, Вы можете создать курсор и проверить его корректность кодом такого вида:


// Создаётся Cursor-объект.
custs = connobj.cursor ("select id, name, city
   from customer order by id");

// Прежде чем продолжить, убедитесь, что возвращён реальный курсор
// и что нет ошибки БД.
if ( custs && (connobj.majorErrorCode() == 0) ) {


   // Получить первый ряд.

   custs.next();

   // ... процессинг рядов курсора ...

   //Закрыть курсор.

   custs.close();
}

else

   // ... обработка ошибок ...

Булево Значение


Следующие методы возвращают Булевы значения:


Connection.connected
Cursor.next
database.connected
DbPool.connected
Resultset.next

Если метод возвращает Boolean-значение, true обычно указывает на успешное выполнение, в то время как false указывает на некоторое другое состояние. Return-значение false не означает реальной ошибки; оно может означать и условие успешного завершения.

Например, Connection.connected возвращает false для указания на то, что Connection -объект в данное время не соединён. Это может означать, что ошибка возникла при создании Connection -объекта или что ранее использованное соединение было намеренно разорвано. Эти события не являются ошибками метода connected. Если ошибка возникла при создании объекта, Ваш код должен отлавливать ошибку в работе этого метода. Если соединение было разорвано, Вы можете установить его вновь.

Второй пример - Cursor.next возвращает false, когда Вы ряды курсора закончились. Если оператор SELECT, используемый для создания Cursor -объекта, находит таблицу, но не находит столбцы, соответствующие условию оператора SELECT, создаётся пустой курсор. При первой Вашей попытке вызова метода next для этого курсора он возвращает false. Ваш код должен учитывать такую возможность.

Строка


Если метод возвращает строку, Вы обычно не получаете сообщения об ошибке. Если, однако, метод возвращает null, проверьте ассоциированный error-метод.

Следующие методы возвращают строку:


Connection.majorErrorMessage
Connection.minorErrorMessage
Cursor.columnName
database.majorErrorMessage
database.minorErrorMessage
DbPool.majorErrorMessage
DbPool.minorErrorMessage
Resultset.columnName

Void


Некоторые методы не возвращают значение. Вы не можете ничего сказать о возможных ошибках в работе этих методов. Следующие методы не возвращают значения:


Connection.release
Cursor.close
database.disconnect
DbPool.disconnect
Resulset.close

Методы Работы с Ошибками


Как уже было сказано, многие методы возвращают числовой статус-код. Если метод возвращает статус-код, может иметься и соответствующие код ошибки и сообщение от сервера БД. LiveWire имеет четыре метода для объектов Connection, DbPool и database для доступа к error-кодам и сообщениям БД.

Вот эти методы:

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

ПРИМЕЧАНИЕ: Вызов другого метода объектов Connection, DbPool или database может зачистить/reset error-коды и сообщения. Чтобы исключить потерю информации, не забудьте проверить эти методы, перед тем как продолжить.

После получения сообщения об ошибке ваше приложение может вывести сообщение пользователю. Ваше сообщение может включать строку, возвращённую majorErrorMessage или minorErrorMessage, или число, возвращённое majorErrorCode или minorErrorCode. Дополнительно можно обработать число или строку, перед тем как вывести их.

При обсчёте строки, возвращённой majorErrorMessage и minorErrorMessage, LiveWire возвращает строку поставщика БД с присоединённым дополнительным текстом. Детальную информацию о возвращаемых значениях см. в описаниях этих методов в книге Серверный JavaScript. Справочник .

Статус-Коды


В следующей таблице дан список статус-кодов, возвращаемых различными методами. Netscape рекомендует не использовать эти значения напрямую. Вместо этого, если метод возвращает ненулевое значение, используйте ассоциированные методы majorErrorCode и majorErrorMessage для определения конкретной ошибки.

Таблица 12.1  Статус-Коды методов LiveWire
Статус-Код Пояснение Статус-Код Пояснение

0

Нет ошибки

14

Null-параметр

1

Недостаточно памяти

15

Объект database не найден

2

Объект не был инициализирован

16

Отсутствует необходимая информация

3

Ошибка конвертации типов

17

Объект не поддерживает несколько читателей

4

БД не зарегистрирована

18

Объект не поддерживает удаление

5

Ошибка, выданная сервером

19

Объект не поддерживает вставку

6

Сообщение сервера

20

Объект не поддерживает обновление

7

Ошибка в библиотеке поставщика

21

Объект не поддерживает обновление

8

Потеря соединения

22

Объект не поддерживает индексы

9

Конец fetch (не смог перевести - прим. перев.)

23

Объект не может быть уничтожен

10

Неверное использование объекта

24

Предоставлено некорректное соединение

11

Столбец не существует

25

Объект не поддерживает привилегии

12

Неверное позиционирование внутри объекта (нарушение границ)

26

Объект не поддерживает курсоры

13

Неподдерживаемая возможность

27

Невозможно открыть

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 2
Введение

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

В главе имеются следующие разделы:

Архитектура Приложений JavaScript


Как уже говорилось, приложения JavaScript имею части, работающие на стороне клиента и на сервере. Кроме того, многие приложения JavaScript используют LiveWire Database Service для соединения приложения с реляционной базой данных. Исходя из этого, Вы можете представить приложения JavaScript как имеющие трёхслойную клиент-серверную архитектуру, как показано на Рисунке 2.1.

Рисунок 2.1   Архитектура среды клиент-серверного приложения на языке JavaScript

Три слоя - это:

Клиентская среда JavaScript работает как часть WWW -клиентов, а серверная среда JavaScript работает как часть Netscape web-сервера с доступом к одному или более серверов БД. Рисунок 2.2 показывает более детально, как серверная среда JavaScript и приложения, созданные для неё, встраиваются в Netscape web-сервер.

Верхняя часть Рисунка 2.2 демонстрирует то, как серверный JavaScript встраивается в Netscape web-сервер. Внутри web-сервера среда работы серверного JavaScript состоит из трёх основных компонентов, перечисленных ниже. JavaScript Application Manager работает поверх серверного JavaScript, как это делается в образце приложения, предоставленном Netscape (таком как приложение videoapp), и в любом приложении, созданном Вами.

Рисунок 2.2   Серверный JavaScript в среде Netscape-сервера

Имеются три главных компонента среды работы JavaScript:

В целом приложение на JavaScript может содержать операторы, интерпретируемые клиентом (интерпретатором JavaScript, предоставляемым Netscape Navigator'ом или некоторыми другими web-браузерами) и сервером (машиной выполнения JavaScript, уже рассмотренной).

Когда вы запускаете приложение JavaScript, происходят различные действия: некоторые на сервере, и некоторые - на клиенте. Хотя конечному пользователю не обязательно знать все детали, Вам как разработчику приложения необходимо понимать, что происходит "под капотом."

При создании приложения Вы пишете HTML-страницы, которые могут содержать операторы серверного и клиентского JavaScript. В исходном коде HTML клиентский JavaScript находится в тэгах SCRIPT, а серверный JavaScript - в тэгах SERVER.

Вы можете также писать файлы, содержащие только операторы JavaScript без тэгов HTML. Такой JavaScript-файл может содержать либо клиентский, либо серверный JavaScript; один файл не может содержать и клиентские, и серверные объекты или функции.

JavaScript VM (Виртуальная Машина), используемая в Netscape Enterprise Server 4.0, реализует значительные улучшения для обработки локальных переменных (то есть переменных, которые объявлены внутри функции), по сравнению с NES 3.6. Соответственно, рекомендуется минимизировать использование глобальных переменных (переменных между тэгами <server> и </server>) и переписать приложения для использования функций там, где это возможно. Это значительно повысит производительность приложения.

Если файлы HTML и JavaScript содержат серверный JavaScript, Вы затем компилируете их в единый исполняемый файл приложения JavaScript. Этот файл называется web-файлом и имеет расширение .web. Компилятор приложений JavaScript развёртывает HTML-код в платформонезависимые байт-коды, разбирая и компилируя операторы серверного JavaScript.

Наконец, Вы публикуете Ваше приложение на Вашем web-сервере и используете JavaScript Application Manager для инсталяции и запуска приложения, чтобы пользователи могли получить к нему доступ.

На этапе прогона, когда клиент запрашивает страницу приложения серверного JavaScript, машина выполнения локализует представление этого файла в web-файле приложения. Она запускает весь найденный серверный код и создаёт HTML-страницу для отправки клиенту. Эта страница может содержать как обычные тэги HTML, так и операторы клиентского JavaScript. Весь серверный код запускается на сервере до отправки страницы клиенту и до выполнения любого HTML или клиентского JavaScript. Соответственно, Ваш серверный код не может использовать клиентские объекты, так же как и клиентский код не может использовать серверные объекты.

Дополнительно см. Главу 5, "Основы Серверного JavaScript."

Системные Требования


Чтобы разрабатывать приложения JavaScript, использующие преимущества и клиентского, и серверного JavaScript, Вам нужна подходящая среда для разработки и публикации. В целом рекомендуется разрабатывать приложения на системе, отделённой от сервера публикации, поскольку разработка потребляет много ресурсов (порты соединений, пропускная способность, время процессора и память). При разработке также может быть нарушена работа уже опубликованных приложений конечного пользователя.

Среда разработки JavaScript состоит из:

Необходимые утилиты:

Публикация и машины публикации требуют наличия следующего программного обеспечения:

Кроме того, если ваше приложение использует JavaScript-службу LiveWire Database Service, Вам понадобится:

Информация Конфигурации


В этом разделе рассматривается информация конфигурации для использования серверного JavaScript. Дополнительно о настройке БД для работы с сервисом LiveWire Database Service см. Главу 10, "Конфигурирование Базы Данных."

Подключение Серверного JavaScript


Чтобы запускать приложения JavaScript на Вашем сервере, Вы обязаны подключить машину выполнения JavaScript в вашем Server Manager, щёлкнув Programs, а затем выбрав серверный JavaScript. После появления промпта "Activate the JavaScript application environment/Активизировать среду приложений JavaScript ?" выберите Yes и щёлкните OK. У Вас спросят также об ограничении доступа к Application Manager. Дополнительно см. "Защита Application Manager'а."

ПРИМЕЧАНИЕ: Если Вы не подключите машину выполнения JavaScript, приложения JavaScript не смогут запускаться на этом сервере.

Чтобы использовать и сервлеты, и LiveWire, Вам необходимо подключить серверный JavaScript до подключения Java. Оба могут быть подключены через использование меню программ Administration Server'а. Если Вы модифицируете путь к классам/classpath в obj.conf, Ваши изменения будут утеряны, если Вы подключите/отключите серверный JavaScript или Java из программного меню Administration Server'а. Альтернативой редактирования директивы classpath в obj.conf является установка переменной окружения CLASSPATH в Unix или установка переменной CLASSPATH в установках System в Windows NT. Если Вам нужно редактировать obj.conf непосредственно, сохраните первоначальный файл на всякий случай. В Enterprise Server 4.0 Вы должны добавить CLASSPATH info в файлы конфигурации JVM (jvm12.conf для Solaris и NT) через интерфейс Enterprise Administration Server.

Как только Вы активируете среду приложений JavaScript, Вы обязаны остановить и рестартовать Ваш web-сервер, чтобы ассоциированные переменные окружения начали действовать. Если этого не сделать, приложения JavaScript, использующие службу LiveWire Database Service, работать не будут.

Защита Application Manager'а


Application Manager предоставляет контроль над приложениями JavaScript. В связи с его особыми возможностями Вы должны защитить его от неавторизованного доступа. Если Вы не ограничиваете доступ к Application Manager'у, любой может добавлять, удалять, изменять, стартовать и останавливать приложения на Вашем сервере. Это, естественно, может привести к нежелательным последствиям.

Вы (разработчик приложений на JavaScript) должны иметь права доступа для использования Application Manager'а на сервере разработчика, так как Вы используете его для работы с приложением при разработке. Администратор Вашего web-сервера, однако, может не предоставить Вам таких прав на сервере разработчика.

Если Вы подключите машину выполнения JavaScript в Server Manager'е, промпт спросит Вас, ограничивать ли доступ к Application Manager'у. Выберите Yes и щёлкните OK. (Yes - по умолчанию.) После этого любой, кто попытается получить доступ к Application Manager'у, обязан будет ввести имя пользователя и пароль Server Manager'а, чтобы получить возможность использовать Application Manager и приложение-образец dbadmin. Дополнительно см. руководство администратора для Вашего web-сервера.

Если Ваш сервер не использует Secure Sockets Layer (SSL), имя пользователя и пароль для Application Manager'а передаются по сети в некодированном виде. Перехватив эти данные, можно получить доступ к Application Manager'у. Если Вы используете тот же самый пароль для Вашего сервера администратора, хакер получит также контроль и над этим сервером. Следовательно, можно рекомендовать не использовать Application Manager вне прокси-сервера, если Вы не используете SSL. О том, как подключить SSL к серверу, см. справочник администратора Вашего web-сервера.

Установки для LiveConnect


Чтобы использовать Java-классы в LiveConnect, Вам нужно установить CLASSPATH сервера. Полное описание этой процедуры дано в Programmer's Guide to Servlets и в Netscape Enterprise Server Administrator's Guide.

Локализация Компилятора


Инсталяция Netscape-сервера не изменяет Вашу переменную окружения PATH для включения директории, в которой установлен компилятор приложений JavaScript. Если Вам необходим быстрый доступ к компилятору, Вы обязаны модифицировать эту переменную.

В системах Unix у Вас есть выбор способов изменения переменной окружения PATH. Можно добавить $NSHOME/bin/https/lib, где $NSHOME это директория, в которой установлен Ваш сервер. Поговорите с Вашим системным администратором о том, как это сделать.

Чтобы изменить системный путь NT, запустите Control Panel, найдите диалоговое окно System и установите переменную PATH в разделе Environment settings, включив в неё %NSHOME%\bin\https\bin, где NSHOME это директория, в которой установлен Ваш сервер.

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

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Словарь

Здесь определены термины, используемые в приложениях JavaScript.

active application/активное приложение

Приложение JavaScript, которое стартовало и работает, или к которому клиенты осуществляют доступ.

application URL/URL приложения

Страница в приложении JavaScript, являющаяся базовым URL приложения. Клиенты используют URL приложения для доступа к конкретным страницам приложения.

ASCII

American Standard Code for Information Interchange. Определяет коды, используемые для хранения символов в компьютерах.

base application URL/базовый URL приложения

Имя приложения JavaScript, как оно специфицировано в Application Manager'е. Клиенты используют application URL для доступа к странице по умолчанию данного приложения.

BLOb

Binary large object/двоичный большой объект. Формат двоичных данных, хранимых в реляционной базе данных.

bytecodes/байт-коды

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

CGI

Common Gateway Interface. Спецификация для сообщения между HTTP-сервером и программами-шлюзами на сервере. CGI это популярный интерфейс, используемый для создания серверных web-приложений на языках типа Perl или C.

client/клиент

Web-браузер, такой как Netscape Navigator.

client cookie/клиентская "кука"

Один из методов, используемых в JavaScript для работы со свойствами client -объекта. Этот метод хранит пары имя/значение (куки) на клиентской машине.

client-side JavaScript/клиентский JavaScript

Ядро JavaScript плюс расширения, управляющие браузером (Navigator или иной web-браузер), и его DOM. Например, клиентские расширения позволяют приложению размещать элементы в HTML-форме и отвечать на пользовательские события, такие как щелчок мыши, ввод данных в форму и навигация по страницам. См. также core JavaScript, server-side JavaScript.

client URL encoding/клиентская кодировка URL

Один из методов, который в JavaScript используется для работы со свойствами client -объекта. Этот метод присоединяет пары имя/значение к строке URL.

commit/подтвердить

Чтобы выполнит все действия с БД в транзакции; попытка подтверждения может быть успешной или может потерпеть неудачу, в зависимости от акции и статуса БД.

cookie/кука

Механизм, с помощью которого Navigator-клиент может сохранять небольшие куски информации на клиентской машине.

CORBA

Common Object Request Broker Architecture. Стандарт, разработанный группой OMG (Object Management Group), программа Object Request Broker (ORB), которая обслуживает взаимодействие между объектами в распределённой компьютерной среде.

core JavaScript/ядро JavaScript

Элементы, общие для клиентского и для серверного JavaScript. Ядро JavaScript содержит основной набор объектов, таких как Array, Date и Math, и основной набор элементов языка, таких как операции, структуры управления и операторы. См. также client-side JavaScript, server-side JavaScript.

critical section/критичный блок (раздел)

Участок кода, в котором вам нужен исключительный доступ к объекту или свойству, чтобы убедиться в целостности данных.

current row/текущий ряд

Ряд в таблице, к которому обращается курсор базы данных.

current transaction/текущая транзакция

В приложении базы данных - активная транзакция, в которой выполняются все акции БД.

cursor/курсор

Структура данных, возвращаемых запросом к БД, состоящая из виртуальной таблицы и указателя на ряд в этой таблице; объект Cursor в JavaScript имеет соответствующие свойства и методы.

DDL

Data Definition Language. Операторы БД для создания, изменения или удаления объектов БД, таких как таблицы, ключи, хранимые процедуры и т.д.

deadlock/мёртвая блокировка/тупик

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

default page/страница по умолчанию

Страница, специфицированная в Application Manager, доступ к которой клиент получает, введя URL приложения, но не указав какую-то специфическую страницу приложения. Сравните с initial pagе/начальной страницей.

deploy/публиковать

Перенести приложение туда, где другие пользователи могут получить к нему доступ. Это может быть место в локальной файловой системе или на удалённом сервере, подключённом к Internet.

deployment server/сервер публикации

Сервер, на котором установлено приложение JavaScript, к которому (серверу) осуществляют доступ пользователи; называется также production server. Это не должен быть сервер разработки.

deprecate/не рекомендуется (применять)

Не рекомендуется использование данной возможности, но без удаления её из продукта. Когда возможность JavaScript не рекомендуется, обычно предлагается альтернатива; Вы не должны в дальнейшем использовать нерекомендуемые возможности, поскольку в последующих релизах они могут быть удалены.

development server/сервер разработки

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

DML

Data Manipulation Language. Операторы БД для выбора, обновления, вставки или удаления рядов таблиц.

ECMA

European Computer Manufacturers Association. Международная ассоциация стандартов информационных и коммуникационных систем.

ECMAScript

Стандартизованный международный язык программирования на базе ядра JavaScript. Эта стандартизованная версия JavaScript работает одинаково во всех приложениях, поддерживающих данный стандарт. Компании могут использовать открытый стандартный язык для разработки своих реализаций JavaScript. См. также core JavaScript.

external function/внешняя функция

Функция, определённая во внешней библиотеке и используемая в приложении JavaScript.

HTML

Hypertext Markup Language. Язык разметки, используемый для создания страниц для World Wide Web.

HTTP

Hypertext Transfer Protocol. Протокол соединения, используемый для передачи информации между серверами и клиентами web.

initial page/начальная страница

Страница, специфицированная в Application Manager, которую Application Manager запускает, когда приложение первоначально стартует. Сравните с default page.

IP address/IP-адрес

Набор из четырёх чисел в диапазоне от 0 до 255 включительно, разделённых точками, который специфицирует место по протоколу TCP/IP.

IP address technique/техника IP-адреса

Один из видов техники, используемой в JavaScript для обслуживания объекта client, когда сервер использует клиентский IP-адрес для обращения к структуре данных, содержащей значения свойств объекта client.

LiveConnect

Даёт возможность кодам на Java и JavaScript взаимодействовать друг с другом. Из JavaScript Вы можете инстанциировать Java-объекты и получать доступ к их public-методам и полям. Из Java Вы можете иметь  доступ к объектам, свойствам и методам JavaScript.

MIME

Multipart Internet Mail Extension. Стандарт, специфицирующий формат данных, пересылаемых по internet.

Netscape cookie protocol/протокол кук Netscape

Netscape-формат специфицирования параметров кук в "шапках"/header HTTP.

ODBC

Open Database Connectivity. Интерфейс Microsoft для программирования реляционных БД.

primitive value/примитивное значение

Данные, непосредственно представленные на самом нижнем уровне языка. Примитивное значение JavaScript является членом одного из следующих типов: undefined, null, Boolean, number или string.
Вот примеры некоторых примитивных значений:
a=true               // Boolean/Булево
b=42                  // number/число
c="Hello world"      // string/строка
if (x==undefined) {} // undefined ("не определено")
if (x==null) {}      // null

roll back/откат

Отмена всех акций в БД в пределах выполнения одной транзакции.

server cookie/серверная кука

Один из видов техники JavaScript для обслуживания объекта client, когда сервер генерирует уникальное имя для клиента, сохраняемое в cookie-файле на стороне клиента и позднее использует сохранённое имя для обращения к структуре данных, содержащей значения свойств объекта client.

server-side JavaScript/серверный JavaScript

Ядро JavaScript плюс расширения, относящиеся только к работе JavaScript на сервере. Например, серверные расширения дают приложению возможность соединяться с реляционной БД, сохранять непрерывность информации от одного вызова приложения до другого или выполнять манипуляции с файлами на сервере. См. также client-side JavaScript, core JavaScript.

server URL encoding/серверная кодировка URL

Один из видов техники JavaScript для обслуживания объекта client, когда сервер генерирует для клиента уникальное имя, присоединяет его к URL и позднее использует сохранённое имя для обращения к структуре данных, содержащей значения свойств объекта client.

Session Management Service/Служба Обслуживания Сессий

4 предопределённых объекта JavaScript - request, client, project и server - и один класс, Lock, предоставляющие основу для совместного использования данных запросами, клиентами и приложениями.

SQL

Structured Query Language. Стандартный язык для определения, управления и запрашивания реляционных баз данных.

static-метод или свойство

Метод или свойство встроенного объекта, которые не могут быть свойством экземпляров объекта. Например, Вы можете инстанциировать (создать экземпляры) новые экземпляры объекта Date. Некоторые методы объекта Date, такие как getHours и setDate, являются также методами экземпляров объекта Date. Другие методы объекта Date, такие как parse и UTC, являются static/статическими, и экземпляры объекта Date не имеют этих методов.

stopped application/остановленное приложение

Приложение, остановленное Application Manager'ом и недоступное клиентам.

transaction/транзакция

Группа акций БД, которые выполняются вместе; все акции проходят или все терпят неудачу.

updatable cursor/обновляемый курсор

Курсор БД, в котором Вы можете обновлять таблицы на основе содержимого виртуальной таблицы.

URL

Universal Resource Locator. Схема адресации, используемая в World Wide Web.

web-файл

Скомпилированная форма приложения JavaScript; содержит байт-коды. Обязана быть установлена на Netscape web-сервере, чтобы функционировать.

WWW

World Wide Web
.
Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 1
JavaScript. Обзор.

Это введение в JavaScript и обсуждение некоторых фундаментальных понятий.

В главе имеются следующие разделы:

Что Такое JavaScript?


JavaScript это созданный фирмой Netscape межплатформенный, объектно-ориентированный язык скриптинга (сценариев). Ядро JavaScript содержит набор основных объектов, таких как Array, Date и Math, и основной набор элементов языка, таких как операции, структуры управления и операторы. Ядро JavaScript может быть расширено для различных целей путём дополнения новыми объектами; например:

JavaScript позволяет создавать приложения, работающие по всей сети Internet. Клиентские приложения работают в браузере, таком как Netscape Navigator, а серверные приложения - на сервере, таком как Netscape Enterprise Server. Используя JavaScript, Вы можете создавать динамические HTML-страницы, обрабатывающие пользовательский ввод и имеющиеся данные, используя специальные объекты, файлы и реляционные БД.

С помощью функциональности JavaScript LiveConnect Вы можете организовать взаимодействие кодов Java и JavaScript. Из JavaScript Вы можете инстанциировать объекты Java и получать доступ к их public-методам и полям. Из Java Вы можете получать доступ к объектам, свойствам и методам JavaScript.

Корпорация Netscape изобрела JavaScript, и JavaScript был впервые использован в браузерах Netscape.

Ядро, Клиентский и Серверный  JavaScript


Компоненты JavaScript показаны на рисунке:

Рисунок 1.1   Язык JavaScript

В следующем разделе разбирается работа JavaScript на стороне клиента и на сервере.

Ядро JavaScript


Клиентский и серверный JavaScript имеют следующие общие элементы:

Клиентский JavaScript


Web-браузеры, такие как Navigator (2.0 и более поздние версии) могут интерпретировать операторы клиентского JavaScript, внедрённые в HTML-страницу. Когда браузер (или клиент) запрашивает такую страницу, сервер высылает клиенту по сети полное содержимое документа, включая HTML и операторы JavaScript. Браузер читает страницу сверху вниз, отображая результат работы HTML и выполняя операторы JavaScript по мере их обнаружения. Этот процесс, проиллюстрированный на рисунке, производит результат, который видит пользователь.

Рисунок 1.2   Клиентский JavaScript

Операторы клиентского JavaScript, встроенного в HTML-страницу, могут реагировать на пользовательские события, такие как щелчок мыши, ввод данных в форму и навигация по страницам. Например, Вы можете написать функцию JavaScript для проверки ввода пользователем правильной информации в форму, запрашивающую телефонный номер или zip-код. Без передачи по сети внедрённый JavaScript на HTML-странице может проверить введённые данные и вывести диалоговое окно, если пользователь ввёл неверные данные.

Разные версии JavaScript работают со специфическими версиями Navigator'а. Например, JavaScript 1.2 работает с Navigator 4.0. Некоторые возможности JavaScript 1.2 недоступны в JavaScript 1.1 и поэтому недоступны в Navigator 3.0. Информацию о версиях JavaScript и Navigator см. в разделе "Версии JavaScript".

Серверный JavaScript


На сервере Вы также можете внедрять JavaScript в HTML-страницы. Серверные операторы могут соединяться с реляционными БД разных производителей, разделять информацию между пользователями приложения, получать доступ к файловой системе сервера или взаимодействовать с другими приложениями через LiveConnect и Java. HTML-страницы с серверным JavaScript могут содержать также клиентский JavaScript.

В отличие от страниц с чисто клиентским JavaScript, HTML-страницы, использующие серверный JavaScript, компилируются в байт-кодовые исполняемые файлы. Эти исполняемые приложения запускаются на выполнение web-сервером, имеющим машину времени выполнения JavaScript. Исходя из этого, создание приложений JavaScript это процесс из двух этапов.

На первом этапе, показанном на Рисунке 1.3, Вы создаёте HTML-страницы (которые могут содержать операторы как клиентского, так и серверного JavaScript) и файлы JavaScript. Затем Вы компилируете все эти файлы в единый исполняемый блок.

Рисунок 1.3   Серверный JavaScript в процессе разработки

На втором этапе, показанном на Рисунке 1.4, страница приложения запрашивается клиентским браузером. Машина выполнения использует исполняемый блок для просмотра исходной страницы и динамической генерации HTML-страницы, возвращаемой клиенту. Она выполняет все найденные на странице операторы серверного JavaScript. Выполнение этих операторов может добавить новые операторы HTML или операторы клиентского JavaScript в HTML-страницу. Машина выполнения отсылает затем окончательный вариант страницы по сети Navigator-клиенту, который выполняет клиентский JavaScript и отображает результат.

Рисунок 1.4   Серверный JavaScript в процессе выполнения

В отличие от стандартных программ Common Gateway Interface (CGI), все исходники JavaScript интегрированы непосредственно в HTML-страницы, ускоряя разработку и облегчая обслуживание. Служба Session Management Service серверного JavaScript содержит объекты, которые Вы можете использовать для работы с данными, существующими между клиентскими запросами, у нескольких клиентов или нескольких приложений. Служба LiveWire Database Service серверного JavaScript предоставляет объекты для доступа к БД, служащие интерфейсом для серверов Structured Query Language (SQL).

JavaScript и Java


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

В отличие от системы времени компиляции Java, построенной на объявлениях, JavaScript поддерживает систему времени выполнения, основанную на небольшом количестве типов данных: числовых, Булевых и строковых. JavaScript имеет объектную модель на базе прототипов вместо более общей объектной модели на базе классов. Модель на базе прототипов предоставляет возможность динамического наследования; то есть, то, что наследуется, может отличаться для разных объектов. JavaScript также поддерживает функции без специальных требований объявления. Функции могут быть свойствами объектов, исполняемыми как нетипизированные методы.

JavaScript это язык, свободный по форме, по сравнению с Java. Вы не должны объявлять все переменные, классы и методы. Вы не должны учитывать, являются ли методы public, private или protected, и не обязаны реализовывать интерфейсы. Return-типы переменных, параметров и функций не типизированы явно.

Java это язык на базе классов, разработанный для быстрого выполнения и строгой типизации. Строгая типизация означает, к примеру, что Вы не можете привести/cast целое число Java (integer) к ссылке на объект или получить доступ к private-памяти, нарушая байт-коды Java. Модель Java на базе классов означает, что программы состоят исключительно из классов и их методов. Наследование классов в Java и строгая типизация обычно требуют тесно выстроенной иерархий объектов. Эти требования делают программирование на Java более сложным, чем авторизация на JavaScript.

В противоположность этому, JavaScript ведёт своё начало от небольших динамически типизированных языков, таких как HyperTalk и dBASE. Эти языки сценариев предоставляют утилиты программирования для более широкой аудитории, поскольку имеют облегчённый синтаксис, специализированную встроенную функциональность и минимальные требования при создании объектов.

Таблица 1.1  JavaScript в сравнении с Java
JavaScript Java

Интерпретируется (не компилируется) клиентом.

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

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

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

Коды интегрированы и внедрены в HTML.

Аплеты отличаются от HTML (доступ к ним осуществляется из HTML-страниц).

Типы переменных не объявляются (динамическая типизация).

Типы переменных обязаны быть объявлены (статическая типизация).

Не может автоматически записывать на жёсткий диск.

Не может автоматически записывать на жёсткий диск.

Отладка в JavaScript


JavaScript позволяет создавать сложные компьютерные программы. Как и во всех других языках, Вы можете ошибаться при написании скриптов. Отладчик Netscape JavaScript Debugger даёт возможность отлаживать Ваши скрипты.

об использовании Отладчика см. Getting Started with Netscape JavaScript Debugger .

Visual JavaScript


Netscape Visual JavaScript это утилита визуальной разработки на базе компонентов для платформы Netscape Open Network Environment (ONE). Он первоначально предназначался для использования разработчиками межплатформенных стандартизованных web-приложений из готовых компонентов с минимальными затратами на программирование. Эти приложения базируются на HTML, JavaScript и Java.

О Visual JavaScript см. Visual JavaScript Developer's Guide .

JavaScript и Спецификация ECMA


Netscape изобрела JavaScript, и JavaScript был впервые использован в браузерах Netscape. Одновременно Netscape работает с ECMA (European Computer Manufacturers Association) для создания стандартизованного международного языка программирования на базе ядра JavaScript. ECMA это международная ассоциация стандартов в области систем информации и коммуникаций. Эта стандартизованная версия JavaScript, называемая ECMAScript, ведёт себя совершенно одинаково во всех приложениях, поддерживающих этот стандарт. Компании могут использовать этот открытый стандартный язык для создания своих реализаций JavaScript. Первая версия стандарта ECMA документирована в спецификации ECMA-262.

Стандарт ECMA-262 одобрен также ISO (International Organization for Standards) как ISO-16262. Вы можете найти PDF-версию ECMA-262 на Netscape DevEdge Online. Вы также можете найти эту спецификацию на сайте ECMA. Спецификация ECMA не описывает Document Object Model (DOM), которая стандартизуется консорциумом World Wide Web Consortium (W3C). DOM определяет способ, которым объекты HTML-документа экспонируются в скрипте.

Соотношение Между Версиями JavaScript и ECMA


Netscape тесно сотрудничает с ECMA для создания спецификации ECMA.

Детальную информацию о соотношении версий спецификаций JavaScript и ECMA см. на сайте mozilla.org.

JavaScript всегда будет содержать возможности, не включённые в спецификацию ECMA; JavaScript совместим с ECMA, предоставляя дополнительные возможности.

Документация JavaScript и Спецификация ECMA


Спецификация ECMA это набор требований по реализации ECMAScript; она применима, если Вам необходимо определить, поддерживается ли возможность из JavaScript в ECMA. Если Вы планируете написать код JavaScript, использующий только возможности, поддерживаемые ECMA, Вам может понадобиться просмотреть спецификацию ECMA.

Документ ECMA не предназначен для помощи программистам скриптов; для этого используйте документацию JavaScript.

JavaScript и Технология ECMA


Спецификация ECMA использует терминологию и синтаксис, которые могут быть незнакомы программистам JavaScript. Хотя описание языка может отличаться в ECMA, сам язык остаётся тем же самым. JavaScript поддерживает всю функциональность, данную в спецификации ECMA.

Документация по JavaScript описывает аспекты языка, необходимые программисту на JavaScript. Например:

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 5
Основы Серверного JavaScript

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

В главе имеются следующие разделы:

Серверный JavaScript имеет то же ядро языка, что и клиентский JavaScript, с которым Вы, возможно, уже знакомы. Задачи, выполняемые Вами при запуске JavaScript на сервере, несколько отличаются от задач, выполняемых при работе JavaScript на клиенте. Разные окружения и задачи обращаются к различным объектам.

Что Делать и Где


Клиентская среда (браузер) является передним краем работы приложения. В этой среде, к примеру, Вы отображаете HTML-страницы в окне и обслуживаете истории сессий HTML-страниц, отображаемых в браузере в течение сессии. Объекты этой среды, следовательно, обязаны иметь возможность манипулировать страницами, окнами и историей.

По контрасту, в серверной среде Вы работаете с ресурсами сервера. Например, Вы можете установить соединение с реляционной базой данных, распределить информацию между пользователями приложения или манипулировать файловой системой сервера. Объекты этой среды обязаны иметь возможность манипулировать реляционной БД и файловой системой сервера.

Кроме того, HTML-страница не отображается на сервере. Она запрашивается на сервере для отображения на клиенте. Запрошенная страница может содержать клиентский JavaScript. Если запрошенная страница является частью приложения JavaScript, сервер может генерировать эту страницу "на лету".

При разработке приложения JavaScript помните о разнице между клиентской и серверной платформами. Различия показаны в следующей таблице.

Таблица 5.1 Сравнение Клиента и Сервера
Серверы Клиенты

Серверы обычно (хотя и не всегда) являются высокопроизводительными рабочими станциями с быстрыми процессорами и возможностью хранения больших объемов информации.

Клиенты часто (хотя и не всегда) являются настольными системами с маломощными процессорами и относительно небольшим объемом хранимых данных.

Серверы могут быть перегружены при одновременном доступе тысяч клиентов.

Клиенты часто - машины одного пользователя, поэтому можно передать часть нагрузки процессинга клиенту.

Предварительная обработка данных на клиенте также может уменьшить требования к пропускной способности сети, если клиентское приложение может компоновать данные.

Обычно имеются разные пути распределения приложения между сервером и клиентом. Некоторые задачи могут выполняться только на клиенте или только на сервере; другие могут выполняться на любом из них. Хотя нет какого-то определённого способа определить, что и где делать, Вы может следовать следующим общим правилам:

Основное правило - использовать клиентский процессинг (тэг SCRIPT) для следующих задач:

Использовать серверный процессинг (тэг SERVER) для следующих задач:

Служба JavaScript Session Management Service предоставляет объекты для сохранения информации, а клиентский JavaScript преходящ. Клиентские объекты существуют, пока пользователь имеет доступ к странице. Серверы могут объединять информацию от многих клиентов и многих приложений и могут сохранять большие объёмы данных в базе данных. Важно помнить обо всех этих характеристиках при распределении функциональности между клиентом и сервером.

Обзор Процессов Времени Прогона (Выполнения)


После того как Вы установили и стартовали приложение JavaScript, пользователь может получить к нему доступ.
Базовые процедуры таковы:

  1. Пользователь выполняет доступ к приложению по его URL в web-браузере, таком как Netscape Communicator. Браузер отправляет клиентский запрос страницы приложения на сервер.
  2. Если это запрос к странице с URL приложения, машина выполнения JavaScript, запущенная на сервере, находит информацию в web-файле, соответствующем этому URL. О деталях этого процесса и о том, что происходит на этом и на последующих двух этапах, см. в разделе "Процессинг Времени Прогона на Сервере".
  3. Машина времени выполнения конструирует HTML-страницу для отправки клиенту. Она выполняет байт-коды, ассоциированные с тэгами SERVER, из исходного кода HTML, создавая HTML-страницу на основе этих байт-кодов и иного HTML, имеющегося в оригинале. О том, как влиять на процесс конструирования страницы, см. в разделе "Конструирование HTML-Страницы".
  4. Машина выполнения высылает новую HTML-страницу (которая может содержать операторы клиентского JavaScript) клиенту.
  5. Машина выполнения JavaScript внутри web-браузера интерпретирует любые операторы клиентского JavaScript, форматирует вывод HTML и выводит результат пользователю.

Рисунок 5.1 иллюстрирует это процесс.

Рисунок 5.1   Процессинг запроса JavaScript-страницы

Конечно, пользователь обязан иметь Netscape Navigator (или иной браузер с возможностью выполнения JavaScript), чтобы клиент мог интерпретировать операторы клиентского JavaScript. Аналогично, если Вы создаёте страницу, содержащую серверный JavaScript, он должен быть установлен на Netscape-сервере, чтобы нормально функционировать.

Например, предположим, клиент запрашивает страницу с таким исходным кодом:


<html>
<head> <title> Add New Customer </title> </head>

<body text="#FFFF00" bgcolor="#C0C0C0" background="blue_marble.gif">
<img src="billlog2.gif">
<br>


<server>
if ( project.lock() ) {
   project.lastID = 1 + project.lastID;
   client.customerID = project.lastID;
   project.unlock();
}
</server>

<h1>Add a New Customer </h1>
<p>Note: <b>All</b> fields are required for the new customer
<form method="post" action="add.html"></p>
<p>ID:
<br> <server>write("<STRONG><FONT COLOR=\"#00FF00\">" +
   project.lastID + "</FONT></STRONG>");</server>

<!-- другие операторы html -->

</body>

</html>

При доступе к этой странице машина выполнения выполняет на сервере код, ассоциированный с тэгами SERVER. (Этот код выделен жирным шрифтом.) Если ID нового потребителя 42, сервер высылает клиенту для отображения такую HTML-страницу:


<html>
<head> <title> Add New Customer </title> </head>


<body text="#FFFF00" bgcolor="#C0C0C0" background="blue_marble.gif">
<img src="billlog2.gif">
<br>

<h1>Add a New Customer
</h1>
<p>Note: <b>All</b> fields are required for the new customer
<form method="post" action="add.html"></p>
<p>ID:
<br><STRONG><FONT COLOR="#00FF00">42</FONT></STRONG>

<!-- другие операторы html -->


</body>
</html>

Серверный Язык. Обзор.


И клиентский, и серверный JavaScript реализуют язык JavaScript. Но каждый при этом добавляет специфические объекты и функции для работы в клиентской или серверной среде. Например, клиентский JavaScript включает объект form для представления формы на HTML-странице, а серверный JavaScript включает объект database для соединения с внешней реляционной БД.

В книге Клиентский JavaScript. Руководство. детально рассматривается ядро языка JavaScript и дополнительная специфика клиентского JavaScript.

ECMA, Европейская организация стандартизации систем информации и коммуникаций, выпустила стандарт ECMA-262 языка JavaScript. Вы можете загрузить эту спецификацию с сайта ECMA по адресу http://www.ecma.ch .

Прототипы


Как указано в книге Серверный JavaScript. Справочник. , Вы можете использовать свойство prototype многих классов, чтобы добавлять новые свойства в класс и во все его экземпляры. Как описано в разделе "Классы и Объекты", серверный JavaScript добавляет несколько классов и предопределённых объектов. В новых классах, имеющих свойство prototype, оно работает в серверном JavaScript точно так же, как и в клиентском JavaScript.

Вы можете использовать свойство prototype для добавления новых свойств в классы Blob, Connection, Cursor, DbPool, File, Lock, Resultset, SendMail и Stproc. Кроме того, Вы можете использовать свойство prototype класса DbBuiltin для добавления свойств в предопределённый объект database. Обратите внимание, что Вы не можете создать экземпляр класса DbBuiltin; вместо этого Вы используете объект database, предоставляемый машиной выполнения JavaScript.

Вы не можете использовать prototype с объектами client, project, request и server.

Так же, как и в клиентском JavaScript, Вы можете использовать свойство prototype для любого класса, который Вы определяете в своём приложении.

Помните, что все приложения JavaScript на сервере работают в одной среде. Вот почему Вы можете распределять информацию между клиентами и приложениями. Следствием этого, однако, является то, что при использовании свойства prototype для добавления нового свойства в любой серверный класс, добавленный языком JavaScript, новое свойство доступно всем приложениям, работающим на сервере, а не только приложению, в котором это свойство было добавлено. Это даёт возможность легко добавлять функциональность всем приложениям JavaScript на Вашем сервере.

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

Использование


Вам необходимо знать, как компилятор приложений JavaScript распознаёт клиентский и серверный JavaScript в HTML-файле.

Операторы клиентского JavaScript могут появляться в следующих ситуациях:

О деталях см. книгу Клиентский JavaScript. Руководство .

Операторы серверного JavaScript могут появляться в следующих ситуациях:

Заметьте, что Вы не можете специфицировать оператор серверного JavaScript как обработчик события. Дополнительно см. "Внедрение JavaScript в HTML".

Окружение (Рабочая Среда)


Возможности LiveConnect ядра языка JavaScript работают на сервере иначе, чем на клиенте. См. дополнительно Главу 14, "LiveConnect. Обзор.".

JavaScript предоставляет дополнительную функциональность без использования объектов. Вы получаете доступ к этой функциональности через функции, не ассоциированные с каким-либо объектом (глобальные функции). Ядро языка JavaScript имеет глобальные функции, описанные в следующей таблице (также как и другие функции, описанные в документации Ядра JavaScript).

Таблица 5.2  Глобальные Функции Ядра JavaScript
Функция Описание

escape

Возвращает 16-ричный код аргумента - символа из набора символов ISO Latin-1; используется при создании строк для добавления в URL.


unescape

Возвращает ASCII-строку для специфицированного значения; используется при разборе строки, добавленной в URL.


isNaN

Вычисляет аргумент для определения не является ли он "неЧислом".


parseFloat

Разбирает аргумент-строку и возвращает число с плавающей точкой.


parseInt

Разбирает аргумент-строку и возвращает целое число.

Серверный JavaScript добавляет глобальные функции, описанные в следующей таблице.

Таблица 5.3  Глобальные Функции Серверного JavaScript
Функция Описание

write

Добавляет операторы к генерируемой клиентской HTML-странице. (См. "Генерация HTML".)


flush

Очищает буфер вывода. (См. "Очистка Буфера Вывода".)


redirect

Перенаправляет клиента по специфицированному URL. (См. "Переход к Новому Клиентскому Запросу".)


getOptionValue

Получает значения отдельных опций в элементе HTML-формы SELECT. (См. "Использование Списков Выбора".)


getOptionValueCount

Получает количество опций в элементе HTML-формы SELECT. (См. "Использование Списков Выбора".)


debug

Выводит значения выражений в окне (фрэйме) трассировки. (См. "Использование Функции debug".)


addClient

Присоединяет клиентскую информацию к URL. (См. "Присоединение client-Свойств к URL Вручную".)


registerCFunction

Регистрирует внешнюю функцию для использования в серверном JavaScript. (См. "Регистрация Внешних Функций/Native Functions".)


callC

Вызывает внешнюю функцию. (См. "Использование Внешних Функций в JavaScript".)


deleteResponseHeader

Удаляет информацию из "шапки" ответа, высылаемого клиенту. (См. "Манипуляции с Запросом и Ответом".)


addResponseHeader

Добавляет новую информацию в "шапку" ответа, высылаемого клиенту. (См. "Манипуляции с Запросом и Ответом".)


ssjs_getClientID

Возвращает идентификатор для client -объекта, используемый при некоторых видах клиентской техники JavaScript. (См. "Уникальное Обращение к Объекту client".)


ssjs_generateClientID

Возвращает идентификатор, который Вы можете использовать для уникального специфицирования объекта client. (См. "Уникальное Обращение к Объекту client".)


ssjs_getCGIVariable

Возвращает значение специфицированной переменной окружения CGI. (См. "Доступ к Переменным CGI".)

Классы и Объекты


Для поддержания различных задач, выполняемых на каждой стороне, JavaScript имеет классы и предопределённые объекты, которые работают на клиенте, но не на сервере, и другие классы и предопределённые объекты, которые работают на сервере, но не на клиенте.

Важно!

Названия этих объектов зарезервированы для JavaScript. Не создавайте Ваши собственные объекты, используя эти имена.

Ядро языка JavaScript предоставляет классы, описанные в следующей таблице. Детальную информацию обо всех этих объектах см. в книге Серверный JavaScript. Справочник .

Таблица 5.4  Классы Ядра JavaScript
Класс Описание

Array

Массив.


Boolean

Булево значение.


Date

Дата.


Function

Специфицирует строку кода JavaScript, компилируемую как функция.


Math

Предоставляет основные математические константы и функции; например, свойство PI содержит значение pi.


Number

Примитивные числовые значения.


Object

Базовая функциональность всех объектов JavaScript.


Packages

Пакет Java в JavaScript. используется вместе с LiveConnect.


String

Строка JavaScript.

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

Таблица 5.5  Классы Серверного JavaScript
Класс Описание

Connection

Одиночное соединение с БД из пула соединений. (См. "Отдельные Соединения с БД").


Cursor

Курсор БД. (См. "Манипуляции с Результатами Выполнения Запроса с Помощью Курсоров").


DbPool

Пул соединений с базами данных. (См. "Пулы Соединений с Базами Данных").


Stproc

Хранимая процедура БД. (См. "Вызов Хранимых Процедур").


Resultset

Представляет информацию, возвращаемую хранимой процедурой БД. (См. "Вызов Хранимых Процедур".)


File

Предоставляет доступ к файловой системе сервера. (См. "Служба Файловой Системы".)


Lock

Предоставляет функциональность для безопасного совместного использования/sharing данных запросами, клиентами и приложениями. (См. "Безопасное Совместное Использование Объектов с Блокировкой".)


SendMail

Предоставляет функциональность для отправки электронной почты из вашего приложения JavaScript. (См. "Почтовая Служба".)

Кроме того, серверный JavaScript имеет предопределённые объекты, описанные в следующей таблице. Эти объекты доступны для каждого HTTP-запроса. Вы не можете создать дополнительные экземпляры какого-либо из этих объектов.

Таблица 5.6  Объекты Серверного JavaScript
Объект Описание

database

Соединение с базой данных. (См. "Соединение. Подходы.")


client

Инкапсулирует информацию о паре клиент/приложение, позволяя хранить эту информацию дольше, чем в течение одного HTTP-запроса. (См. "Объект client.")


project

Инкапсулирует информацию о приложении, которая хранится, пока приложение не прекратит работу на сервере. (См. "Объект project".)


request

Инкапсулирует информацию об отдельном HTTP-запросе. (См. "Объект request".)


server

Инкапсулирует глобальную информацию о сервере, которая хранится, пока сервер не остановится. (См. "Объект server".)

Внедрение JavaScript в HTML


Есть два способа встроить операторы серверного JavaScript в HTML-страницу:

Если Вы внедряете серверный JavaScript в HTML-страницу, машина выполнения JavaScript на сервере выполняет обнаруженные ею операторы при процессинге (обработке) страницы. Большинство операторов выполняют какие-либо операции на сервере, такие как открытие соединения с БД или блокировка совместно используемого объекта. Однако, если Вы используете функцию write в тэге SERVER или заключаете операторы в обратные кавычки, машина выполнения динамически генерирует новый HTML для модифицирования страницы, высылаемой клиенту.

Тэг SERVER


Тэг SERVER это наиболее распространённый способ внедрения серверного JavaScript в HTML-страницу. Вы можете использовать тэг SERVER в любой ситуации; обычно, однако, вместо него используются обратные кавычки, если Вы генерируете имена или значения атрибутов для HTML-страницы.

Большая часть операторов между тэгами <SERVER> и </SERVER> не появляется на HTML-странице, высылаемой клиенту. Эти операторы выполняются на сервере. Однако вывод вызовов функции write появляется в результирующем HTML.

Следующая выдержка из приложения Hello World иллюстрирует эти варианты:


<P>This time you are 
<SERVER>
write(request.newname);
client.oldname = request.newname;
</SERVER>
<h3>Enter your name</h3>

Получив данный участок кода, машина выполнения генерирует HTML на базе значения request.newname в операторе write. Во втором операторе она просто выполняет операцию JavaScript, присваивая значение request.newname свойству client.oldname. Она не генерирует никакого HTML. Итак, если request.newname будет "Mr. Ed," машина выполнения генерирует из предыдущего отрывка следующий HTML:


<P>This time you are
Mr. Ed
<h3>Enter your name</h3>

Обратные Кавычки


Используйте обратные кавычки (`) для выделения выражений серверного JavaScript как заместителей для имён атрибутов или значений атрибутов HTML. JavaScript, внедрённый  в HTML с помощью обратных кавычек, автоматически генерирует HTML; Вам не нужно использовать write.

В целом тэги HTML имеют форму:


<TAG ATTRIB="value" [...ATTRIB="value"]>

где ATTRIB   это атрибут, а " value " это его значение. Значение в угловых скобках означает, что допускается любое количество пар атрибут/значение.

Если в обратные кавычки заключено выражение JavaScript, используемое как значение атрибута, машина выполнения JavaScript автоматически добавляет знак кавычки вокруг всего значения. Вы сами не вводите знаки кавычек, хотя Вам это может понадобиться для разграничения строковых литералов выражения, как в следующем примере. Машина выполнения не делает это для имён атрибутов, поскольку не предполагается заключение имён атрибутов в кавычки.

Например, рассмотри следующую строку из образца-приложения Hangman:


<IMG SRC=`"images\hang" + client.num_misses + ".gif"`>

Эта строка динамически генерирует имя изображения на основе значения client.num_misses. Обратные кавычки обрамляют выражение JavaScript, конкатенирующее строку "images\hang" и целочисленное значение client.num_misses и строку ".gif", давая строку типа "images\hang0.gif". Результатом будет HTML, такой как


<IMG SRC="images\hang0.gif">

Порядок ввода кавычек является критичным. Сначала идёт обратная кавычка, указывая, что следующее значение является выражением JavaScript, состоящим из строки ("images\hang"), соединяемой с целым числом (client.num_misses) и с другой строкой (".gif"). JavaScript конвертирует всё выражение до строки и добавляет необходимые знаки кавычек вокруг значения атрибута.

Вы должны внимательно использовать знаки двойных кавычек внутри обратных кавычек, поскольку содержащееся внутри них значение интерпретируется как литерал. Поэтому не окружайте выражения JavaScript, которые необходимо вычислить, знаками кавычек. Например, если значение свойства client.val будет NetHead, то данный оператор:


<A NAME=`client.val`>

генерирует такой HTML:


<A NAME="NetHead">

но следующий оператор:


<A NAME=`"client.val"`>

генерирует HTML:


<A NAME="client.val">

В качестве другого примера приведём два атрибута тэга ANCHOR - HREF и NAME. HREF делает тэг гиперссылкой, а NAME делает его именованным якорем. Следующие операторы используют переменную choice для установки свойств attrib и val объекта client и создают затем гиперссылку/hyperlink или цель/target, в зависимости от значений:


<SERVER>
if (choice == "link") {
   client.attrib = "HREF";
   client.val = "http://www.netscape.com";
}
if (choice == "target") {
   client.attrib = "NAME";
   client.val = "NetHead";
}
</SERVER>

<A `client.attrib`=`client.val`>Netscape
Communications</A>

Если значением choice будет "link", результат будет:


<A HREF="http://home.netscape.com">Netscape Communications</A>

Если значением choice будет "target", результат будет:


<A NAME="NetHead">Netscape Communications</A>

Когда Использовать Эти Виды Техники


В большинстве случаев ясно, когда использовать тэг SERVER, а когда - обратные кавычки. Иногда, однако можно достичь того же результата другим путём ("Мы пойдём..."). В общем, лучше использовать обратные кавычки для внедрения значений JavaScript в тэги HTML, а в других случаях - тэг SERVER.

Например, в Hangman вместо


<IMG SRC=`"images\hang" + client.num_misses + ".gif"`>

можно записать


<SERVER>
write("<IMG SRC=\"images\hang");
write(client.num_misses);
write(".gif\">");
</SERVER>

Обратите внимание, что обратная наклонная черта (backslash) даёт возможность ввести знак кавычки внутри литеральной строки. Хотя результирующий HTML - тот же самый, в этом случае обратные кавычки предпочтительнее, поскольку исходник легче читать и редактировать.

Процессинг Времени Прогона на Сервере


В разделе "Обзор Процессинга Времени Выполнения" показано, что происходит на этапе прогона, если пользователь выполняет доступ к странице приложения JavaScript. В данном разделе детально рассматриваются этапы этого процесса со 2 по 4, чтобы Вы смогли лучше понять, что происходит на каждом этапе. Это описание предоставляет контекст для понимания того, что Вам нужно делать на клиенте и сервере.

При работе с приложениями JavaScript важно помнить об асинхронной природе процессов Web. Приложения JavaScript разрабатываются для использования многими пользователями одновременно. Машина выполнения JavaScript на сервере обрабатывает запросы нескольких пользователей по мере их поступления и выполняет их в порядке поступления.

В отличие от традиционного приложения, которое запускается отдельным пользователем на отдельной машине, Ваше приложение обязано поддерживать одновременный доступ нескольких пользователей. Фактически, поскольку каждый фрэйм (кадр) HTML-документа из нескольких фрэймов генерирует свой собственный запрос/request, для машины выполнения может оказаться, что запрос одного пользователя является множественным запросом.

HTTP (Hypertext Transfer Protocol) это протокол, по которому HTML-страница пересылается клиенту. Этот протокол является stateless\бесстатусным, то есть информация не сохраняется в период между запросами. В общем, любая информация, необходимая для обработки HTTP-запроса, должна пересылаться вместе с этим запросом. Это создаёт проблемы для многих приложений. Как использовать информацию одновременно различными пользователями приложения или даже различными запросами одного пользователя? Служба JavaScript Session Management Service была разработана для того, чтобы помочь разрешить эту проблему. Детально эта служба рассматривается в Главе 6, "Session Management Service." В данный момент просто помните, что машина выполнения автоматически обслуживает объекты client, server, project и request.

Если Netscape-сервер получает клиентский запрос на страницу приложения, он сначала выполняет авторизацию (идентификацию). Этот шаг является частью базовых функций администрирования сервера. Если попытка авторизации запроса не удалась, последующие шаги не выполняются. Если запрос получил авторизацию сервера, машина выполнения JavaScript продолжает работу. Она выполняет следующие шаги, описанные в последующих разделах:

  1. Конструирует новый объект request и конструирует или восстанавливает объект client.
  2. Находит страницу для запроса и начинает создание HTML-страницы для отправки клиенту.
  3. Для каждого участка исходной HTML-страницы: добавляет его в буфер или исполняет код.
  4. Сохраняет свойства объекта client.
  5. Высылает HTML клиенту.
  6. Уничтожает объект request и сохраняет или уничтожает объект client.

Шаг 1. Создание объекта request и конструирование или восстановление объекта client


Инициализируются встроенные свойства объекта request, такие как IP-адрес и элементы формы, ассоциированные с данным request. Если URL запроса специфицирует другие свойства, они инициализируются для объекта request, как описано в разделе "Кодирование Информации в URL".

Если объект client уже существует, машина выполнения запрашивает его на основе специфицированной техники обслуживания клиента. (См. "Техника Обслуживания Объекта client"). Если объект client не существует, машина выполнения конструирует новый объект без свойств.

Вы не можете предвидеть, в каком порядке эти объекты конструируются.

Шаг 2. Поиск исходной страницы и начало конструирования HTML-страницы


Когда Вы компилировали исходный код JavaScript, исходник включал HTML-страницы с операторами серверного JavaScript. Главной задачей машины выполнения является конструирование из одной из этих исходных страниц HTML-страницы, содержащей только HTML и операторы клиентского JavaScript. При создании этой HTML-страницы машина выполнения сохраняет её части в области памяти, называемой буфером, пока не придёт время отправки буферизованного содержимого клиенту.

Шаг 3. Добавить в буфер вывода или выполнить код


Этот шаг выполняется для каждого участка кода исходной страницы. Детали процесса выполнения различных серверных операторов рассматриваются далее в этом учебнике. Дополнительно см. "Конструирование HTML-Страницы".

Для данного запроса/request машина выполнения выполняет этот шаг, пока не произойдёт одно из следующих событий:

Шаг 4. Сохранение свойств объекта client


Машина выполнения сохраняет свойства объекта client непосредственно перед первой отправкой части HTML-страницы клиенту. Она сохраняет эти свойства только один раз. Машина выполнения может повторять шаги 3 и 5, но не может повторить данный шаг.

Машина выполнения сохраняет свойства в этот момент, чтобы поддерживать один из видов техники обслуживания объекта client. Например, схема кодирования клиентского URL высылает свойства client'а в шапке/header HTML-файла. Поскольку шапка высылается как первая часть файла, свойства client'а обязаны быть затем высланы.

Следовательно, Вы должны учитывать, где в Вашем файле-источнике устанавливаются свойства client'а. Вы всегда должны изменять свойства client'а в файле до любого вызова redirect или flush и до генерирования 64KB HTML-вывода.

Если Вы изменяете значения свойств объекта client в коде после того как HTML был выслан клиенту, эти изменения будут действовать для оставшейся части клиентского запроса, но затем будут отменены. Отсюда: следующий клиентский запрос не получит эти значения свойств; он получит значения, действовавшие в тот момент, когда содержимое было в первый раз отправлено клиенту. Например, ваш код содержит такие операторы:


<HTML>
<P>The current customer is
<SERVER>
client.customerName = "Mr. Ed";
write(client.customerName);
client.customerName = "Mr. Bill";
</SERVER>

<P>The current customer really is 
<SERVER>
write(client.customerName);
</SERVER>
</HTML>

Эта серия операторов даст в результате такой HTML, отправляемый клиенту:


<P>The current customer is Mr. Ed
<P>The current customer really is Mr. Bill

Теперь, когда появится следующий клиентский запрос, значение свойства client.customerName будет "Mr. Bill". Этот очень похожий набор операторов даст в результате тот же HTML:


<HTML>
<P>The current customer is
<SERVER>
client.customerName = "Mr. Ed";
write(client.customerName);
flush();
client.customerName = "Mr. Bill";
</SERVER>
<P>The current customer really is
<SERVER>
write(client.customerName);
</SERVER>
</HTML>

Однако при появлении следующего клиентского запроса значение client.customerName будет "Mr. Ed"; а не "Mr. Bill".

Дополнительно см. "Техника Обслуживания Объекта client".

Шаг 5. Отправка HTML клиенту


Сервер отсылает содержимое страницы клиенту. Для страниц без операторов серверного JavaScript сервер просто передаёт HTML клиенту. Для других страниц - машина выполнения реализует логику приложения для конструирования HTML и затем высылает сгенерированную страницу клиенту.

Шаг 6. Уничтожение объекта request и сохранение или уничтожение объекта client


Машина выполнения разрушает объект request, сконструированный для данного клиентского запроса. Она сохраняет значения объекта client и разрушает физический объект JavaScript. Она не разрушает объекты project или server.

Конструирование HTML-Страницы


Когда Вы компилируете приложение JavaScript, исходники состоят из HTML-страниц, содержащих операторы серверного JavaScript, и, возможно, HTML-страницы, не содержащие операторов серверного JavaScript. Если пользователь получает доступ к странице, которая не содержит серверных операторов, сервер высылает страницу обратно, как и любую другую HTML-страницу. Если пользователь получает доступ к странице, которая содержит серверные операторы, машина выполнения на сервере конструирует HTML-страницу для отправки в ответе, используя одну из исходных страниц Вашего приложения.

Машина выполнения сканирует исходную страницу. При обнаружении операторов HTML клиентского JavaScript она присоединяет их к создаваемой странице. При обнаружении операторов серверного JavaScript она выполняет их. Хотя большинство операторов серверного JavaScript выполняются на сервере, некоторые влияют на конструируемую страницу. В следующих разделах рассматриваются три функции: write, flush и redirect, которые влияют на обрабатываемую HTML-страницу.

Генерирование HTML


Как уже было сказано ранее в этой главе, функция write генерирует HTML на основе значения выражения JavaScript, заданного в качестве аргумента. Например, рассмотрим оператор:


write("<P>Customer Name is:" + project.custname + ".");

В ответ на этот оператор JavaScript генерирует HTML, вставляя тэг параграфа и некоторый текст, соединённый со значением свойства custname объекта project. Например, если свойство будет иметь значение "Fred's software company", клиент получит следующий HTML:


<P>Customer Name is: Fred's software company.

Как кажется клиенту, это нормальный HTML. Однако он в действительности динамически сгенерирован машиной выполнения JavaScript.

Очистка Буфера Вывода


Для повышения производительности, JavaScript буферизует конструируемую им HTML-страницу. Функция flush сразу высылает данные из внутреннего буфера клиенту. Если Вы явно не вызываете функцию flush, JavaScript высылает данные клиенту после создания каждых 64KB содержимого конструируемой HTML-страницы.

Не путайте функцию flush с методом flush класса File. (Об использовании класса File для ввода и вывода в файл см. "Служба Файловой Системы").

Вы можете использовать flush для управления временем переноса данных клиенту. Например, Вы можете очищать буфер до операции, создающей задержку/delay, такой как запрос к базе данных. Также, если запрос к БД запрашивает большое количество рядов, очистка буфера каждый раз после получения нескольких рядов предотвращает паузы при отображении данных.

ПРИМЕЧАНИЕ: Если Вы используете клиентские куки для обслуживания свойств объекта client, Вы обязаны делать все изменения объекта client до очистки буфера. Дополнительно см. "Техника Обслуживания Объекта client".

Следующий фрагмент кода показывает, как используется flush. Предположим, Ваше приложение должно выполнить некоторые действия с каждым потребителем/customer в Вашей БД потребителей. Если потребителей много, процесс может затянуться. Поэтому, для того чтобы пользователь не ждал у застывшего экрана, Ваше приложение может высылать вывод клиенту до начала обработки и затем вновь - после конца обработки каждого ряда. Для этого Вы должны использовать примерно такой код:


flush();
conn.beginTransaction();
cursor = conn.cursor ("SELECT * FROM CUSTOMER", true);
while ( cursor.next() ) {
   // ... обработка ряда ...
   flush();
}
conn.commitTransaction();
cursor.close();

Переход к Новому Клиентскому Запросу


Функция redirect прерывает текущий клиентский запрос и стартует новый по специфицированному URL. Например, у вас имеется оператор:


redirect("http://www.royalairways.com/apps/page2.html");

Когда машина выполняет это оператор, она прерывает текущий запрос. Машина выполнения не продолжает обработку страницы-оригинала. Следовательно любые операторы HTML или JavaScript, идущие в оригинальной странице после вызова redirect, будут утеряны. Клиент сразу загрузит указанную страницу, отбросив предыдущее содержимое.

Параметром для redirect может быть любой оператор серверного JavaScript, вычисляемый до URL. Таким образом, Вы можете динамически генерировать URL, используемый в redirect. Например, если страница определяет переменную choice, Вы можете перенаправить клиента на страницу в зависимости от значения choice таким образом:


redirect ("http://www.royalairways.com/apps/page" 
   + choice + ".html");

Если Вам нужно удостовериться, что текущие свойства client'а доступны в новом запросе и что Вы используете один из видов техники обслуживания объекта client на основе URL, Вы должны кодировать свойства в URL, передаваемом Вами в redirect. О том, как это сделать, см. "Присоединение Свойств client'а к URL Вручную".

В целом свойства объекта request и переменные верхнего уровня JavaScript существуют только в течение одиночного клиентского запроса. Если Вы выполняете перенаправление на новую страницу, Вам может понадобиться сохранить некоторую информацию для нескольких запросов. Вы можете сделать это, присоединив имена и значения свойств к URL, как описано в разделе "Кодирование Информации в URL".

Доступ к Переменным CGI


Как и большинство других web-серверов, серверы Netscape устанавливают значения для определённого набора переменных окружения, называемых CGI-переменными, при установке контекста для запуска CGI-скрипта. Предполагается, что создатели CGI-скриптов могут использовать эти переменные в своих скриптах.

По контрасту, Netscape web-серверы не устанавливают отдельного окружения для приложений серверного JavaScript. Тем не менее, некоторая часть информации, обычно устанавливаемой в CGI-переменных, может использоваться в приложениях JavaScript. Машина выполнения предоставляет несколько механизмов для доступа к этой информации:

В следующей таблице перечислены свойства объекта request, соответствующие CGI-переменным. Дополнительно об этих свойствах и об объекте request в целом см. "Объект request".

Таблица 5.7  CGI-переменные, доступные как свойства объекта request
CGI-переменная Свойство Описание

AUTH_TYPE

auth_type

Тип авторизации, если запрос защищён авторизацией любого типа. Netscape web-серверы поддерживают базовую авторизацию доступа HTTP.
Пример значения: basic


REMOTE_USER

auth_user

Имя локального HTTP-пользователь web-браузера, если авторизации доступа HTTP была активирована для данного URL. Заметьте, что это не способ определения имени пользователя, получившего доступ к Вашей программе. Пример значения: ksmith


REQUEST_METHOD

method

HTTP-метод, ассоциированный с запросом. Приложение может использовать его для определения соответствующего ответа на запрос.
Пример значения: GET


SERVER_PROTOCOL

protocol

Уровень протокола HTTP, поддерживаемый клиентским программным обеспечением. Пример значения: HTTP/1.0


QUERY_STRING

query

Информация запрашивающей HTML-страницы; если имеется "?", информация в URL, идущая после знака "?". Пример значения: x=42

Серверная функция ssjs_getCGIVariable даёт Вам доступ к переменным окружения, установленным в серверном процессе, включая CGI-переменные, перечисленные в следующей таблице.

Таблица 5.8  CGI-переменные, доступные через ssjs_getCGIVariable
Переменная Описание

AUTH_TYPE

Тип авторизации, если запрос защищён авторизацией любого типа. Netscape web-серверы поддерживают базовую авторизацию доступа HTTP.
Пример значения: basic


HTTPS

Если на сервере активна служба безопасности/security, значение этой переменной ON; иначе - OFF. Пример значения: ON


HTTPS_KEYSIZE

Количество битов в ключе сессии, используемом для шифрования сессии, если безопасность on. Пример значения: 128


HTTPS_SECRETKEYSIZE

Количество битов, используемых для генерации private-ключа сервера.
Пример значения: 128


PATH_INFO

Информация пути, установленная браузером. Пример: /cgivars/cgivars.html


PATH_TRANSLATED

Фактическое системное pathname/имя пути , содержащегося в PATH_INFO. Пример: /usr/ns-home/myhttpd/js/samples/cgivars/cgivars.html


QUERY_STRING

Информация запрашивающей HTML-страницы; если имеется "?", информация в URL, идущая после знака "?". Пример значения: x=42


REMOTE_ADDR

IP-адрес хоста, отправившего запрос. Пример: 198.93.95.47


REMOTE_HOST

Если DNS на сервере включена, имя хоста, отправившего запрос; иначе - его IP-адрес. Пример: www.netscape.com


REMOTE_USER

Имя локального HTTP-пользователя web-браузера, если авторизация доступа HTTP была активирована данным URL. Заметьте, что это не способ определения user name того, кто выполнил доступ к Вашей программе. Пример: ksmith


REQUEST_METHOD

HTTP-метод, ассоциированный с запросом. Приложение может использовать его для определения ответа на запрос. Пример: GET


SCRIPT_NAME

pathname к данной странице, как он введён в URL. Пример: cgivars.html


SERVER_NAME

hostname или IP-адрес, по которому приложение JavaScript запущено, как они даны в URL. Пример: piccolo.mcom.com


SERVER_PORT

TCP-порт, по которому запущен сервер. Пример: 2020


SERVER_PROTOCOL

Уровень протокола HTTP, поддерживаемый клиентским программным обеспечением. Пример: HTTP/1.0


SERVER_URL

URL, введённый пользователем для доступа к данному серверу. Пример: https://piccolo:2020

Здесь приведён синтаксис ssjs_getCGIVariable:


value = ssjs_getCGIVariable("name");

Этот оператор устанавливает в переменную value значение CGI-переменной name. Если предоставленный вами аргумент не является одной из CGI-переменных, перечисленных в Таблице 5.8, машина выполнения ищет переменную окружения с этим именем в среде сервера. Если она найдена, машина выполнения возвращает значение; иначе, возвращает null. Например, следующий код присваивает значение стандартной переменной окружения CLASSPATH переменной JavaScript classpath:


classpath = ssjs_getCGIVariable("CLASSPATH");

Метод httpHeader объекта request возвращает шапку/header текущего клиентского запроса. Для CGI-скрипта Netscape web-серверы устанавливают CGI-переменные для некоторой информации в шапке. Для приложений JavaScript Вы получаете эту информацию непосредственно из шапки. Таблица 5.9 показывает информацию, доступную как переменные CGI в среде CGI, но как свойства шапки - в серверном JavaScript. В свойствах шапки символы подчёркивания в имени CGI-переменной (_) заменяются на тире (-); например, CGI-переменная CONTENT_LENGTH соответствует свойству шапки content-length.

Таблица 5.9 CGI-переменные, доступные через клиентские "шапки"
CGI-переменная Описание

CONTENT_LENGTH

Количество байтов, отправленных клиентом.


CONTENT_TYPE

Тип данных, отправленных клиентом, если форма отправлена методом POST.


HTTP_ACCEPT

Перечисляет типы данных, которые может принимать клиент.


HTTP_USER_AGENT

Идентифицирует браузер, используемый для доступа к Вашей программе.


HTTP_IF_MODIFIED_SINCE

Дата, установленная в соответствии со стандартным временем GMT (по Гринвичу), дающая возможность отправлять клиенту ответ на запрос только тогда, когда дата была изменена после данной даты.

Дополнительно о манипулировании клиентской "шапкой" см. "Манипуляции с Запросом и Ответом".

В таблице даны CGI-переменные, не поддерживаемые серверным JavaScript, которые не могут быть применены при запуске приложений JavaScript.

Таблица 5.10  CGI-переменные, не поддерживаемые серверным JavaScript
Переменная Описание

GATEWAY_INTERFACE

Версия CGI, запущенная на сервере. Не применяется к приложениям JavaScript.


SERVER_SOFTWARE

Тип запущенного сервера. Недоступна для приложений JavaScript.

Сообщение Между Сервером и Клиентом


Нередко Вашим приложениям JavaScript нужно передать информацию либо с сервера клиенту, либо с клиента на сервер. Например, когда пользователь в первый раз выполняет доступ к приложению videoapp, оно динамически генерирует список категорий видео-файлов из текущего содержимого БД. Эта информация, генерируемая на сервере, должна быть передана обратно клиенту. И наоборот, когда пользователь щёлкает на категории из этого списка, выбор пользователя должен быть передан обратно на сервер, чтобы он мог сгенерировать набор файлов.

Отправка Значений с Клиента на Сервер


Есть несколько способов отправки информации с клиента на сервер:

Доступ к Значениям Формы


Формы это альфа и омега приложений на JavaScript. Вы используете такие элементы формы как текстовые поля и радио-кнопки в качестве первичного механизма переноса данных с клиента на сервер. Когда пользователь щёлкает на кнопке Submit, браузер отправляет значения, введённые форму, на сервер для обработки.

Атрибут ACTION тэга FORM определяет приложение, которому отправляются значения. Для того чтобы отправить информацию приложению на сервер, используйте URL приложения как значение атрибута ACTION.

Если документ, содержащий форму, является скомпилированной частью того же самого приложения, Вы можете просто предоставить имя страницы вместо полного URL. Например, вот тэг FORM из приложения-примера Hangman:


<FORM METHOD="post" ACTION="hangman.html">

Формы, отправляемые приложениям на серверном JavaScript, могут использовать get или post в качестве значения атрибута METHOD.

ПРИМЕЧАНИЕ: Приложения на серверном JavaScript не поддерживают автоматическую выгрузку файлов. То есть, если специфицированная action это страница в приложении JavaScript, Вы отправляете элемент INPUT с типом TYPE="file", Ваше приложение обязано само обработать этот файл, как описано в разделе "Манипуляции с Запросом и Ответом".

Каждый элемент ввода HTML-формы соответствует свойству объекта request. Имя свойства специфицируется атрибутом NAME элемента формы. Например, следующий HTML создаёт свойство объекта request под названием guess, которое принимает одиночный символ в текстовом поле. Вы обращаетесь к этому свойству в серверном JavaScript как к request.guess.


<FORM METHOD="post" ACTION="hangman.html"> 
<P>
What is your guess?
<INPUT TYPE="text" NAME="guess" SIZE="1">

Элемент SELECT, дающий возможность множественного выбора, требует особого обращения, поскольку это единственное свойство, которое может иметь несколько значений. Вы можете использовать функцию getOptionValue для получения значений выбранных опций в списке множественного выбора. Дополнительно см. "Использование Списков Select".

Информацию об объекте request см. в разделе "Объект request".

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

Например, у Вас имеется функция клиентского JavaScript под названием calc, выполняющая расчёт на основе пользовательского ввода. Вы хотите передать результат работы этой функции Вашему приложению для дальнейшей обработки. Сначала Вам нужно определить скрытый элемент формы для результата:


<INPUT TYPE="hidden" NAME="result" SIZE=5>

Затем Вам нужно создать обработчик события onClick для кнопки Submit, который назначает вывод функции в скрытый элемент:


<INPUT TYPE="submit" VALUE="Submit"
   onClick="this.form.result.value=calc(this.form)">

Значение элемента result отправляется вместе с другими значениями элементов формы. Обратиться к этому значению в приложении можно request.result.

Использование Списков Select


HTML-тэг SELECT, используемый с атрибутом MULTIPLE, даёт возможность ассоциировать несколько значений с одним элементом формы. Если Вашему приложению нужны списки с возможностью выбора нескольких опций, Вы используете функцию getOptionValue для получения значений в JavaScript. Синтаксис getOptionValue таков:


itemValue = getOptionValue(name, index)

Здесь name это строка, специфицированная как атрибут NAME тэга SELECT, а index это порядковый индекс выбранной опции, начиная с 0. Функция getOptionValue возвращает значение выбранного элемента, как специфицировано ассоциированным тэгом OPTION.

Функция getOptionValueCount возвращает количество опций (специфицированных тэгами OPTION) в списке выбора. Она требует только одного аргумента, строки, содержащей имя тэга SELECT.

Например, у Вас имеется следующий элемент:


<SELECT NAME="what-to-wear" MULTIPLE SIZE=8>
   <OPTION SELECTED>Jeans
   <OPTION>Wool Sweater
   <OPTION SELECTED>Sweatshirt
   <OPTION SELECTED>Socks
   <OPTION>Leather Jacket
   <OPTION>Boots
   <OPTION>Running Shoes
   <OPTION>Cape
</SELECT>

Вы можете обработать ввод из этого select-списка таким образом:


<SERVER>
var i = 0;
var howmany = getOptionValueCount("what-to-wear");
while ( i < howmany ) {
   var optionValue =
      getOptionValue("what-to-wear", i);
   write ("<br>Item #" + i + ": " + optionValue + "\n");
   i++;
}
</SERVER>

Если пользователь оставил выбор по умолчанию, скрипт возвратит:

Item #0: Jeans
Item #1: Sweatshirt
Item #2: Socks

Кодирование Информации в URL


Вы можете вручную кодировать свойства объекта request в URL, по которому выполняется доступ к странице Вашего приложения. При создании URL используется следующий синтаксис:


URL?varName1=value1[&varName2=value2...]

Здесь URL это базовый URL, каждое varName N   это имя свойства, каждое value N   это соответствующее свойству значение (с мнемониками специальных символов). В этой схеме после базового URL идёт знак вопроса (?), после которого, в свою очередь, идут пары имён свойств и их значений. Каждая пара отделяется амперсандом (&). Когда машина выполнения на сервере получает результирующий URL в качестве клиентского запроса, она создаёт свойство объекта request под названием varName N   для каждой переменной.

Например, следующий HTML определяет гиперссылку на страницу, инстанциирующую свойства объекта request i и j в 1 и 2, соответственно. Операторы JavaScript в refpage.html могут затем обратиться к эти переменным request.i и request.j.


<A HREF="refpage.html?i=1&j=2">Click Here</A>

Вместо использования статической URL-строки, как в предыдущем примере, Вы можете использовать операторы серверного или клиентского JavaScript для динамической генерации URL, кодирующего значения свойств. Например, Ваше приложение может включать страницу:


<HTML>
<HEAD>
<SCRIPT>
function compute () {
   // ... заменить подходящими расчётами,    // которые возвращают строку поиска ...
   return "?num=25";
}
</SCRIPT>
</HEAD>

<BODY>
<a HREF="refpage.html" onClick="this.search=compute()">
Click here to submit a value.</a></p>

</BODY>
</HTML>

В данном случае, если пользователь щёлкнет на ссылке, машина выполнения на клиенте запустит на выполнение обработчик события onClick. Этот обработчик устанавливает часть поиска из URL в ссылке в какую-нибудь строку, возвращённую функцией compute. Когда машина выполнения на сервере получит этот запрос, она создаст свойство num объекта request и установит его значение в 25.

В качестве второго примера Вы можете добавить свойства объекта request в URL, созданный в серверном скрипте. Это особенно применимо, если Вы перенаправляете клиентский запрос на новую страницу. Чтобы добавить свойства объекта request в серверный скрипт, Вы можете использовать такой оператор:


<A HREF=`"refpage.html?i=" + escape(i) + "&j=" + escape(j)`>
   Click Here</A>

Если вы создаёте URL в операторе серверного JavaScript, свойства объекта client не добавляются автоматически. Если Вы используете технику на основе URL для объекта client, используйте функцию addClient для генерирования окончательного URL. В этом примере оператор может быть таким:


<A HREF=`addClient("refpage.html?i=" + escape(i)
   + "&j=" + escape(j))`>Click Here</A>

Об использовании addClient см. "Присоединение Свойств Объекта client к URL Вручную".

Функция escape ядра JavaScript даёт возможность кодировать имена или значения, присоединённые к URL, включая специальные символы. Вообще, если приложению необходимо генерировать имена и значения собственных свойств в URL запроса, Вы должны использовать escape, чтобы гарантировать корректную интерпретацию всех значений. Дополнительно см. книгу Серверный JavaScript. Справочник .

Помните, что URL не изменяется, если пользователь перезагружает его, хотя содержимое страницы может измениться. Любые свойства, высланные в оригинальном URL, восстанавливают свои значения в URL, имевшиеся на момент его первой отправки, независимо от любых возможных изменений, сделанных при обработке. Например, если пользователь щёлкнул кнопку Reload для перезагрузки URL в предыдущем примере, i и j снова установятся в 1 и 2, соответственно.

Отправка Значений с Сервера Клиенту


Приложение JavaScript сообщается с клиентом через HTML и клиентский JavaScript. Если Вам нужно просто вывести информацию пользователю, нет никаких проблем: Вы создаёте HTML для форматирования этой информации так, как она будет отображаться.

Однако Вам может понадобиться выслать значения непосредственно клиентскому скрипту. Можно сделать это по-разному, включая такие способы:

Значения по Умолчанию Формы и Скрытых Элементов Формы


Чтобы отобразить HTML-форму с набором значений по умолчанию в элементах формы, используйте тэг INPUT для создания необходимых элементов формы, замещая выражения серверного JavaScript атрибутов VALUE. Например, Вы можете использовать следующий оператор для отображения элемента text и установки значения по умолчанию на основе значения переменной client.custname:


<INPUT TYPE="text" NAME="customerName" SIZE="30"
   VALUE=`client.custname`>

Начальным значением этого текстового поля становится значение переменной client.custname. Так, если значением client.custname является Victoria, клиенту будет выслан такой оператор:


<INPUT TYPE="text" NAME="customerName" SIZE="30" VALUE="Victoria">

Вы может использовать аналогичную технику со скрытыми элементами формы, если не хотите показывать значения пользователю, как в следующем примере:


<INPUT TYPE="hidden" NAME="custID" SIZE=5 VALUE=`client.custID`>

В обоих случаях Вы можете использовать эти значения клиентского JavaScript в значениях свойств объектов, доступных клиенту. Если эти два элемента находятся в форме с именем entryForm, то значения станут свойствами JavaScript document.entryForm.customerName и document.entryForm.custID, соответственно. Вы можете затем выполнять обработку этих значений на стороне клиента. См. также книгу Клиентский JavaScript. Руководство .

Прямая Замена


Вы можете также использовать серверный JavaScript для генерирования клиентских скриптов. Эти значения могут использоваться в последовательности операторов на клиенте. В качестве простого примера Вы можете инициализировать клиентскую переменную по имени budget на основе значения client.amount таким образом:


<p>The budget is:
<SCRIPT>
<SERVER>
write("var budget = " + client.amount);
</SERVER>
document.write(budget);
</SCRIPT>

Если значение client.amount равно 50, это сгенерирует такой JavaScript:


<p>The budget is:
<SCRIPT>
var budget = 50
document.write(budget);
</SCRIPT>

При запуске на клиенте это будет выглядеть так:


The budget is: 50

Использование Кук


Куки это механизм, который Вы можете использовать на клиенте для сохранения информации между запросами. эта информация находится в файле с названием cookie.txt (куки-файл), хранящемся на клиентской машине. Протокол Netscape cookie детально описан в книге Клиентский JavaScript. Руководство .

Вы можете использовать куки для отправки информации в обоих направлениях, от клиента серверу и с сервера клиенту. Куки, высылаемые с клиента, становятся свойствами объекта client или объекта request. Хотя Вы можете выслать с сервера клиенту любое строковое значение в качестве куки, простейший метод будет - отправить свойства объекта client.

Свойства Объекта client как Куки


Если приложение использует технику клиентских кук для работы с объектом client, машина выполнения на сервере сохраняет имена и значения свойств объекта client как куки на клиенте. Об использовании кук для работы с объектом client см. раздел "Техника Работы с Объектом client".

Для свойства объекта client propName   машина выполнения автоматически создаёт куку с именем NETSCAPE_LIVEWIRE. propName , принимая, что приложение использует технику работы с клиентскими куками. Машина выполнения кодирует значения свойств так, как это требуется по протоколу кук Netscape cookie protocol.

Для доступа к этим кукам в клиентском JavaScript Вы можете извлечь эту информацию путём использования свойства document.cookie и такой функции как getSSCookie, как показано здесь:


function getSSCookie(name) {
   var search = "NETSCAPE_LIVEWIRE." + name + "=";
   var retstr = "";
   var offset = 0;
   var end = 0;
   if (document.cookie.length > 0) {
      offset = document.cookie.indexOf(search);
      if (offset != -1) {
         offset += search.length;
         end = document.cookie.indexOf(";", offset);
         if (end == -1)
            end = document.cookie.length;
         retstr = unescape(document.cookie.substring(offset, end));
      }
   }
   return(retstr)
}

Функция getSSCookie не является предопределённой функцией JavaScript. Если Вам нужна похожая функциональность, Вы обязаны определить её (функцию) в Вашем приложении.

Чтобы отправленная на сервер информация стала свойством объекта client, добавьте куку с именем, имеющим форму NETSCAPE_LIVEWIRE. propName. Предположим, Ваше приложение использует технику работы с клиентскими куками, а машина выполнения на сервере создаёт свойство объекта client под названием propName   для данной куки.

Тогда Вы можете использовать функцию типа следующей:


function setSSCookie (name, value, expire) {
   document.cookie =
      "NETSCAPE_LIVEWIRE." + name + "="
      + escape(value)
      + ((expire == null) ? "" : ("; expires=" + expire.toGMTString()));
}

Здесь функция setSSCookie также не является предопределённой функцией JavaScript. Если Вам необходима аналогичная функциональность, Вы обязаны определить функцию в Вашем приложении.

Вы можете вызывать эти функции в клиентском JavaScript для получения набора значений свойств объекта client, как в следующем примере:


var value = getSSCookie ("answer"); 
if (value == "") {
   var expires = new Date();
   expires.setDate(expires.getDate() + 7);
   setSSCookie ("answer", "42", Expires);
}
else
   document.write ("The answer is ", value);

Эта группа операторов проверяет, имеется ли свойство объекта client с названием answer. Если нет, код создаёт его и устанавливает значение 42; если найдено, выводится его значение.

Другие Куки


Когда серверу высылается запрос на страницу приложения JavaScript, шапка/header запроса включает все куки, установленные в данный момент для приложения. Можно использовать метод request.httpHeader для доступа к этим кукам из серверного JavaScript и присвоения их значений серверным переменным. И наоборот, Вы можете использовать функцию addResponseHeader для добавления новых кук в ответ, высылаемый обратно клиенту. Эта функциональность  описана в разделе "Манипуляция с Запросом и Ответом".

На клиентской стороне Вы можете использовать функцию вроде приведённой здесь для доступа к куке:


function GetCookie (name) {
   var arg = name + "=";
   var alen = arg.length;
   var clen = document.cookie.length;
   var i = 0;
   while (i < clen) {
      var j = i + alen;
      if (document.cookie.substring(i, j) == arg) {
         var end = document.cookie.indexOf (";", j);
         if (end == -1)
            end = document.cookie.length;
         return unescape(document.cookie.substring(j, end));
      }
      i = document.cookie.indexOf(" ", i) + 1;
      if (i == 0) break;
   }
   return null;
}

И Вы может использовать функцию типа приведённой ниже для установки куки на клиенте:


function setCookie (name, value, expires, path, domain, secure) {
   document.cookie =
      name + "="
      + escape(value)
      + ((expires) ? "; expires=" + expires.toGMTString() : "")
      + ((path) ? "; path=" + path : "")
      + ((domain) ? "; domain=" + domain : "")
      + ((secure) ? "; secure" : "");
}

Если путь, специфицированный Вами для куки, находится в Вашем приложении JavaScript, то эта кука будет отправлена в ответ на любой запрос к приложению.

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

Сбор Мусора


Серверный JavaScript имеет сборщика мусора, который автоматически освобождает память, выделенную для объекта, более не используемого. В большинстве случаев нет необходимости понимать досконально работу сборщика мусора. Этот раздел даёт обзор  сборщика мусора и информацию о том, когда он вызывается.

Важно!

Этот раздел даёт возможность продвинутым пользователям взглянуть на внутренние процессы JavaScript. Netscape не гарантирует, что эти алгоритмы останутся такими же в последующих релизах.

Пространство объекта в JavaScript состоит из арен. То есть машина выполнения JavaScript размещает набор арен, из которого затем размещает объекты. Если машина выполнения получает запрос на новый объект, она сначала просматривает список свободных арен. Если в списке свободных есть место, машина выделяет его. Иначе машина выполнения выделяет место в текущей используемой арене. Если используются все арены, машина размещает новую арену. Если все объекты арены - мусор, сборщик мусора освобождает арену.

Строка JavaScript обычно размещается как GC-объект. Строка имеет ссылку на байты строки, которая также размещается в куче/heap процесса. Если строковой объект подвергся сборке мусора, байты строки высвобождаются.

Работа сборщика мусора JavaScript основана на пометке и уничтожении. Сборщик не перемещает объекты. Он всегда обрабатывает корневой набор объектов. Этот корневой набор/root set включает в себя стэк JavaScript, объект global для контекста JavaScript и любые объекты JavaScript, которые были явно добавлены в корневой набор. В фазе разметки сборщик мусора помечает все объекты, достижимые из корневого набора. В конечной фазе все непомеченные объекты уничтожаются. Все убранные объекты собираются в список свободных.

Сборка мусора считается необходимой, если количество текущих используемых байтов в 1.5 раза превышает количество байтов, бывших в использовании в конце последней уборки мусора. Машина выполнения проверяет это условие в следующих точках и начинает уборку, если это необходимо:

Обработка Ошибок в Серверном JavaScript


Функция  ssjs_onError, если она определена в Вашем приложении, вызывается в случае ошибки серверного JavaScript, такой как "undefined variable name/имя переменной не определено". В функции ssjs_onError Вы можете делать всё, что можно делать в функции серверного JavaScript, включая доступ к объектам server, project, client и request. Вы можете также выполнять перенаправление и вызывать другие функции.

Функция ssjs_onError имеет следующий синтаксис:


function ssjs_onError (<message>,<file>,<line number>) 

<message> текст сообщения об ошибке

<file> имя исходного файла

<line number> номер строки с ошибкой

Ошибка JavaScript в ходе выполнения функции onError записывается в log-файл и трассируется (если активна). Функция ssjs_onError, однако, не вызывается рекурсивно. Ошибка в функции onError вызывает запись сообщения в error log, но не выполняет вызов onError.

Вот пример функции:


function ssjs_onError(msg,file,line) 

{ 

write("<br>\n<hr>") 

write("error message: "+msg+"<br>\n") 

write("file name: "+file+"<br>\n") 

write("line number: "+line+"<br>\n") 


write("<hr>") 

}

ПРИМЕЧАНИЕ:

Чтобы дать каждой странице её собственную специальную функцию onError, добавьте присвоение ssjs_onError в начале кода страницы. Например:


ssjs_onError = custom_onError; 


function custom_onError(msg,file,line) 

{ 

// ... 

} 

Серверный JavaScript выполняет всё, что ssjs_onError представляет во время ошибки. Вы можете использовать одну функцию ssjs_onError, которая совместно используется всеми страницами, либо можете динамически переключаться на другую функцию onError в любое время, в том числе в начале каждой страницы. Если два запроса выполняют одну и ту же функцию onError в один момент времени, они имеют различные среды выполнения, как если бы Вы одновременно выполняли какую-нибудь другую функцию.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 14
LiveConnect. Обзор.

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

В главе имеются следующие разделы:

Дополнительно об использовании LiveConnect см. JavaScript technical notes на сайте DevEdge, а также ищите соответствующую информацию на сайтах mozilla.org и developer.netscape.com.

Что Такое LiveConnect?


LiveConnect даёт возможность подключать приложения серверного JavaScript к Java-компонентам и классам на сервере.

Вашему приложению JavaScript может понадобиться соединиться с кодом, написанным на других языках, таких как Java или C. Для подключения к Java-коду Вы используете функциональность LiveConnect. Для взаимодействия с кодом, написанным на других языках, у Вас есть несколько вариантов:

В этой главе обсуждается использование LiveConnect для доступа к не-JavaScript коду из приложений JavaScript.

Наконец, LiveConnect даёт возможность объектам JavaScript Вашего приложения взаимодействовать с Java-объектами. Эти Java-объекты являются экземплярами классов в серверном CLASSPATH. Об установке CLASSPATH см. книгу Programmer's Guide to Servlets . LiveConnect работает и с клиентским, и серверным JavaScript, но имеет для каждой среды разные возможности.

Предполагается, что Вы уже знакомы с программированием на Java. Об использовании Java с Netscape-серверами см. Enterprise Server 3.5.1/3.6: Notes for Java Programmers 1 . О LiveConnect см. DevEdge Library 2 .

Во всех доступных Java-классах Вы можете иметь доступ к статичным public-свойствам или методам или создавать экземпляры класса и получать доступ к public-свойствам и методам этих экземпляров. В отличие от клиентского, однако, Вы можете иметь доступ только к тем Java-объектам, которые были созданы Вашим приложением или другим приложением JavaScript, а затем сохранены как свойство объекта server.

Если Java-объект был создан серверным приложением, отличным от приложения на серверном JavaScript, Вы не можете иметь доступ к этому Java-объекту.
Например, Вы не можете получить доступ к Java-объекту, созданному WAI plug-in, расширением NSAPI или HTTP-аплетом.

Когда Вы вызываете метод Java-объекта, Вы можете передать объекты JavaScript в этот метод. Код Java может установить свойства и вызвать методы этих объектов JavaScript. Таким образом, Вы можете иметь и код JavaScript, вызывающий код Java, и код Java, вызывающий код JavaScript.

Код Java может иметь доступ к приложению JavaScript только таким способом. То есть Java-объект не может вызывать приложение JavaScript, если это приложение JavaScript (или другое приложение JavaScript) не имеет само доступа к соответствующему Java-объекту и не вызывает один из его методов.

Работа с Оболочками


В JavaScript wrapper\оболочка это объект типа данных целевого языка, который содержит в себе объект исходного языка. На стороне JavaScript Вы можете использовать объект-оболочку для доступа к методам и полям Java-объекта; вызывая метод или получая доступ к свойству в оболочке даёт в результате вызов Java-объекта. На стороне Java объекты JavaScript оборачиваются в экземпляры класса netscape.javascript.JSObject и передаются в Java.

Когда JavaScript-объект высылается в Java, машина выполнения создаёт Java-оболочку типа JSObject; когда JSObject высылается из Java в JavaScript, машина выполнения разворачивает его в объект оригинального типа JavaScript. Класс JSObject предоставляет интерфейс для вызова методов JavaScript и проверки свойств JavaScript.

Взаимодействие JavaScript с Java


Когда Вы обращаетесь к пакету или классу Java или работаете с объектом или массивом Java, Вы используете один из специальных объектов LiveConnect. Доступ JavaScript к Java имеет место в объектах, резюме по которым дано в следующей таблице.

Таблица 14.1  Объекты LiveConnect
Объект Описание

JavaArray

Обёрнутый/wrapped массив Java, доступ к которому выполняется в коде JavaScript.

JavaClass

Ссылка JavaScript на Java-класс.

JavaObject

Обёрнутый объект Java, доступ к которому выполняется в коде JavaScript.

JavaPackage

Ссылка JavaScript на Java-пакет.

ПРИМЕЧАНИЕ:

Поскольку Java является строго типизированным, а JavaScript -слабо типизированным языком, машина выполнения JavaScript конвертирует значения аргументов в соответствующие типы данных тех языков, которые Вы используете с LiveConnect. См. "Конвертация Типов Данных".

Иногда существование объекта LiveConnect прозрачно, поскольку Вы работаете с Java интуитивно. Например, Вы можете создать в Java String -объект и присвоить его переменной JavaScript myString с помощью оператора new в конструкторе Java таким образом:


var myString = new java.lang.String("Hello world")

В предыдущем примере переменная myString это JavaObject, потому что она содержит экземпляр Java String-объекта. Как JavaObject, myString имеет доступ к методам public-экземпляра java.lang.String и его суперкласса java.lang.Object. Эти методы Java доступны в JavaScript как методы JavaObject, и Вы можете вызывать их так:


myString.length() // возвращает 11

Вы имеете доступ к конструкторам, полям и методам класса через тот же синтаксис, который используете в Java. Например, следующий код JavaScript использует свойства объекта request для создания нового экземпляра класса Bug и присвоения затем этого нового экземпляра переменной JavaScript bug. Поскольку Java-класс требует целочисленного значения для первого поля, этот код конвертирует строковое свойство объекта request к целому числу, перед тем как передать его конструктору.


var bug = new Packages.bugbase.Bug(
   parseInt(request.bugId),
   request.bugPriority,
   request);

Объект Packages


Если класс Java не является частью пакетов java, sun или netscape, Вы имеете к нему доступ через объект Packages. Например, корпорация Redwood использует пакет Java под названием redwood как контейнер различных Java-классов, которые ею реализованы. Для создания экземпляра класса HelloWorld в redwood Вы вводите конструктор класса:


var red = new Packages.redwood.HelloWorld()

Вы можете также получить доступ к классам в пакете по умолчанию (то есть классам, которые не указывают пакет явно). Например, если класс HelloWorld находится непосредственно в CLASSPATH, а не в пакете, Вы можете получить к нему доступ так:


var red = new Packages.HelloWorld()

Объекты LiveConnect java, sun и netscape являются сокращениями для обычно используемых пакетов Java. Например, можно записать так:


var myString = new java.lang.String("Hello world")

вместо более длинной версии:


var myString = new Packages.java.lang.String("Hello world")

По умолчанию директория $NSHOME\js\samples, где $NSHOME это директория, в которой установлен сервер, находится в CLASSPATH сервера. Вы можете поместить Ваш пакет в эту директорию. Альтернативно Вы можете поместить Ваши пакеты и классы Java в другую директорию. Если Вы это делаете, убедитесь, что директория находится в Вашем CLASSPATH.

Работа с Массивами Java


Если какой-нибудь метод Java создаёт массив и Вы обращаетесь к этому массиву в JavaScript, Вы работаете с JavaArray. Например, следующий код создаёт JavaArray x из 10 элементов типа int:


theInt = java.lang.Class.forName("java.lang.Integer")
x = java.lang.reflect.Array.newInstance(theInt, 10)

Подобно объекту JavaScript Array, JavaArray имеет свойство length, возвращающее количество элементов массива. В отличие от Array.length, JavaArray.length является свойством только для чтения/read-only, поскольку количество элементов в Java-массиве фиксируется в момент создания.

Ссылки на Пакеты и Классы


Простые ссылки на пакеты и классы Java из JavaScript создают объекты JavaPackage и JavaClass. В одном из предыдущих примеров о корпорации Redwood, например, обращение Packages.redwood это JavaPackage -объект. Аналогично обращение java.lang.String это JavaClass -объект.

В большинстве случаев Вам не нужно беспокоиться об объектах JavaPackage и JavaClass: Вы просто работаете с пакетами и классами Java, а LiveConnect прозрачно создаёт эти объекты.

JavaClass -объекты не конвертируются автоматически в экземпляры java.lang.Class при передаче их в качестве параметров Java-методам -- Вы обязаны создать оболочку/wrapper вокруг экземпляра java.lang.Class. В следующем примере метод forName создаёт объект-оболочку theClass, который затем передаётся методу newInstance для создания нового массива.


theClass = java.lang.Class.forName("java.lang.String")
theArray = java.lang.reflect.Array.newInstance(theClass, 5)

Аргументы Типа char


Вы не можете передать односимвольную строку Java-методу, требующему аргумента типа char. Вы обязаны передать таким методам целое число, соответствующее значению Unicode для данного символа. Например, следующий код присваивает значение "H" переменной c:


c = new java.lang.Character(72)

Пример JavaScript-Вызова Java


Директория $NSHOME\js\samples\bugbase содержит простое приложение, иллюстрирующее использование LiveConnect. В этом разделе описан код JavaScript этого приложения-образца. См. в разделе "Пример Вызывающего JavaScript" описание кода Java этого приложения.

Приложение bugbase представляет собой простую БД "жучков". Вы вводите bug, заполняя клиентскую форму номером жучка, приоритетом, продуктом, в котором он обнаружен, и кратким описанием. Другая форма позволяет просмотреть существующий bug.

Следующий JavaScript обрабатывает акцию входа:


// Шаг 1. проверить, что ID был введён.
if (request.bugId != "") {
   // Шаг 2. Создаётся Bug-экземпляр и присваивается переменной.
   var bug = new Packages.bugbase.Bug(parseInt(request.bugId),
      request.bugPriority, request);


   // Шаг 3. Получить доступ к массиву и сохранить экземпляр в нём.
   project.bugsLock.lock();
   project.bugs[parseInt(request.bugId)] = bug;
   project.bugsLock.unlock();


   // Шаг 4. Отобразить информацию.
   write("<P><b><I>====>Committed bug: </I></b>");
   write(bug, "<BR>");
}
// Шаг 5. Если ID не был введён, предупредить пользователя.
else {
   write("<P><b><I>====>Couldn't commit bug: please complete
      all fields.</I></b>");
}

Шаги в этом коде:

  1. Проверить, что пользователь ввёл ID для bug. Только в этом случае выполняется вход в bug.
  2. Создать экземпляр Java-класса Bug и присвоить его переменной bug. Конструктор класса Bug принимает три параметра: два из них являются свойствами объекта request; третий это сам объект JavaScript request. Поскольку они являются элементами формы, эти свойства объекта request являются строками JavaScript. Код изменяет ID на целое число перед передачей его Java-конструктору. После передачи request -объекта Java-конструктору этот конструктор может затем вызывать его методы. Этот процесс обсуждается в разделе "Пример Вызывающего Серверного JavaScript".
  3. Использовать project.bugsLock для получения исключительного доступа к массиву project.bugs и сохранить затем новый Bug -экземпляр в этом массиве, индексированным по номеру bug'а, специфицированному в форме. Заметьте, что этот код сохраняет ссылку на Java-объект как значение свойства JavaScript-объекта. О блокировке см. "Безопасное Совместное Использование Объектов с Блокировкой"
  4. .
  5. Отобразить клиенту информацию о bug'е, который Вы только что сохранили.
  6. Если bug ID не введён, вывести сообщение о том, что bug не может быть найден в БД.

Взаимодействие Java с JavaScript


Если Вам нужно использовать объекты JavaScript в Java, Вы обязаны импортировать пакет netscape.javascript в Ваш Java-файл. Этот пакет определяет следующие классы:

Эти классы поставляются в .jar или .zip-файле. См. в книге Серверный JavaScript. Справочник. дополнительную информацию об этих классах.

Например, в Navigator 4. 0 для Windows NT классы поставляются в файле java40.jar в директории Program\Java\Classes ниже директории Navigator'а. Вы можете специфицировать переменную окружения Windows NT, войдя в Control Panel и создав пользовательскую переменную окружения с названием CLASSPATH со значением типа такого:


D:\Navigator\Program\Java\Classes\java40.jar

Дополнительно о CLASSPATH см. Administrator's Guide .

Поскольку Java является строго типизированным языком, а JavaScript - слабо типизированным, машина выполнения JavaScript конвертирует значения аргументов в подходящие типы данных другого языка, при использовании LiveConnect. См. "Конвертация Типов Данных".

Использование Классов LiveConnect


Все объекты JavaScript появляются в коде Java как экземпляры netscape.javascript.JSObject. Когда Вы вызываете метод в Вашем Java-коде, Вы можете передать ему JavaScript-объект как один из аргументов. Чтобы сделать это, Вы обязаны определить соответствующий формальный параметр метода как имеющий тип JSObject.

Таким образом, всегда, когда Вы используете JavaScript-объекты в коде Java, Вы должны помещать вызов JavaScript-объекта внутри блока try...catch, который обрабатывает исключения netscape.javascript.JSException. Это позволяет Вашему Java-коду обрабатывать ошибки при выполнении кода JavaScript, которые появляются в Java как исключения типа JSException.

Доступ к JavaScript с Помощью JSObject


Предположим, к примеру, что вы работаете с Java-классом JavaDog. Как показано в следующем коде, конструктор JavaDog constructor принимает JavaScript-объект jsDog, который определён как имеющий тип JSObject, в качестве аргумента:


import netscape.javascript.*;

public class JavaDog
{
    public String dogBreed;
    public String dogColor;
    public String dogSex;

    // определить конструктор класса
    public JavaDog(JSObject jsDog)
    {
        // использовать try...catch для обработки JSExceptions
        this.dogBreed = (String)jsDog.getMember("breed");
        this.dogColor = (String)jsDog.getMember("color");
        this.dogSex = (String)jsDog.getMember("sex");
    }
}

Обратите внимание, что метод getMember объекта JSObject используется для доступа к свойствам объекта JavaScript. Предыдущий пример использует getMember для присвоения значения JavaScript-свойства jsDog.breed члену данных Java JavaDog.dogBreed.

ПРИМЕЧАНИЕ: Более жизненный пример помещает вызов getMember в блок try...catch для обработки ошибок типа JSException. См. "Обработка Ошибок JavaScript в Java".

Чтобы лучше понять, как работает getMember, посмотрим на определение специального JavaScript-объекта Dog:


function Dog(breed,color,sex) {
   this.breed = breed
   this.color = color
   this.sex = sex
}

Вы можете создать JavaScript-экземпляр Dog под названием gabby:


gabby = new Dog("lab","chocolate","female")

Если Вы вычислите свойство gabby.color, Вы увидите, что оно имеет значение "chocolate". Теперь предположим, что Вы создаёте экземпляр JavaDog в вашем JavaScript-коде, передавая объект gabby -конструктору:


javaDog = new Packages.JavaDog(gabby)

Если Вы вычислите javaDog.dogColor, Вы увидите, что оно также имеет значение "chocolate", поскольку метод getMember в Java-конструкторе присваивает dogColor значение gabby.color.

Обработка Исключений JavaScript в Java


Если JavaScript-код, вызванный из Java, потерпел неудачу на этапе прогона/выполнения, он вызывает исключение. Если Вы вызываете JavaScript-код из Java, Вы можете отловить/catch это исключение в блоке операторов try...catch. Исключение JavaScript доступно коду Java как экземпляр netscape.javascript.JSException. JSException это Java-оболочка вокруг исключения любого типа, вызываемого в JavaScript, так же как и экземпляры JSObject являются оболочками для JavaScript-объектов.

Используйте JSException при вычислении JavaScript-кода в Java. Если JavaScript-код не вычисляется из-за ошибки компиляции JavaScript или из-за какой-то другой ошибки времени прогона, интерпретатор JavaScript генерирует сообщение об ошибке, которое конвертируется в экземпляр JSException.

Например, можно использовать блок try...catch для обработки исключений LiveConnect:


try {
   global.eval("foo.bar = 999;");
} catch (Exception e) {
   if (e instanceof JSException) {
      jsCodeFailed()";
   } else {
      otherCodeFailed();
   }
}

В этом примере оператор eval терпит неудачу, если foo не определён. Блок catch выполняет метод jsCodeFailed, если оператор eval в блоке try вызывает JSException; метод otherCodeFailed выполняется, если блок try вызывает какую-то иную ошибку.

Доступ к Серверному JavaScript


Рассмотрим теперь использование Java для доступа к серверному JavaScript. Для того чтобы метод Java получил доступ к объектам JavaScript, он обязан быть вызван из приложения, написанном на серверном JavaScript. В клиентском JavaScript, Java может инициировать взаимодействие с JavaScript. На сервере Java не может инициировать это взаимодействие.

ПРИМЕЧАНИЕ:

Когда Вы рекомпилируете Java-класс, который используется в приложении JavaScript, новое определение может не иметь немедленного эффекта. Если любое приложение JavaScript, запущенное на web-сервере, имеет "живую" ссылку на объект, созданный из старого определения класса, все приложения продолжают использовать старое определение. Поэтому при рекомпилировании Java-класса Вы должны рестартовать любые приложения JavaScript, имеющие доступ к этому классу.

Потоки


Java даёт вам возможность создавать раздельные потоки выполнения. Вы должны осторожно использовать эту возможность, если Ваш Java-код взаимодействует с JavaScript-кодом.

Каждый запрос серверного JavaScript обрабатывается в потоке, известном как request thread/поток запроса. Этот поток запроса ассоциируется с информацией о статусе, такой как контекст JavaScript, используемый для процессинга информации HTTP-запроса, и HTTP-буфер ответа.

Когда Вы вызываете Java-код из приложения JavaScript, этот код Java работает в том же самом потоке запроса, что и оригинальное приложение JavaScript. Java-код в этом потоке может взаимодействовать с приложением JavaScript и иметь гарантию, что оно является таким, как он ожидает. Точнее, он может полагаться на ассоциированную информацию статуса.

Однако Вы можете создать новый поток из Java-кода. Если Вы это сделаете, этот новый поток не сможет взаимодействовать с приложением JavaScript и не сможет опираться на информацию о статусе, ассоциированную с оригинальным потоком запроса. Если он попытается это сделать, поведение будет неопределённым. Например, создаваемый Вами Java-поток не может ни инициировать выполнение JavaScript-кода через использование JSObject, ни использовать writeHttpOutput, поскольку этот метод требует доступа к HTTP-буферу ответа.

Пример Вызывающего Серверного JavaScript


В директории $NSHOME\js\samples\bugbase содержится простое приложение, которое иллюстрирует использование LiveConnect. В это разделе описывается приложение-образец Java-кода. См. в разделе "Пример JavaScript, Вызывающего Java" описание основ работы этого приложения и его JavaScript-кода.


// Шаг 1. Импортировать необходимые Java-объекты.

package Bugbase;
import netscape.javascript.*;
import netscape.server.serverenv.*;

// Шаг 2. Создать класс Bug.

public class Bug {
   int id;
   String priority;
   String product;
   String description;
   String submitter;

   // Шаг 3. Определить конструктор класса.
   public Bug(int id, String priority, JSObject req)
   throws java.io.IOException
   {
      // Записать часть http-ответа.
      NetscapeServerEnv.writeHttpOutput("Java constructor: Creating
         a new bug.<br>");
      this.id = id;
      this.priority = priority;
      this.product = (String)req.getMember("bugProduct");
      this.description = (String)req.getMember("bugDesc");
   }

   // Шаг 4. Возвратить строковое представление объекта.

   public String toString()
   {
      StringBuffer result = new StringBuffer();
      result.append("\r\nId = " + this.id
         + "; \r\nPriority = " + this.priority
         + "; \r\nProduct = " + this.product
         + "; \r\nDescription = " + this.description);
      return result.toString();
   }   }

Многие шаги в этом коде не являются специфичными для взаимодействия с JavaScript. Только шаги 1 и 3 имеют отношение к JavaScript.

  1. Специфицировать пакет, используемый в файле, и импортировать пакеты netscape.javascript и netscape.server.serverenv. Если Вы пропустите этот шаг, Вы не сможете использовать объекты JavaScript.
  2. Создать Java-класс Bug, специфицировать его поля.
  3. Определить конструктор для этого класса. Этот конструктор принимает три параметра: целое число, строку и объект типа JSObject. Этот последний параметр является представлением JavaScript-объекта в Java. Через методы этого объекта конструктор может получить доступ к свойствам и вызвать методы объекта JavaScript. В этом случае он использует метод getMember объекта JSObject для получения значений свойств JavaScript-объекта. Также этот метод использует метод writeHttpOutput предопределённого объекта NetscapeServerEnv (из пакета netscape.server.serverenv) для вывода информации в процессе конструирования объекта. Этот метод записывает массив байтов в тот же поток вывода, который используется JavaScript-функцией write.
  4. Определить метод toString. Это стандартный метод для Java-объекта, возвращающий строковое представление полей объекта.

Конвертация Типов Данных


Поскольку Java является строго типизированным, а JavaScript - слабо типизированным языком, машина выполнения JavaScript конвертирует значения аргументов в подходящие типы данных других языков, если Вы пользуетесь LiveConnect. Эта конвертация описана в следующих разделах:

Конвертация из JavaScript в Java


Если Вы вызываете Java-метод и передаёте ему параметры из JavaScript, типы данных передаваемых параметров конвертируются в соответствии с правилами, описанными в следующих разделах:

Return-значения методов netscape.javascript.JSObject всегда конвертируются в экземпляры java.lang.Object. Правила конвертации этих return-значений также описаны в этих разделах.

Например, если JSObject.eval возвращает число JavaScript, Вы можете найти правило конвертации этого числа в экземпляр java.lang.Object в разделе "Числовые Значения".

Числовые Значения


Если Вы передаёте числовые типы JavaScript в качестве параметров Java-методам, Java конвертирует эти значения в соответствии с правилами из данной таблицы:

Тип Java-параметра Правила конвертации

double

Точное значение переносится в Java без округления и без потери точности или знака.

lava.lang.Double
java.lang.Object

Создаётся новый экземпляр java.lang.Double, и точное значение переносится в Java без округления и без потери точности или знака.

float

  • Значения округляются до точности float.
  • Значения, которые слишком велики либо малы, округляются до +бесконечности
    или -бесконечности.

byte
char
int
long
short

  • Значения округляются с использованием режима "округление до минус-бесконечности"/round-to-negative-infinity.
  • Значения, которые слишком велики либо малы, дают ошибку времени выполнения.
  • NaN -значения конвертируются до нуля.

java.lang.String

Значения конвертируются в строки. Например,

  • 237 становится "237"

boolean

  • 0 и NaN -значения конвертируются в false.
  • Другие значения конвертируются в true.

Когда число JavaScript передаётся как параметр в Java-метод, ожидающий экземпляр java.lang.String, это число конвертируется в строку. Используйте операцию == для сравнения результата этой конвертации с другими строковыми значениями.

Булевы Значения


Когда Вы передаёте Булев тип JavaScript в качестве параметра Java-методам, Java конвертирует эти значения в соответствии с правилами, описанными в таблице:

Тип Java-параметра Правила конвертации

boolean

Все значения конвертируются непосредственно в Java-эквиваленты.

lava.lang.Boolean
java.lang.Object

Создаётся новый экземпляр java.lang.Boolean. Каждый параметр создаёт новый экземпляр, а не экземпляр с тем же примитивным значением.

java.lang.String

Значения конвертируются в строки. Например:

  • true становится "true"
  • false становится "false"

byte
char
double
float
int
long
short

  • true становится 1
  • false становится 0

Когда JavaScript Boolean передаётся в качестве параметра Java-методу, ожидающему экземпляр java.lang.String, Boolean конвертируется в строку. Используйте операцию == для сравнения результата конвертации с другими строковыми значениями.

Строковые Значения


Когда Вы передаёте строковые типы JavaScript в качестве параметра Java-методам, Java конвертирует эти значения в соответствии с правилами, описанными в таблице:

Тип Java-параметра Правила конвертации

lava.lang.String
java.lang.Object

Строка JavaScript конвертируется в экземпляр java.lang.String с ASCII-значением.

byte
double
float
int
long
short

Все значения конвертируются в числа, как описано в ECMA-262.

char

Все значения конвертируются в числа.

boolean

  • Пустая строка становится false.
  • все другие значения становятся true.

Null-Значения


Когда Вы передаёте null JavaScript в качестве параметра Java-методам, Java конвертирует это значение в соответствии с правилами, описанными в таблице:

Тип Java-параметра Правила конвертации

Любой класс
Любой тип интерфейса

Значение становится null.

byte
char
double
float
int
long
short

Значение становится 0.

boolean

Значение становится false.

Объекты JavaArray и JavaObject


В большинстве случаев, когда Вы передаёте объект JavaScript JavaArray или JavaObject как параметр Java-методу, Java просто разворачивает этот объект (снимает оболочку); иногда объект переводится в другой тип данных по правилам из таблицы:

Тип Java-параметра Правила конвертации

Любой интерфейс или класс, который совместим в операции присвоения с развёрнутым объектом.

Оболочка с объекта снимается.

java.lang.String

Оболочка с объекта снимается, вызывается метод toStringразвёрнутого Java-объекта, а результат возвращается как новый экземпляр java.lang.String.

byte
char
double
float
int
long
short

Оболочка с объекта снимается, и возникает одна из следующих ситуаций:

  • Если развёрнутый Java-объект имеет метод doubleValue, JavaArray или JavaObject конвертируется в значение, возвращаемой этим методом.
  • Если развёрнутый Java-объект не имеет метода doubleValue, возникает ошибка.

boolean

Оболочка с объекта снимается, и возникает одна из следующих ситуаций:

  • Если развёрнутый объект имеет метод booleanValue, объект-источник конвертируется в это return-значение.
  • Если развёрнутый объект не имеет метода booleanValue, конвертация терпит неудачу.

Интерфейс или класс совместимы для присвоения с развёрнутым объектом, если развёрнутый объект является экземпляром типа Java-параметра. То есть, следующий оператор обязан возвращать true:



развёрнутыйОбъект instanceof типПараметра

Объекты JavaClass


Если вы передаёте JavaScript-объект JavaClass в качестве параметра Java-методу, Java конвертирует объект в соответствии с правилами из таблицы:

Тип Java-параметра Правила конвертации

java.lang.Class

Оболочка с объекта снимается.

java.lang.JSObject
java.lang.Object

Объект JavaClass оборачивается в новый экземпляр java.lang.JSObject.

java.lang.String

Оболочка с объекта снимается, вызывается метод toString развёрнутого Java-объекта, а результат возвращается как новый экземпляр java.lang.String.

boolean

Оболочка с объекта снимается, и возникает одна из следующих ситуаций:

  • Если развёрнутый объект имеет метод booleanValue, исходный объект конвертируется в return-значение.
  • Если объект не имеет метода booleanValue, конвертация терпит неудачу.

Другие Объекты JavaScript


Если вы передаёте любой другой объект JavaScript в качестве параметра Java-методу, Java конвертирует объект в соответствии с правилами из таблицы:

Тип Java-параметра Правила конвертации

java.lang.JSObject
java.lang.Object

Объект оборачивается в новый экземпляр java.lang.JSObject.

java.lang.String

Оболочка с объекта снимается, вызывается метод toString развёрнутого Java-объекта, а результат возвращается как новый экземпляр java.lang.String.

byte
char
double
float
int
long
short

Объект конвертируется в значение с использованием логики оператора ToPrimitive, описанного в ECMA-262. Подсказка PreferredType, используемая с этим оператором, это Number.

boolean

Оболочка с объекта снимается, и возникает одна из следующих ситуаций:

  • Если развёрнутый объект имеет метод booleanValue, исходный объект конвертируется в return-значение.
  • Если объект не имеет метода booleanValue, конвертация терпит неудачу.

Конвертация из Java в JavaScript


Значения, переданные из Java в JavaScript конвертируются так:

Java String -объекты также соответствуют оболочкам JavaScript. Если Вы вызываете JavaScript-метод, который требует строки JavaScript, и передаёте его данной оболочке, Вы получите ошибку. Вместо этого конвертируйте оболочку в строку JavaScript, присоединяя к ней пустую строку, как показано здесь:


var JavaString = JavaObj.methodThatReturnsAString();
var JavaScriptString = JavaString + "";

1 http://developer.netscape.com/docs/manuals/enterprise/javanote/index35.html

2 http://developer.netscape.com/docs/manuals/index.html?content=javascript.html

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 7
Другая Функциональность JavaScript

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

В главе имеются следующие разделы:

Почтовая Служба/Mail Service


Вашему приложению может понадобиться отправить email-сообщение. Для этого Вы используете экземпляры класса SendMail. Единственным методом SendMail является send, для отправки сообщения, а errorCode и errorMessage служат для интерпретации ошибок.

Например, следующий скрипт отсылает почту в vpg со специфицированной темой/subject и телом сообщения:


<server>
SMName = new SendMail();
SMName.To = "vpg@royalairways.com";
SMName.From = "thisapp@netscape.com";
SMName.Subject = "Here's the information you wanted";
SMName.Body = "sharm, maldives, phuket, coral sea, taveuni, maui,
   cocos island, marathon cay, san salvador";
SMName.send();
</server>

В таблице даны свойства класса SendMail. Свойства To и From необходимы; все остальные свойства - по выбору/optional.

Таблица 7.1  Свойства класса SendMail

To

Список разделённых запятыми первичных/primary получателей сообщения.

From

Имя пользователя/user name отправляющего сообщение.

Cc

Список разделённых запятыми дополнительных получателей сообщения.

Bcc

Список разделённых запятыми получателей сообщения, чьи имена не должны быть видны в сообщении.

Smtpserver

Имя почтового сервера (SMTP). По умолчанию это свойство имеет значение, установленное на сервере администрирования.

Subject

Тема сообщения.

Body

Текст сообщения.

Вы можете добавлять к этим свойствам любые другие. Все свойства класса SendMail включаются в шапку/header сообщения при фактической отправке. Например, следующий код отсылает сообщение получателю bill от vpg, устанавливая в поле vpg organization значение Royal Airways. Отвечает на сообщение от vpgboss.


mailObj["Reply-to"] = "vpgboss";
mailObj.Organization = "Royal Airways";
mailObj.From = "vpg";
mailObj.To = "bill";
mailObj.send();

Дополнительно о предопределённых полях шапки см. RFC 822, стандарт формата текстовых сообщений Internet.

Класс SendMail позволяет отправлять простое текстовое почтовое сообщение или сложное MIME-сообщение. Вы можете также добавить в сообщению приложение/attachment. Для отправки MIME-сообщения добавьте свойство Content-type к объекту SendMail и укажите в нём MIME-тип сообщения.

Например, следующий участок кода отсылает изображение в формате GIF:


<server>
SMName = new SendMail();
SMName.To = "vpg@royalairways.com";
SMName.From = "thisapp@netscape.com";
SMName.Subject = "Here's the image file you wanted";
SMName["Content-type"] = "image/gif";
SMName["Content-Transfer-Encoding"] = "base64";

// В следующем операторе image2.gif обязан быть кодирован с базой 64/base 64.
// Если вы используете uuencode для кодирования GIF-файла, удалите header
// (например, "begin 644 image2.gif") и замыкающий ("end").
fileObj = new File("/usr/somebody/image2.gif");

openFlag = fileObj.open("r"); 
if ( openFlag ) {
   len = fileObj.getLength();
   SMName.Body = fileObj.read(len);
   SMName.send();
   }
</server>

Некоторые MIME-типы требуют больше информации. Например, если content type это multipart/mixed, Вы обязаны также специфицировать сепаратор границ для одного или более различных наборов данных тела. Например, следующий код отсылает многочастное сообщение, содержащее две части, каждая из которых является обычным текстом:


<server>
SMName = new SendMail();
SMName.To = "vpg@royalairways.com";
SMName.From = "thisapp@netscape.com";
SMName.Subject = "Here's the information you wanted";
SMName["Content-type"]
   = "multipart/mixed; boundary=\"simple boundary\"";
fileObj = new File("/usr/vpg/multi.txt");
openFlag = fileObj.open("r");
if ( openFlag ) {
   len = fileObj.getLength();
   SMName.Body = fileObj.read(len);
   SMName.send();
   }
</server>

Вот файл multi.txt, содержащий многочастное сообщение:


Это место для преамбулы. 
Она игнорируется.
Это удобное место для комментария, предназначенного для читателей, не знакомых с MIME.
--простая граница

Это первая часть тела сообщения. 
Это НЕ конец с символом обрыва строки.

--простая граница

Content-Type: text/plain; charset=us-ascii

Это вторая часть  тела сообщения.
Это КОНЕЦ с символом обрыва строки.

--простая граница--

Это эпилог. Он также игнорируется.

Вы можете вкладывать друг в друга многочастные сообщения. То есть, если у Вас есть сообщение, content type которого многочастный, Вы можете включить другой многочастное сообщение в его тело. В таких случаях будьте внимательны и убедитесь, штаа каждый вложенный многочастный объект использует разные ограничители.

Детали о MIME-типах см. в RFC 1341 1 , MIME-стандарте. Об отправке почтовых сообщений в JavaScript см. также описание этого класса в книге Серверный JavaScript. Справочник .

Служба Файловой Системы


JavaScript предоставляет класс File, который даёт приложению возможность записывать в файловой системе сервера. Это используется для генерации постоянных HTML-файлов и хранения информации без использования сервера БД. Одним из важнейших преимуществ хранения информации в файле вместо JavaScript-объектов является то, что информация сохраняется даже при отказе сервера.

Проблемы Безопасности


Соблюдайте осторожность при использовании класса File. Приложение JavaScript может читать или записывать файлы везде, где позволяет операционная система, в том числе, возможно, и в системных файлах. Вы должны быть уверены, что Ваше приложение не позволяет читать файлы паролей и другую закрытую информацию или записывать в файлы. Делайте так, чтобы имена файлов, которые Вы передаёте в методы, не могли быть изменены хакерами.

Например, не используйте свойства объектов client или request в качестве имён файлов, поскольку эти значения могут стать доступными хакеру через куки или URL. В таких случаях хакер сможет модифицировать куки или URL, чтобы получить доступ к закрытым файлам.

Исходя из таких же соображений, Navigator не предоставляет автоматического доступа к файловой системе клиентской машины. Если необходимо, пользователь может сохранять информацию непосредственно в клиентской файловой системе, делая соответствующий выбор в меню Navigator'а.

Создание File-Объекта


Чтобы создать экземпляр класса File, используйте стандартный синтаксис JavaScript для создания объекта:


fileObjectName = new File("path");

Здесь fileObjectName это имя, по которому Вы обращаетесь к файлу, а path это полный путь к файлу. Этот path должен быть в формате серверной файловой системы, а не URL.

Вы можете отобразить имя файла, используя функцию write с File -объектом в качестве аргумента. Например, следующий оператор выводит имя файла:


x = new File("\path\file.txt");
write(x);

Открытие и Закрытие Файла


После создания File -объекта Вы можете использовать метод open для открытия файла и чтения и записи. Метод open имеет следующий синтаксис:


result = fileObjectName.open("mode");

Это метод возвращает true, если операция прошла успешно, и false в ином случае. Если файл уже открыт, операция терпит неудачу, и оригинальный файл остаётся открытым.

Параметр mode это строка, специфицирующая режим открытия файла. В таблице описаны эти режимы.

Таблица 7.2  Режимы доступа к файлу
Режим Описание

r

Открывает файл, если он существует, как текстовый файл для чтения и возвращает true. Если файл не существует, возвращает false.

w

Открывает файл как текстовый файл для записи. Создаёт новый (первоначально пустой) текстовый файл, независимо от того, существует файл или нет.

a

Открывает файл как текстовый файл для дополнения (записи в конец файла). Если файл ещё не существует, создаёт его.

r+

Открывает файл как текстовый файл для чтения и записи. Чтение и запись начинаются в начале файла. Если файл существует, возвращает true. Если не существует, возвращает false.

w+

Открывает файл как текстовый файл для чтения и записи. Создаёт новый (первоначально пустой) текстовый файл, независимо от того, существует файл или нет.

a+

Открывает файл как текстовый файл для чтения и записи. Чтение и запись начинаются в конце файла. Если файл не существует, создаёт его.

b

Если присоединён к одному из вышеуказанных режимов, открывает файл как бинарный/двоичный файл, а не как текстовый. Применяется только для операционных систем Windows.

Когда приложение заканчивает использование файла, оно может закрыть его, вызвав метод close. Если файл не открыт, close терпит неудачу. Это метод возвращает true при успехе и false - в противном случае.

Блокировка Файлов


Часто доступ ко многим приложениям могут выполнять одновременно многие пользователи. Вообще разные пользователи не должны пытаться одновременно вносить изменения в файлы, поскольку это может привести к непредсказуемым ошибкам.

Чтобы предотвратить модификацию файла одновременно несколькими пользователями, используйте один из механизмов блокирования, предоставляемых службой Session Management Service, как описано в разделе "Безопасное Совместное Использование Объектов с Помощью Блокировки". Если один пользователь блокировал файл, другие пользователи приложения должны ждать, пока файл не будет разблокирован. В общем это означает, что lock (замок/блокировка) должна предшествовать всем файловым операциям; после выполнения операций должно выполняться unlock (разблокирование).

Если только одно приложение может модифицировать данный файл, Вы можете получать блокировку в объекте project. Если более чем одно приложение может иметь доступ к одному и тому же файлу, получайте блокировку в объекте server.

Например, у Вас создан файл myFile. Затем Вы может использовать его так:


if ( project.lock() ) {
   myFile.open("r");
   // ... файл используется ...
   myFile.close();
   project.unlock();
}

Таким образом, только один пользователь приложения может изменять файл в данный момент времени. Для более тонкого управления блокировкой Вы можете создать Ваш собственный экземпляр класса Lock для управления доступом к данному файлу. Это описано в разделе "Использование Lock-Экземпляров".

Работа с Файлами


Класс File имеет несколько методов, которые можно использовать после открытия файла:

Эти методы описаны в последующих разделах.

Позиционирование Внутри Файла


Физический файл, ассоциированный с File -объектом, имеет указатель текущей позиции в файле. Когда Вы открываете файл, указатель находится в начале либо в конце файла, в зависимости от режима, использованного при открытии файла. В пустом файле начало и конец файла это одна точка.

Метод setPosition позиционирует указатель в файле, возвращая true при успехе и false - в ином случае.


fileObj.setPosition(position);
fileObj.setPosition(position, reference);

Здесь fileObj это File -объект, position это целое число, указывающее позицию указателя, а reference указывает относительную точку для position таким образом:

Метод getPosition возвращает текущую позицию в файле, где первый байт файла это всегда байт 0. Этот метод возвращает -1, если имеется ошибка.


fileObj.getPosition();

Метод eof возвращает true, если указатель находится в конце файла, и false - в ином случае. Этот метод возвращает true после первой операции чтения, которая пытается прочесть после конца файла.


fileObj.eof();

Чтение из Файла


Используйте методы read, readln и readByte для чтения из файла.

Метод read читает специфицированное количество байтов из файла и возвращает строку.


fileObj.read(count);

Здесь fileObj это File -объект, а count это целое число, специфицирующее количество байтов для чтения. Если count специфицирует больше байтов, чем осталось в файле, метод читает до конца файла.

Метод readln читает следующую строку файла и возвращает её как строку.


fileObj.readln();

Здесь fileObj это File -объект. Символы-разделители строк (\r\n в Windows или просто \n в Unix или Macintosh) не включаются в строку. Символ \r пропускается; \n определяет действительный конец строки. Этот компромисс даёт осмысленное поведение на всех платформах.

Метод readByte читает следующий байт из файла и возвращает числовое значение следующего байта или -1.


fileObj.readByte();

Запись в Файл


Для записи в файл имеются методы write, writeln, writeByte и flush.

Метод write записывает строку в файл. В случае успеха операции возвращает true и false - в ином случае.


fileObj.write(string);

Здесь fileObj это File -объект, в string это строка JavaScript.

Метод writeln записывает сроку в файл и вводит последующие \n (\r\n в текстовом режиме Windows). Возвращает true при успешном выполнении записи и false - в ином случае.


fileObj.writeln(string);

Метод writeByte записывает байт в файл. Возвращает true в случае успеха и false - в противном случае.


fileObj.writeByte(number);

Здесь fileObj это File -объект, а number это число.

Когда Вы используете один из этих методов, содержимое файла внутренне буферизуется. Метод flush записывает буфер в файл на диске. Этот метод возвращает true в случае успеха и false - в противном случае.


fileObj.flush();

Конвертация Данных


Есть два основных формата файлов : ASCII-текст и бинарный. Методы byteToString и stringToByte класса File конвертируют данные этих форматов.

Метод byteToString конвертирует число в односимвольную строку. Это static-метод. Вы можете использовать класс File сам по себе, а не его экземпляр, для вызова этого метода.


File.byteToString(number);

Если аргумент - не число, метод возвращает пустую строку.

Метод stringToByte конвертирует первый символ своего аргумента, строку, в число. Это также static-метод.


File.stringToByte(string);

Метод возвращает числовое значение первого символа или 0.

Получение Информации о Файле


Вы можете использовать несколько методов класса File для получения информации о файлах и работы с error-статусом.

Метод getLength возвращает число символов в текстовом файле или количество байтов в любом другом файле. Возвращает -1, если возникла ошибка.


fileObj.getLength();

Метод exists возвращает true, если файл существует, и false - в ином случае.


fileObj.exists();

Метод error возвращает статус ошибки или -1, если файл не открыт или не может быть открыт. Статус ошибки/error status это ненулевое значение, если ошибка возникла, и 0 в ином случае (нет ошибки). Коды статуса ошибки зависят от платформы; обратитесь к документации по Вашей ОС.


fileObj.error();

Метод clearError очищает error-статус (значение error) и значение eof.


fileObj.clearError();

Пример


На сервере Netscape имеется приложение-образец Viewer. Поскольку это приложение даёт возможность просматривать файлы на сервере, оно не устанавливается автоматически.

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

Следующий код из приложения Viewer создаёт экземпляр класса File, открывает его для чтения и генерирует HTML, отражающий строки файла, с разделительной линией после каждой строки.


x = new File("\tmp\names.txt");
fileIsOpen = x.open("r");
if (fileIsOpen) {
   write("file name: " + x + "<BR>");
   while (!x.eof()) {
      line = x.readln();
      if (!x.eof())
         write(line+"<br>");
   }
   if (x.error() != 0)
      write("error reading file" + "<BR>");
   x.close();
}

Работа с Внешними Библиотеками


Для взаимодействия с внешними приложениями рекомендуется использовать LiveConnect, как описано в Главе 14, "LiveConnect. Обзор.". Однако Вы можете также вызывать функции, написанные на других языках, таких как C, C++ или Pascal, и скомпилированных в библиотеки. Такие функции называются native-функции или внешние функции. Библиотеки внешних функций, называемые внешними библиотеками, являются библиотеками динамической компоновки/dll в ОС Windows и совместно используемыми объектами/shared objects - в ОС Unix.

Важно!

 Будьте осторожны при использовании внешних функций в Вашем приложении. Внешние функции могут нарушить защиту/безопасность, если внешняя программа выполняет команды пользователя в командной строке (например, программа, дающая возможность войти в ОС, или команды оболочки/shell). Эта функциональность опасна, так как хакер может присоединить дополнительные команды, используя точку с запятой для присоединения нескольких операторов. Лучше исключить использование ввода командной строки, если Вы не проверяете его достаточно жёстко.

Внешние функции используются в следующих случаях:

В директории примеров jsaccall есть несколько исходных и header-файлов, иллюстрирующих вызов функций внешних библиотек из приложения JavaScript.

В Application Manager Вы ассоциируете внешнюю библиотеку с определённым приложением. Но после того как библиотека ассоциирована с одним из приложений, она становится доступной всем другим установленным приложениям.

Выполните следующие действия для использования библиотеки внешних функций в приложении JavaScript:

  1. Напишите и скомпилируйте библиотеку внешних функций в форме, совместимой с JavaScript. (См. "Рекомендации по Написанию Внешних Функций")
  2. .
  3. С помощью Application Manager идентифицируйте используемую библиотеку, установив новое приложение или изменив параметры установки существующего приложения. После этого все приложения на данном сервере смогут вызывать внешние функции этой библиотеки. (См. "Идентификация Файлов Библиотек")
  4. .
  5. Рестартуйте сервер, чтобы загрузить библиотеку с Вашим приложением. Функции внешней библиотеки теперь доступны для всех приложений на этом сервере.
  6. В вашем приложении используйте функции JavaScript registerCFunction - для идентифицирования вызываемых функций библиотеки - и callC - для вызова этих функций. (См. "Регистрация Внешних Функций" и "Использование Внешних Функций в JavaScript")
  7. .
  8. Рекомпилируйте и рестартуйте Ваше приложение, чтобы изменения вступили в силу.
  9. Важно!

     Вы обязаны рестартовать Ваш сервер, чтобы установить библиотеку для использования с приложениями. Вы обязаны рестартовать сервер каждый раз после добавления файлов новых библиотек или изменения имён файлов библиотек, используемых приложениями.

Рекомендации по Написанию Внешних Функций


Хотя Вы можете написать внешние библиотеки на любом языке, JavaScript использует соглашения языка C по вызову. Ваш код обязан подключать header-файл jsaccall.h, находящийся в директории js\samples\jsaccall\.

Эта директория также содержит исходный код примеров приложений, которые вызывают функции C, определённые в jsaccall.c. Просмотрите эти файлы, чтобы найти более конкретные рекомендации по написанию функций C для использования с JavaScript.

Функции, вызываемые из JavaScript, обязаны быть экспортируемыми и обязаны соответствовать этому определению типа:


typedef void (*LivewireUserCFunction)
   (int argc, struct LivewireCCallData argv[],
    struct LivewireCCallData* result, pblock* pb,
    Session* sn, Request* rq);

Идентификация Файлов Библиотек


Прежде чем Вы сможете запустить приложение, использующее функции внешних библиотек, Вы обязаны идентифицировать файлы этих библиотек. Используя Application Manager, Вы можете идентифицировать библиотеки, когда Вы устанавливаете приложение (щёлкнув Add) или когда модифицируете параметры инсталяции приложения (щёлкнув Modify). Дополнительно об идентификации файлов библиотек с помощью Application Manager см. "Установка Нового Приложения".

Важно!

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

После идентификации внешних библиотек с помощью Application Manager все приложения, запущенные на данном сервере, могут вызывать функции этих библиотек (используя registerCFunction и callC).

Регистрация Внешних Функций


Используйте JavaScript-функцию registerCFunction для регистрации внешней функции для использования с приложением JavaScript. Эта функция имеет следующий синтаксис:


registerCFunction(JSFunctionName, libraryPath, CFunctionName);

Здесь JSFunctionName это имя функции как она будет вызываться в JavaScript функцией callC. Параметр libraryPath это полный путь к библиотеке, использующий соглашения Вашей ОС, а параметр CFunctionName это имя C-функции как она определена в библиотеке. В вызове этого метода Вы обязаны вводить имя точно в указанном регистре, указанном в Application Manager, даже в ОС NT.

ПРИМЕЧАНИЕ:

Backslash (\) это специальный символ в JavaScript, поэтому Вы обязаны использовать forward slash (/) или двойной backslash (\\) для отделения Windows-директории и имён файлов в libraryPath.

Данная функция возвращает true, если функция зарегистрирована успешно, и false - в ином случае. Функция может потерпеть неудачу, если JavaScript не сможет найти библиотеку по специфицированному пути или не найдёт специфицированную функцию в библиотеке.

Приложение обязано использовать registerCFunction для регистрации функции, прежде чем сможет использовать callC для её вызова. После того как приложение зарегистрировало функцию, оно может вызывать эту функцию любое число раз. Хорошим местом для регистрации функций является начальная страница приложения.

Использование Внешних Функций в JavaScript


После того как Ваше приложение зарегистрировало функцию, оно может использовать callC для её вызова. Эта функция имеет следующий синтаксис:


callC(JSFunctionName, arguments);

Здесь JSFunctionName это имя функции, как она была идентифицирована с помощью registerCFunction, а arguments это список разделённых запятыми аргументов внешней функции. В качестве аргументов могут использоваться любые значения JavaScript: строки, числа, булевы значения, объекты или null. Количество аргументов обязано соответствовать количеству необходимых аргументов внешней функции. Хотя Вы можете специфицировать объект JavaScript в качестве аргумента, это используется редко, поскольку объект конвертируется в строку перед передачей внешней функции.

Эта функция возвращает строковое значение, возвращённое внешней функцией. Функция callC может возвращать только строковые значения.

Приложение-образец jsaccall иллюстрирует использование внешних функций. Директория jsaccall содержит исходный код C (в jsaccall.c), определяющий C-функцию с именем mystuff_EchoCCallArguments. Эта функция принимает любое количество аргументов и возвращает строку, содержащую HTML с перечислением аргументов. Это пример иллюстрирует вызов функций C из приложения JavaScript и возвращаемые значения.

Чтобы запустить jsaccall, Вы обязаны скомпилировать jsaccall.c имеющимся у Вас компилятором C. Командные строки для нескольких распространённых компиляторов даны в файле в виде комментариев.

Следующие операторы JavaScript (взятые из jsaccall.html) регистрируют C-функцию как echoCCallArguments в JavaScript, вызывают функцию echoCCallArguments, а затем генерируют HTML на основе значения, возвращённого данной функцией.


var isRegistered = registerCFunction("echoCCallArguments",
   "c:\\mycode\\mystuff.dll", "mystuff_EchoCCallArguments");
if (isRegistered == true) {
   var returnValue = callC("echoCCallArguments",
      "first arg",
      42,
      true,
      "last arg");
   write(returnValue);
}
else {
   write("registerCFunction() returned false, "
      + "check server error log for details")
}

Функция echoCCallArguments создаёт результирующую строку, содержащую HTML, который выводит тип и значение каждого переданного ей аргумента JavaScript. Если registerCFunction возвращает true, вышеприведённый код генерирует такой HTML:



argc = 4<BR>
argv[0].tag: string; value = first arg<BR>
argv[1].tag: double; value = 42<BR>
argv[2].tag: boolean; value = true<BR>
argv[3].tag: string; value = last arg<BR>

Манипуляции с Запросами и Ответами


Обычный запрос, высылаемый клиентом на сервер, не имеет content type (тип содержимого). Машина выполнения JavaScript автоматически обрабатывает такие запросы. Однако, если пользователь отправляет форму, то клиент автоматически помещает content type в шапку/header, чтобы сообщить серверу, как интерпретировать данные формы. Этот content type обычно application/x-www-form-urlencoded. Машина выполнения также автоматически обрабатывает запросы с этим content type. В таких ситуациях Вам редко нужен прямой доступ к шапкам/header запроса или ответа. Если, однако, Ваше приложение использует иной content type, оно обязано уметь работать с шапкой запроса.

В свою очередь, типичный ответ сервера клиентку имеет тип содержимого text/html. Машина выполнения автоматически добавляет этот content type в свой ответ. Если Вам в ответе нужен другой content type, Вы обязаны предоставить его сами.

Для поддержки этих потребностей машина выполнения JavaScript на сервере даёт возможность Вашему приложению иметь доступ к (1) шапке/header любого запроса и к (2) телу запроса, имеющего нестандартный content type. Вы уже контролируете тело ответа тэгом SERVER и тэгами HTML. Функциональность, описанная в этом разделе, даёт также возможность управлять шапкой/header ответа.

Вы можете использовать эту функциональность в различных целях. Например, как описано в разделе "Использование Кук", можно осуществлять связь серверных и клиентских процессов с помощью кук. Также Вы можете использовать эту функциональность для поддержки выгрузки файлов.

World Wide Web Consortium публикует онлайновую информацию о протоколе HTTP и о том, что может пересылаться по этому протоколу. См., например, HTTP Specifications and Drafts .

Шапка/Header Запроса


Для доступа к парам имя/значение шапки клиентского запроса используйте метод httpHeader объекта request. Этот метод возвращает объект, чьи свойства и значения соответствуют парам имя/значение шапки.

Например, если запрос содержит куки, header["cookie"] или header.cookie будет его значением. Свойство cookie, содержащее все пары имя/значение этой куки (со значениями, кодированными так, как описано в разделе "Использование Кук"), обязано разбираться Вашим приложением.

Следующий код выводит свойства и значения шапки:


var header = request.httpHeader();
var count = 0;
var i;

for (i in header ) {
   write(count + ". " + i + " " + header[i] + "<br>\n");
   count++;
}

Если Вы отправили форму методом GET, на выходе получится примерно так:


0. connection Keep-Alive 
1. user-agent Mozilla/4.0b1 (WinNT; I)
2. host piccolo:2020
3. accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

Если для отправки формы использован метод POST, вывод будет таким:


0. referer http://piccolo:2020/world/hello.html 
1. connection Keep-Alive
2. user-agent Mozilla/4.0b1 (WinNT; I)
3. host piccolo:2020
4. accept image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
5. cookie NETSCAPE_LIVEWIRE.oldname=undefined; NETSCAPE_LIVEWIRE.number=0
6. content-type multipart/form-data; boundary=---------------------------79741602416605
7. content-length 208

Тело Запроса


Для нормальных HTML-запросов content type (тип содержимого) запроса будет application/x-www-form-urlencoded. После получения запроса с этим content type машина выполнения JavaScript на сервере обрабатывает запрос, используя данные из тела запроса. В этой ситуации Вы не можете получить прямой доступ к необработанным данным тела запроса. (Конечно, Вы можете получить доступ к его содержимому через объекты request и client, сконструированные машиной выполнения).

Если, однако, запрос имеет любой иной content type, машина выполнения не обрабатывает автоматически тело запроса. В этом случае Ваше приложение должно определить, что делать с содержимым.

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

Для получения доступа к телу запроса Вы используете метод getPostData объекта request. Этот метод принимает в качестве параметра количество символов тела. Если Вы специфицируете 0, тело возвращается целиком. return-значение это строка, содержащая запрошенные символы. Если доступных данных нет, метод возвращает пустую строку.

Можно использовать этот метод для получения всех символов за один раз или читать участки данных. Представляйте тело запроса как поток символов. При чтении Вы можете только продвигаться вперёд; Вы не можете читать одни и те же символы несколько раз.

Чтобы назначить всё тело запроса переменной postData, можно использовать следующий оператор:


postData = request.getPostData(0);

Если в качестве параметра специфицировано 0, метод получает весь запрос. Вы можете точно определить, сколько символов содержится в информации, используя свойство content-length шапки таким образом:


length = parseInt(header["content-length"], 10);

Для получения тела запроса небольшими блоками Вы можете специфицировать иной параметр. Например, следующий код обрабатывает тело запроса блоками по 20 символов:


var length = parseInt(header["content-length"], 10);
var i = 0;

while (i < length) {
   postData = request.getPostData(20);
   // ...обработка postData...
   i = i + 20;
}

Конечно, такой подход имеет смысл только тогда, когда Вы знаете, что блоки состоят из 20 символов информации.

Шапка/Header Ответа


Если отправляемый клиенту ответ/response использует специальный content type (тип содержимого), Вы должны кодировать этот content type в шапке ответа. Машина выполнения JavaScript автоматически добавляет content type по умолчанию (text/html) в шапку ответа/response header. Если вам необходима специальная шапка, Вы обязаны сначала удалить из шапки старый content type по умолчанию, а затем уже добавить новый. Это делается при помощи функций addResponseHeader и deleteResponseHeader.

Например, если Ваш response использует royalairways-format как специальный content type, Вы можете специфицировать его так:


deleteResponseHeader("content-type");
addResponseHeader("content-type","royalairways-format");

Вы можете использовать функцию addResponseHeader для добавления в шапку ответа любой другой нужной информации.

Важно!

 Помните, что header отсылается с первой частью ответа/response. Следовательно, Вы должны вызывать эти функции раньше в скрипте на каждой странице. В общем, Вы должны быть уверены, что header ответа установлен до любого из следующих событий:

Дополнительно см. разделы "Очистка Буфера Вывода" и "Процессинг Времени Выполнения на Сервере".


1 http://info.internet.isi.edu:80/in-notes/rfc/files/rfc1341.txt

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Часть 2
Возможности Серверного JavaScript

Глава 4. Приложения-Образцы: Быстрый Старт

В главе рассматривается пример приложения серверного JavaScript, поставляемого вместе с Netscape web-серверами. Это введение в использование серверного JavaScript при помощи двух простых приложений-образцов.

Глава 5. Основы Серверного JavaScript

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

Глава 6. Служба Session Management Service

В этой главе рассмотрены объекты службы Session Management Service, введённые в серверном JavaScript для обеспечения возможности совместного использования данных несколькими клиентскими запросами к приложению, несколькими пользователями к одному приложению или даже несколькими приложениями на сервере.

Глава 7. Другая Функциональность JavaScript

В этой главе описана дополнительная функциональность серверного JavaScript, которую вы можете использовать для отправки сообщений e-mail из Вашего приложения, доступа к файловой системе сервера, подключения в приложение внешних библиотек или прямого манипулирования клиентскими запросами и ответами клиенту.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

╘ Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

ЧАСТЬ 4.
Работа с LiveConnect.

Глава 14   LiveConnect. Обзор.

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


Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Часть 3
Служба LiveWire Database Service

Глава 8. Соединение с Базой Данных

В главе обсуждается, как использовать LiveWire Database Service для соединения приложения с реляционными БД DB2, Informix, ODBC, Oracle и Sybase и как выбрать наилучшую методологию соединения с БД.

Глава 9. Работа с Базой Данных

В главе обсуждается работа с реляционными БД DB2, Informix, ODBC, Oracle и Sybase, как запросить информацию из БД и использовать её в Вашем приложении, как работать с транзакциями БД и как выполнять хранимые процедуры.

Глава 10. Конфигурирование Базы Данных

В главе описано, как настроить Вашу БД для работы с LiveWire Database Service. Вы должны прочесть эту главу и "Информацию Конфигурации", прежде чем начать использовать LiveWire с Вашими приложениями JavaScript.

Глава 11. Конвертация Типов Данных

В главе описано, как машина выполнения JavaScript на сервере конвертирует сложные типы данных из реляционных БД и простые типы JavaScript.

Глава 12. Обработка Ошибок LiveWire

В этой главе рассмотрены типы ошибок, которые могут возникнуть при работе с реляционными БД.

Глава 13. Приложения-Образцы Videoapp и Oldvideo

В главе описано приложение-образец videoapp, иллюстрирующее использование службы LiveWire Database Service. Показано, как конфигурировать окружение для запуска приложений videoapp и oldvideo.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

╘ Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Предисловие

В этой книге рассматривается создание приложений, написанных на языке "Серверный/Server-Side JavaScript" (SSJS). JavaScript это разработанный корпорацией Netscape платформонезависимый объектно-ориентированный язык скриптинга (сценариев) для клиентских и серверных приложений.

В данной главе имеются следующие разделы:

Что Нового в Этом Релизе


В релизах 3.x и 4.x версий сервера Netscape Enterprise Server служба LiveWire полностью интегрирована с сервером. Поскольку LiveWire database connectivity теперь интегрирована как LiveWire Database Service - часть серверного JavaScript, разработчикам не нужно устанавливать LiveWire как отдельный продукт. Просто включите поддержку JavaScript в Administration Server, чтобы сделать доступными необходимые компоненты.

ПРИМЕЧАНИЕ:

Отличие между SSJS в Netscape Enterprise Server (NES) 3.x и в NES 4.x состоит в том, что NES 4.x использует теперь JavaScript Runtime от Mozilla.org, которая поддерживает JavaScript 1.4. Предыдущие версии SSJS поддерживали JavaScript 1.0, JavaScript 1.1 и JavaScript 1.2.

Поддержка JavaScript 1.4


В JavaScript версии 1.4 появились новые возможности и различные усовершенствования, которые обсуждаются в онлайновом учебнике Core JavaScript Reference v1.4:



http://developer.netscape.com/docs/manuals/js/core/jsref/index.htm

Также можно воспользоваться моим переводом на русский язык новой версии (Ядро JavaScript 1.5) этой книги .

В следующем списке резюмируются эти новые возможности:

Изменения в JavaScript Application Manager


Функциональность менеджера JavaScript Application Manager не изменилась в Enterprise Server 4.0 по сравнению с Enterprise Server 3.x. Однако он теперь использует ту же новую схему цветов, что и Server Manager в Enteprise Server 4.0, и имеет некоторые изменения внешнего вида.

Рисунок 0.1  JavaScript Application Manager в Enteprise Server 4.0.

JavaScript Application Manager теперь имеет три вкладки:

Хотя названия и внешний вид вкладок и кнопок в JavaScript Application Manager в Enterprise Server 4.0 слегка отличается от Enterprise Server 3.6, их функциональность не изменилась.

Что Вы Уже Должны Знать


Предполагается, что Вы уже имеете следующие базовые знания:

Версии JavaScript


Каждая версия Netscape Enterprise Server поддерживает свою версию JavaScript. Чтобы помочь Вам при создании скриптов, совместимых с несколькими версиями Enterprise Server, в этом учебнике используются сокращённые обозначения версий сервера, в которых каждая возможность реализована.

Версии JavaScript и Netscape Enterprise Server
Версия JavaScript Версии Enterprise Server

JavaScript 1.2

Netscape Enterprise Server 3.6 (NES 3.6)

JavaScript 1.4

Netscape Enterprise Server 4.0 (NES 4.0)

Где Найти Информацию о JavaScript


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

Документацию по JavaScript, состоящую из следующих книг:

Если Вы новичок в JavaScript, начните с Главы 1, "JavaScript. Обзор.". После того как Вы будете иметь твёрдое понимание основ, можете воспользоваться книгой Серверный JavaScript, Справочник. для получения долее детальной информации об объектах и операторах.

Используйте материал этой книги для знакомства с ядром и серверным JavaScript. Пользуйтесь книгами Клиентский JavaScript. Руководство. и Клиентский JavaScript. Справочник. для получения информации о создании сценариев на HTML-страницах.

Enterprise Server 4.x Release Notes содержат информацию о Enterprise Server 4.x, в том числе - касающуюся серверного JavaScript для Enterprise Server 4.x.

Книга Netscape Enterprise Server Programmer's Guide содержит резюме по разным интерфейсам программирования, доступным в версиях 4.x Netscape web-серверов. Используйте это учебник в качестве карты или отправной точки при изучении документации Enterprise Server для разработчиков.

Помимо этого, другие книги Netscape обсуждают отдельные аспекты JavaScript, особенно относящиеся к их области действия. Эти книги упоминаются в тексте данной книги там, где это возможно.

Сайт Netscape содержит большое количество информации, которая может понадобиться при создании приложений JavaScript. Вот некоторые URL, представляющие особый интерес:

Обновление Предыдущей Версии


Если у вас имеется установленная версия предыдущего релиза Netscape web-сервера, Вы должны перенести установки сервера при инсталяции Enterprise Server 4.x. См. Enterprise Server 4.0 Installation and Migration Guide.

Если Вы ранее создавали приложения JavaScript, используя Серверный JavaScript 3.x, Вы должны знать об изменениях, выполняемых при обновлении до версии 4.x и переносе старых установок сервера:

Обратная Совместимость с Предыдущими Релизами


Вы также должны знать об изменениях в поведении приложений серверного JavaScript по сравнению с Netscape Enterprise Server 3.x:

Соглашения по Документам


Приложения JavaScript работают на многих операционных системах; данная информация применима ко всем версиям. Пути файлов и директорий даны в формате Windows (с обратной наклонной чертой в качестве разделителя имён директорий). Для Unix-версий пути директорий - те же,  за исключением того, что в качестве разделителей используются слэши вместо backslash.

В этой книге используются uniform resource locators (URLs) в форме:


http://
server.domain
/
path
/
file
.html

В этих URL server это имя сервера, на котором запускается Ваше приложение, как, например, research1 или www; domain это имя домена Internet, такое как netscape.com или uiuc.edu; path это структура директорий на сервере; а file .html это имя файла. В целом элементы, выделенные italic в URL, являются заглушками, а элементы с нормальным моноширинным шрифтом являются литералами. Если на Вашем сервере имеется Secure Sockets Layer (SSL), Вы должны использовать https вместо http в URL.

В книге использованы следующие соглашения по шрифтам:

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

╘ Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 4
Быстрое Начало с Примерами Приложений

В этой главе рассматриваются образцы приложений серверного JavaScript, поставляемые вместе с Netscape web-сервером. Это начало работы с JavaScript с использованием двух простейших приложений.

В данной главе имеются следующие разделы:

О Приложениях-Образцах Серверного JavaScript


Если вы устанавливаете Netscape web-сервер, несколько примеров приложений JavaScript устанавливаются одновременно. Для получения представления о возможностях приложений JavaScript запустите их и просмотрите исходный код. Вы можете также изменять эти приложения по мере изучения возможностей JavaScript. Исходные и исполняемые файлы этих приложений установлены в директории $NSHOME\js\samples, где $NSHOME это директория, в которой Вы установили сервер.

В таблице перечислены приложения-образцы.

Таблица 4.1  Примеры Приложений JavaScript

Базовые понятия

world

Приложение "Hello World".

hangman

"Виселица".

cipher

Угадай цифру.

LiveWire Database Service 1

dbadmin

Простой интерактивный SQL-доступ с использованием LiveWire.

Если Вы имеете ограниченный доступ к Application Manager, это приложение также защищено именем и паролем администратора сервера.

videoapp

Приложение видео-магазин, использующее реляционную БД видеоклипов.

oldvideo

Альтернативная версия видео-магазина.

LiveConnect

bugbase

Пример БД "жучков" с использованием LiveConnect.

Другие приложения

sendmail

Демонстрирует способность отправлять e-mail из вашего приложения JavaScript.

viewer

Даёт возможность просматривать файлы на сервере, используя класс JavaScript File.

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

jsaccall

Пример использования внешних библиотек и предоставления доступа к CGI-переменным.

1 Эти приложения работают только при наличии поддерживаемого сервера БД, установленного в сети, и корректно сконфигурированного клиентского программного обеспечения. См. Главу 10, "Конфигурирование Базы Данных". Эти приложения обсуждаются в Главе 13, "Приложения-Образцы Videoapp и Oldvideo". Перед началом использования videoapp или oldvideo выполните указания по их установке.

ПРИМЕЧАНИЕ:

Помимо указанных, в директории $NSHOME\js\samples имеется также приложение metadata. Оно используется Visual JavaScript. Когда Вы будете просматривать исходный код, не изменяйте исполняемый файл.

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

В Главе 13, "Приложения-Образцы Videoapp и Oldvideo", приложение videoapp рассматривается детально. Вы должны прочесть эту главу перед началом работы с LiveWire Database Service.

Hello World


В этом разделе Вы запустите приложение Hello World, пример простейшего приложения, и получите представление о следующих процедурах:

Чтобы начать работу с образцами приложений, Вам необходим доступ к JavaScript Application Manager. Вы можете получить этот доступ, введя следующий URL в Navigator:


http://
server.domain
/appmgr

В этом и других URL в данном учебнике server это имя сервера, на котором Вы запускаете Ваше приложение, как, например research1 или www, domain это имя домена Internet, такое как netscape.com или uiuc.edu. Если Ваш сервер имеет Secure Sockets Layer (SSL), используйте  https вместо http в URL.

В Application Manager'е выберите world в левом фрэйме и щёлкните кнопку Run. Вы можете также ввести URL приложения в поле Location Navigator'а:


http://
server.domain
/world

Application Manager выведет страницу, показанную на Рисунке 4.1.

Рисунок 4.1   Hello World

Об Application Manager см. "Технология Разработки Приложений JavaScript".

Как Работает Hello World?


Это приложение демонстрирует две важные вещи: обслуживание различных клиентских статусов  нескольких клиентов и обслуживание существующего статуса приложения. Оно выполняет следующие функции:

При первом посещении страницы пользователем значения обоих имён не определены. Количество предыдущих посещений пользователя равно 0; общее количество посещений также равно 0.

Введите своё имя и нажмите Enter. Страница теперь показывает введённое имя и текст "This time you are." Оба числа посещений увеличиваются на 1. Эта акция иллюстрирует простейшую обработку данных формы. Введите другое имя и нажмите Enter. Страница теперь показывает новое имя и текст "This time you are", а предыдущее имя с - текстом "Last time you were." И вновь оба числа посещений увеличиваются.

Если Вы выполните доступ к приложению из другого экземпляра Navigator'а (или с другого компьютера), страница покажет общее число посещений и количество посещений каждого экземпляра Navigator'а, а не только одного данного экземпляра.

Взгляд на Исходный Скрипт


Теперь посмотрим на исходный код JavaScript для данного приложения. Используйте для этого ваш привычный текстовый редактор, откройте файл $NSHOME\js\samples\world\hello.html, где $NSHOME это директория, в которой установлен ваш Netscape-сервер. Файл начинается обычным HTML:


<html>
<head>
<title> Hello World </title> </head>
<body>
<h1> Hello World </h1>
<p>Your IP address is <server>write(request.ip);</server>

Тэги SERVER в нижней строчке содержат код JavaScript, который выполняется на сервере. В данном случае оператор write(request.ip) выводит свойство ip объекта request (IP-адрес клиента, выполнившего доступ к странице). Функция write очень важна в приложениях JavaScript, поскольку используется для дополнения значений выражений JavaScript в HTML-страницу, отправляемую клиенту.

Объект request является частью службы JavaScript Session Management Service. Полное его описание см. в Главе 6, "Session Management Service". Функция write это одна из функций JavaScript, которые не ассоциированы со специфическим объектом. О функции write см. раздел "Конструирование HTML-Страницы".

Далее идут операторы, пока не представляющие для нас интереса. Затем - оператор:



<server> client.oldname = request.newname;
</server>

Этот оператор присваивает значение свойства newname объекта request свойству oldname объекта client. Объект client также является частью JavaScript Session Management Service. Его полное описание см. в Главе 6, "Session Management Service". Пока просто отметьте, что client может содержать информацию о приложении, специфичную для определённого браузера, запускающего это приложение.

Значение свойства request.newname устанавливается, когда пользователь вводит значение в форме. Далее в файле можно найти такие операторы:


<form method="post" action="hello.html">
<input type="text" name="newname" size="20">

Значением атрибута ACTION формы является hello.html (имя текущего файла). Это означает, что, когда пользователь отправляет форму, щёлкая кнопку Enter или нажимая клавишу Enter, Navigator перезагружает текущую страницу. Вообще, ACTION может быть любая страница приложения JavaScript.

Значением атрибута NAME текстового поля является newname. Когда страница отсылается, этот оператор присваивает то, что пользователь ввёл в текстовом поле, свойству newname объекта request, к которому в JavaScript можно обратиться request.newname. Значения элементов формы всегда соответствуют свойствам объекта request. Свойства объекта request сохраняются только в течение одного (текущего) клиентского запроса.

Несколькими строками ниже находится другой тэг SERVER, указывающий, что следующие строки являются операторами серверного JavaScript. Вот первая группа операторов:


if (client.number == null)
   client.number = 0
else
   client.number = 1 + parseInt (client.number, 10)

Данный условный оператор проверяет, инициализировано ли свойство number объекта client. Если нет, код инициализирует его в 0; иначе number увеличивается на 1 с использованием функции JavaScript parseInt, которая конвертирует строковое значение в число. Поскольку предопределённый объект client конвертирует все значения свойств в строки, Вы обязаны использовать parseInt или parseFloat для конвертации этих значений в числа.

Так как number это свойство объекта client, оно отличается для каждого клиента, выполняющего доступ к приложению. Это значение указывает количество раз, когда "you have been here/Вы здесь были."

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


project.lock() 
if (project.number == null)
   project.number = 0
else
   project.number = 1 + project.number
project.unlock()

Первый оператор использует метод lock объекта project. Это даёт клиенту временный исключительный доступ к объекту project. Оператор if проверяет, было ли определено свойство project.number. Если нет, код инициализирует его в 0; иначе код увеличивает его на 1. Наконец, метод unlock освобождает объект project, и другие клиенты могут получить к нему доступ.

Последние операторы файла выводят значения свойств client.number и project.number.


<p>You have been here <server>write(client.number);</server>
times.
<br>This page has been accessed <server>write(project.number);
</server> times.

Модифицирование Приложения Hello World


В этом разделе Вы модифицируете, рекомпилируете и рестартуете приложение-образец. Для редактирования исходного файла Вы сначала должны найти его. Как Вы помните, Application Manager показывает путь к исполняемому файлу приложения (файлу с расширением .web). Исходный файл hello.html должен находиться в той же директории. Отредактируйте файл. HTML-файл начинается такими операторами:


<html>
<head> <title> Hello World </title> </head>

<body>
<h1> Hello World </h1>
<p>Your IP address is <server>write(request.ip);</server>


<server>
write ("<P>Last time you were " + client.oldname + ".");
</server>
<p>This time you are <server>write(request.newname);</server>


<server>client.oldname = request.newname; </server>

Добавьте строку, выводящую тип пользовательского браузера:


<p>You are using <server>write(request.agent)</server>

Если Вам нужно, можете также персонализировать шапку/head страницы; например, можете сделать такой заголовок: "Fred's Hello World."

Когда вы закончите изменение файла, запустите компилятор приложений JavaScript. В командной строке перейдите в директорию, содержащую исходный файл. Введите такую строку для компиляции приложения:


jsac -v -o hello.web hello.html

Альтернативно Вы можете из этой директории запустить скрипт build (в Unix) или build.bat (в NT). В этом случае компилятор стартует и выводит сообщения. Последнее сообщение должно быть "Compiled and linked successfully/Откомпилировано и скомпоновано успешно".

Опубликуйте файлы на Вашем сервере разработки. Для рестарта войдите в Application Manager, выберите Hello World, затем выберите Restart. Эта операция загрузит на сервер новую откомпилированную версию приложения. Затем Вы можете запустить приложение, выбрав Run. Открывается окно с Hello World. Вы увидите внесённые Вами изменения в приложении.

Hangman


В этом разделе Вы запустите и модифицируете приложение-образец Hangman и получите представление о том, как:

Hangman это классическая игра, в которой игроки пытаются угадать слово. Неизвестные буквы отображаются на экране звёздочками; звёздочка заменяется на букву, если игрок угадывает её. Если введённая буква некорректна, прорисовывается часть повешенного. Игра показывает также некорректные буквы, введённые Вами.

Если повешенный прорисуется полностью, игрок проиграл. Игрок выигрывает, угадав все буквы слова до окончания прорисовки повешенного. В этой упрощённой версии игры есть только три слова для угадывания. После окончания игры можно снова начать её снова (и использовать следующее слово) или закончить игру.

Запустите приложение Hangman, выбрав Hangman в Application Manager и щёлкнув Run. Можно также загрузить приложение в Navigator:


http://
server.domain
/hangman

В ответ Application Manager выведет страницу, показанную на следующем рисунке.

Рисунок 4.2   Hangman

 Поиграйте в игру, чтобы получить представление о работе программы.

Взгляд на Исходные Файлы


В следующей таблице перечислены исходные файлы приложения Hangman.

Таблица 4.2  Исходные файлы приложения Hangman

hangman.html

Главная страница приложения. Она устанавливается как страница по умолчанию приложения Hangman в Application Manager'е. Она выводится, если пользователь введёт просто hangman в URL без специфицирования страницы.


hangman.js

Файл, содержащий только функции серверного JavaScript, используемые в hangman.html.


youwon.html
youlost.html
thanks.html

Страницы, выводимые, если пользователь победил, проиграл или закончил игру, соответственно.


директория images

Изображения программы , hang0.gif, hang1.gif, и т.д.


rules.html

Содержит текст с пояснениями об игре. Этот файл не компилируется вместе с приложением; он включён как пример неоткомпилированной страницы приложения, являющейся частью того сайта.

Основная логика приложения содержится в файле hangman.html. Базовая логика проста, как три рубля:

  1. Для новой игры: инициализируется угадываемое слово и другие переменные.
  2. Если игрок угадал букву, она замещается в вопросе.
  3. Если игрок не угадал, увеличивается число неудачных попыток.
  4. Проверяется, победил пользователь или проиграл.
  5. Прорисовывается текущий вариант изображения с использованием GIF-изображения с учётом неугаданных букв.

Тело/body HTML-файла hangman.html начинается кодом JavaScript в тэге SERVER. Сначала идёт код для инициализации новой игры:


if (client.gameno == null) {
   client.gameno = 1;
   client.newgame = "true";
}

if (client.newgame == "true")
{
   if (client.gameno % 3 == 1)
         client.word = "LIVEWIRE";
   if (client.gameno % 3 == 2)
      client.word = "NETSCAPE";
   if (client.gameno % 3 == 0)
         client.word = "JAVASCRIPT";
   client.answer = InitAnswer(client.word);
   client.used = "";
   client.num_misses = 0;
}

client.newgame = "false";

Этот код использует объект client для сохранения информации об игроке. Поскольку нет необходимости сохранять статус игры между вызовами разных клиентов, этот код не использует объекты project или server.

Первый оператор определяет, играл игрок до этого, или нет, проверяя существование client.gameno; если нет, код инициализируется в 1 и client.newgame устанавливается в true. Затем некоторая простая логика присваивает "секретное слово" свойству client.word; имеются только три секретных слов, по которым игра проходит по циклу. Свойство client.gameno хранит количество игр, сыгранных конкретным пользователем. Финальная часть инициализации использует InitAnswer, функцию, определённую в файле hangman.js, для инициализации свойства client.answer строкой звёздочек.

Затем идёт блок операторов обработки действий игрока по угадыванию:


if (request.guess != null) {
   request.guess = request.guess.toUpperCase().substring(0,1);
   client.used = client.used + request.guess + " ";
   request.old_answer = client.answer;
   client.answer = Substitute (request.guess, client.word,
      client.answer);
   if (request.old_answer == client.answer)
      client.num_misses = parseInt(client.num_misses) + 1;
}

Оператор if определяет, угадал ли игрок (введя букву в форму). Если да, код вызывает Substitute (другую функцию, определённую в файле hangman.js) для замены угаданной буквы в client.answer. Это постепенно прорисовывает слово в client.answer (например, "N*T**AP*").

Второй оператор if проверяет, было ли изменено свойство client.answer после последнего угадывания; если нет, код увеличивает client.num_misses для отслеживания количества некорректных ответов. Вы обязаны всегда использовать parseInt при работе с целочисленными значениями свойств предопределённого объекта client.

Как видно из следующего кода, последний оператор if в коде JavaScript проверяет, победил игрок или проиграл, и перенаправляет клиента соответственно. Функция redirect открывает специфицированный HTML-файл и передаёт управление в него.



if (client.answer == client.word)
   redirect(addClient("youwon.html"));
else if (client.num_misses > 6)
   redirect(addClient("youlost.html"));

Это конец начального тэга SERVER. Начинается HTML, дополненный выражениями JavaScript. Человек прорисовывается с использованием закавыченных выражений JavaScript внутри HTML-тэга IMG:


<IMG SRC=`"images\hang" + client.num_misses + ".gif"`>

Всё выражение между двумя обратными кавычками (`) это строка JavaScript. Она состоит из строкового литерала "images\hang", соединяемого со значением client.num_misses (которое является целым числом, но хранится как строка), соединяемого со строковым литералом ".gif". Имеются шесть GIF-файлов с изображениями повешенного человечка в различных стадиях: image0.gif, image1.gif и так далее. Выражение JavaScript в кавычках генерирует HTML вида:


<IMG SRC="images\hang0.gif">

Затем идут строки:


<PRE><SERVER>write(client.answer)</SERVER></PRE>
You have used the following letters so far:
<SERVER>write(client.used)</SERVER>

Они выводят значение client.answer (слово, содержащее все правильно угаданные буквы) и все угаданные буквы.

Оставшаяся часть файла это стандартный HTML. Важно отметить, что атрибут ACTION тэга FORM специфицирует файл hangman.html как URL, по которому отправляется форма. Это значит, что при отправке формы страница перезагружается с новыми (специфицированными) значениями формы.

Посмотрим на hangman.js, пример исходного файла, написанного с использование только серверного JavaScript. В нём определены две функции, InitAnswer и Substitute, используемые приложением. Заметьте, что в файлах с серверным JavaScript тэги SERVER не используются.

Отладка Приложения Hangman


Вы можете поэкспериментировать с JavaScript, чтобы получить представление о разработке приложений. Одна из важнейших задач - отладка. Выберите в Application Manager приложение Hangman и Debug/Отладить. Application Manager открывает окно с приложением в одном фрэйме и с отладочной информацией - в другом, слева, как показано на Рисунке 4.3.

Рисунок 4.3   Отладка приложения Hangman

Заметьте, что URL будет теперь


http://
server.domain
/appmgr/debug.html?name=hangman

Вы можете сделать закладку на этот URL для удобства работы с Hangman. После этого не нужно будет выходить в Application Manager.

Попытайтесь добавить в Hangman функцию, проверяющую, является ли введённый пользователем символ буквой (а не числом или знаком пунктуации). Можете использовать функцию InitAnswer из hangman.js для старта. После компиляции и рестарта приложения используйте закладку для запуска приложения в режиме отладки.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 6
Служба Session Management Service

В этой главе рассматриваются объекты службы Session Management Service, доступные в серверном JavaScript и предназначенные для обеспечения совместного использования данных несколькими клиентскими запросами к приложению, несколькими пользователями одного приложения или даже несколькими приложениями на сервере.

Session Management Service это набор возможностей для управления созданием и уничтожением различных предопределённых объектов в ходе сессии сервера. Эти возможности предоставлены через объекты request, client, project и server.

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

В главе имеются следующие разделы:

Предопределённые Объекты. Обзор.


Предопределённые объекты request, client, project и server содержат данные, существующие в течение различных периодов времени и доступные различным клиентам и приложениям. Имеется единственный объект server, используемый всеми запущенными на сервере приложениями. Имеется отдельный объект project для каждого запущенного приложения. Имеется один объект client для каждого браузера (клиент), выполняющего доступ к данному отдельному приложению. Наконец, имеется отдельный объект request для каждого клиентского запроса с определённого клиента к определённому приложению. На Рисунке 6.1 показаны возможности относительной доступности различных объектов.

Рисунок 6.1   Относительная доступность объектов, обслуживающих сессию

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

Рисунок 6.2 может помочь представить, как все эти объекты соответствуют URL страницы Вашего приложения.

Рисунок 6.2   Предопределённые объекты в URL

На этом рисунке Joe запрашивает URL http://www.royalairways.com/videoapp/category.html, соответствующий странице приложения videoapp. Когда машина выполнения получает запрос, она использует уже существующий объект server, соответствующий www.royalairways.com и уже существующий объект project, соответствующий приложению videoapp. Машина создаёт объект client, соответствующий комбинации Joe и приложения videoapp. Если Joe уже получал доступ к другим страницам этого приложения, новый объект client использует любые сохранённые свойства. Наконец, машина создаёт новый объект request для конкретного запроса на страницу category.html.

Объект request


Объект request содержит данные, специфичные для текущего клиентского запроса. Они имеет самое короткое время существования из всех объектов. JavaScript конструирует новый объект request для каждого получаемого клиентского запроса; например, объект создаётся, когда

Машина выполнения JavaScript на сервере уничтожает объект request по окончании ответа на запрос (обычно предоставляя запрошенную страницу). Следовательно, типичный период существования объекта request - менее одной секунды.

ПРИМЕЧАНИЕ:

Вы не можете использовать объект request в начальной странице приложения. Эта страница запускается, когда приложение стартует на сервере. В этой точке нет объекта клиентского запроса, и поэтому нет доступного объекта request. О начальных страницах см. раздел "Установка Нового Приложения".

Резюме по объекту request см. а разделе "Предопределённые Объекты. Обзор.".

Свойства


В таблице перечислены предопределённые свойства объекта request. Некоторые из них соответствуют переменным окружения CGI. Вы можете получить доступ к этим и другим переменным окружения CGI через использование функции ssjs_getCGIVariable, описанной в разделе "Доступ к Переменным CGI".

Таблица 6.1  Свойства объекта request
Свойство Описание Пример значения

agent

Имя и версия клиентского программного обеспечения. Используйте это свойство для адресного применения расширенных возможностей некоторых браузеров.


Mozilla/1.1N (Windows; I; 32bit)

auth_type

Тип авторизации, если запрос защищён авторизацией какого-либо типа. Netscape web-серверы поддерживают базовую авторизацию доступа по HTTP. Соответствует переменной окружения CGI AUTH_TYPE.


basic

auth_user

Имя локального HTTP-пользователя web-браузера, если авторизация доступа HTTP была активирована для данного URL. Заметьте, что это не способ определения имени пользователя, получающего доступ к Вашей программе. Соответствует переменной окружения CGI REMOTE_USER.


vpg

ip

IP-адрес клиента. Может использоваться для авторизации или отслеживания доступа.


198.95.251.30

method

HTTP-метод, ассоциированный с запросом. Приложение может использовать его для определения соответствующего ответа на запрос. Соответствует переменной окружения CGI REQUEST_METHOD.


GET 
1


protocol

Уровень протокола HTTP, поддерживаемый клиентским программным обеспечением. Соответствует переменной окружения CGI SERVER_PROTOCOL.


HTTP/1.0

query

Информация из запрашивающей HTML-страницы; это информация в URL, идущая после знака "?". Соответствует переменной окружения CGI QUERY_STRING.


button1=on&button2=off

imageX

Горизонтальная позиция курсора, когда пользователь щёлкает на карте изображений/image map. Описано в разделе "Работа с Картами Изображений".


45

imageY

Вертикальная позиция курсора, когда пользователь щёлкает на карте изображений. Описано в разделе "Работа с Картами Изображений".


132

uri

Частичный URL запроса: с вырезанными протоколом, именем хоста и, возможно имеющимся, номером порта.


videoapp/add.html

1 Для HTTP 1.0 method имеет одно из значений: GET, POST или HEAD. Если Вы объявляете переменные верхнего уровня в серверном JavaScript, они имеют тот же период существования, что и свойства объекта request. Например, такое объявление существует только на протяжении текущего запроса:


var number = 42;

Помимо предопределённых свойств, Вы можете иметь в клиентском коде информацию, которая будет становиться свойствами объекта request. Это делается через использование элементов формы и кодирование свойств в URL запроса, как описано в разделе "Отправка Значений с Клиента на Сервер".

Хотя Вы можете создавать дополнительные свойства объекта request непосредственно операторами серверного JavaScript, производительность будет выше, если использовать переменные JavaScript. Создаваемые Вами свойства объекта request могут быть любого допустимого в JavaScript типа, включая ссылки на другие объекты JavaScript.

Помните, что период существования объекта request и, следовательно, его свойств, это период действия запроса. Если Вы сохраняете ссылку на другой объект в объекте request, то объект, на который ссылаются, уничтожается вместе с объектом request, если только объект, на который ссылаются, не имеет на себя другой действующей ссылки, прямой или косвенной, с объекта server или project.

Работа с Картами Изображений/Image Maps


Атрибут ISMAP тэга IMG указывает на серверную карту изображений. Если пользователь щёлкает на карте, горизонтальная и вертикальная позиции курсора высылаются на сервер. Свойства imageX и imageY возвращают эти координаты. Рассмотрим такой HTML:


<A HREF="mapchoice.html">
<IMG SRC="images\map.gif" HEIGHT=599 WIDTH=424 BORDER=0
   ISMAP ALT="SANTA CRUZ COUNTY">
</A>

Страница mapchoice.html получает свойства request.imageX и request.imageY на основе позиции курсора в момент щелчка мышью.

Объект client


Несколько браузеров-клиентов могут иметь одновременный доступ к приложению JavaScript. Объект client предоставляет метод для работы отдельно с каждым клиентом. Он также имеет технологию для отслеживания работы каждого браузера-клиента с приложением при наличии нескольких запросов.

Машина выполнения JavaScript на сервере конструирует объект client для каждой пары клиент/приложение. Браузер-клиент, соединённый с одним приложением, имеет другой объект client из того же самого браузера-клиента, соединённого с другим приложением. Машина выполнения конструирует новый объект client каждый раз, когда пользователь выполняет доступ к приложению; могут быть сотни и тысячи объектов client, активных одновременно.

ПРИМЕЧАНИЕ:

Вы не можете использовать объект client на начальной странице Вашего приложения. Эта страница начинает работу при старте приложения на сервере. В этот момент клиентского запроса нет, и поэтому нет также и доступного объекта client. Дополнительно см. раздел "Установка Нового Приложения".

Машина выполнения конструирует и уничтожает объект client для каждого клиентского запроса. В то же время, при обработке запроса машина выполнения сохраняет имена и значения свойств объекта client. Таким способом машина выполнения может конструировать новый объект client из сохранённых данных, если тот же самый пользователь вновь использует приложение, сделав следующий запрос. Таким образом, концептуально Вы можете представлять объект client как объект, действующий в течение сессии работы клиента с приложением.

JavaScript не сохраняет объекты client, не имеющие значений свойств. Поэтому, если приложению не нужны объекты client и оно не присваивает свойствам объекта client никаких значений, оно не выполняет никакой лишней работы.

У Вас имеются несколько различных опций: как и где машине выполнения сохранять свойства объекта client. Эти опции обсуждаются в разделе "Технология Обслуживания Объекта client".

Резюме по объекту client см. в разделе "Предопределённые Объекты. Обзор".

Свойства


В объекте client отсутствуют значения предопределённых свойств, поскольку он предназначен для хранения специфических для приложения данных. Операторы JavaScript могут присваивать специфичные для приложения свойства и значения объекту client. Хорошим примером свойства объекта client является ID-номер потребителя. Когда пользователь в первый раз вызывает приложение, оно обязано присвоить customer ID, как в следующем примере:


client.custID = getNextCustID();

Здесь определяемая в приложении функция getNextCustID используется для вычисления customer ID. Машина выполнения затем присваивает этот ID свойству custID объекта client.

После установки customer ID может оказаться неудобным требовать от пользователя ввода ID на каждой странице приложения. Однако без использования объекта client нет иной возможности ассоциировать корректный customer ID с последующими запросами клиента.

Из-за использования такой техники для обслуживания свойств объекта client при наличии нескольких клиентских запросов имеется одно важное ограничение для значений свойств объекта client. Машина выполнения JavaScript не сервере конвертирует значения всех свойств объекта client в строки.

Не присваивайте объект в качестве значения свойства объекта client. Если Вы это сделаете, машина выполнения конвертирует этот объект в строку; после этого Вы не сможете больше работать с этим объектом. Если значение клиентского свойства представляет другой тип данных, например, number, Вы обязаны конвертировать строковое значение перед тем как его использовать. Например, Вы можете создать целочисленное свойство объекта client:


client.totalNumber = 17;

Затем Вы можете использовать parseInt для инкремента значения totalNumber:


client.totalNumber = parseInt(client.totalNumber) + 1;

Аналогично Вы можете создать Булево свойство объекта client:


client.bool = true;

А затем проверить его:


if (client.bool == "true")
   write("It's true!");
else
   write("It's false!");

Заметьте, что условное выражения сравнивает client.bool со строкой "true". Можно использовать эту технику для обработки Булева выражения. Например, для отрицания Булева свойства используйте такой код:


client.bool = (client.bool == "true") ? false : true;

Хотя Вы можете работать непосредственно со свойствами объекта client, Вы выполняете таким образом лишнюю работу. Если Вы повторно используете значение свойства объекта client, предусмотрите использование переменных верхнего уровня JavaScript. Перед использованием свойства объекта client, присвойте его переменной. Когда Вы закончите работу с этой переменной, присвойте результат обратно соответствующему свойству объекта client. Эта техника несколько повысит производительность среды.

Как отмечено ранее, Вы не можете сохранять ссылки на другие объекты в объекте client. Вы можете, однако, сохранять ссылки на объекты в объектах project или server. Если у вас имеется свойство, ассоциированное с клиентом, принимающее значения объекта, создайте массив, индексированный по клиентским ID, и храните ссылку на массив в объекте project или server. Вы можете использовать этот массив для хранения значений объекта, ассоциированного с клиентом. Рассмотрим следующий код:


if client.id == null
   client.id = ssjs_generateClientID();
project.clientDates[client.id] = new Date();

Здесь использована функция ssjs_generateClientID, описанная далее, для создания уникального ID для данного объекта client. Она использует этот ID как индекс массива clientDates в объекте project и сохраняет новый объект Date в этом массиве, ассоциированном с текущим объектом client.

Уникальная Ссылка на Объект client


Для некоторых приложений может понадобиться сохранять информацию, специфическую для пары клиент/приложение, в объектах project или server. Два обычных примера - сохранение соединения с БД между клиентскими запросами (описано в Главе 8, "Соединение с Базой Данных") или хранение специального объекта, имеющего такой же период существования, что и предопределённый объект client, и содержащего значения объектов (описано в разделе "Создание Специального Объекта client").

В этих случаях Вам необходим способ уникально обратиться к паре клиент/приложение. JavaScript имеет для этого две функции, ssjs_getClientID и ssjs_generateClientID. Они не принимают аргументов; обе возвращают уникальную строку, которую вы можете использовать для идентификации пары.

При каждом вызове ssjs_generateClientID машина выполнения возвращает новый идентификатор. Исходя из этого, если Вы используете эту функцию и Вам нужен идентификатор, существующий дольше, чем отдельный клиентский запрос, Вам нужно сохранить этот идентификатор, возможно, как свойство объекта client. Пример использования этой функции см. в разделе "Совместное Использование Массива Пула Соединений".

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

Альтернативой может стать использование функции ssjs_getClientID. Если Вы применяете одну из этих серверных технологий для объекта client, машина JavaScript генерирует и использует идентификатор для доступа к информации определённой пары клиент/приложение. (О работе с объектом client см. раздел "Технология Работы с Объектом client").

При использовании этих технологий ssjs_getClientID возвращает идентификатор, используемый машиной выполнения. Каждый раз при вызове этой функции из определённой пары клиент/приложение Вы будете получать тот же самый идентификатор. Соответственно, Вам нет необходимости сохранять идентификатор, возвращаемый функцией ssjs_getClientID. Однако, если Вы используете другую технику, эта функция возвращает "undefined"; тогда необходимо использовать функцию ssjs_generateClientID.

Если Вам нужен идентификатор и Вы используете серверную технологию, возможно, понадобится использовать функцию ssjs_getClientID. Тогда Вам не нужно будет самостоятельно сохранять идентификатор и отслеживать его использование; машина выполнения сделает это за Вас. При использовании клиентской техники, однако, Вы не сможете применять функцию ssjs_getClientID; тогда Вы обязаны использовать функцию ssjs_generateClientID.

Создание Специального Объекта client


Как уже было сказано ранее, свойства предопределённого объекта client могут иметь только строковые значения. Это ограничение может представлять проблему для работы некоторых приложений. Например, Вашему приложению нужен объект, который существует столько же, сколько предопределённый объект client, но который может принимать в качестве значений свойств объекты или другие типы данных. В этом случае Вы можете создать Ваш собственный объект и сохранить его как свойство объекта client.

В этом разделе приведён пример создания такого объекта. Можете включить этот код как файл JavaScript в Ваше приложение. Затем в начале страницы, на которой нужно использовать этот объект, введите следующий оператор:


var customClient = getCustomClient()

(Разумеется, можно использовать другое имя переменной.) Если это первая страница, запрашивающая данный объект, метод getCustomClient создаёт новый объект. На других страницах он будет возвращать уже существующий объект.

Этот код сохраняет массив всех специальных объектов client, определённых в приложении как значения свойства customClients предопределённого объекта project. Он сохраняет индекс в этом массиве и строковое значение свойства customClientID предопределённого объекта client. Кроме того, этот код использует блокировку/lock, хранимую в свойстве customClientLock объекта project, чтобы гарантировать надёжность доступа к этому массиву. О блокировании см. раздел "Безопасное Совместное Использование Объектов с Блокировкой".

Переменная timeout в функции getCustomClient жёстко кодирует период окончания действия этого объекта. Если Вам нужен другой период окончания действия, специфицируйте другое значение для этой переменной. Независимо от используемого периода действия, Вы должны вызывать метод expiration предопределённого объекта client для установки его срока окончания действия в то же значение, какое специфицировано Вами для специального объекта. О работе этого метода см. раздел "Период Существования Объекта client".

Для удаления всех закончивших работу специальных объектов приложения вызовите следующую функцию:


expireCustomClients()

Это всё, что нужно сделать! Если Вы используете этот код, предопределённые объекты client и project имеют следующие дополнительные свойства, которые Вы не должны изменять:

Вы можете специализировать класс путём изменения его методов onInit и onDestroy. Как показано здесь, эти методы - это просто основа. Вы можете добавить код для изменения действий при создании и уничтожении объекта.

Вот этот код:


// Эта функция создаёт новый специальный объект client или запрашивает существующий.

function getCustomClient()
{
   // ==========> Измените жёстко кодированный период ожидания <==========
   // Примечание: Не забудьте установить окончание обслуживания client-статуса
   // в то же самое значение, что и использованное ниже в вызове
   // client.expiration. Это даст возможность индексу отключать все предопределённые
   // объекты client в то же время, которое содержится в объекте project.
   var timeout = 600;
   var customClient = null;
   var deathRow = null;
   var newObjectWasCreated = false;


   var customClientLock = getCustomClientLock();
   customClientLock.lock();
   var customClientID = client.customClientID;
   if ( customClientID == null ) {
      customClient = new CustomClient(timeout);
      newObjectWasCreated = true;
   }

   else {
      var customClients = getCustomClients();
       customClient = customClients[customClientID];
       if ( customClient == null ) {
         customClient = new CustomClient(timeout);
         newObjectWasCreated = true;
      }
      else {
         var now = (new Date()).getTime();
         if ( customClient.expiration <= now ) {
            delete customClients[customClientID];
            deathRow = customClient;

            
customClient = new CustomClient(timeout);
             newObjectWasCreated = true;
         }
         else {
             customClient.expiration = (new Date()).getTime() +
               timeout*1000;
         }
      }
   }
   if ( newObjectWasCreated )
       customClient.onInit();
   customClientLock.unlock();

   if ( deathRow != null )
       deathRow.onDestroy();
   return customClient;
}

// Функция для удаления старых специальных объектов client.


function expireCustomClients()
{
   var customClients = getCustomClients();
   var now = (new Date()).getTime();
   for ( var i in customClients ) {
      var clientObj = customClients[i];
      if ( clientObj.expiration <= now ) {
         var customClientLock = getCustomClientLock();
         customClientLock.lock();
         if ( clientObj.expiration <= now ) {
            delete customClients[i];
         }
         else {
            clientObj = null;
         }
         customClientLock.unlock()
         if ( clientObj != null )
            clientObj.onDestroy();
      }   }   }

// Не вызывайте эту функцию явно. 
// Она используется методами getCustomClient и expireCustomClients.
function getCustomClientLock()
{
    if ( project.customClientLock == null ) {
      project.lock()
      if ( project.customClientLock == null )
         project.customClientLock = new Lock()
      project.unlock()
   }
   return project.customClientLock
}

// Не вызывайте эту функцию явно. 
// Она используется методами getCustomClient и expireCustomClients.
function getCustomClients()
{
    if ( project.customClients == null ) {
      project.lock()
      if ( project.customClients == null )
         project.customClients = new Object()
      project.unlock()
   }
   return project.customClients
}

// Конструктор класса CustomClient. Не вызывайте его явно.
// Используйте вместо него функцию getCustomClient.
function CustomClient(seconds)
{
   var customClients = getCustomClients();
   var customClientID = ssjs_generateClientID();

   this.onInit = CustomClientMethod_onInit;
   this.onDestroy = CustomClientMethod_onDestroy;
   this.expiration = (new Date()).getTime() + seconds*1000;>

   client.customClientID = customClientID;

   customClients[customClientID] = this;
}

// Если нужно специализировать, переопределите следующие две функции.
function CustomClientMethod_onInit()
{
   // ==========> Добавьте код инициализации Вашего объекта <==========
   // Этот метод вызывается при блокировке.
}

function CustomClientMethod_onDestroy()
{
   // ==========> Добавьте код очистки Вашего объекта <==========
   // Этот метод не вызывается из блокировки.
}

Объект project


Объект project содержит глобальные данные приложения и предоставляет метод для совместного использования информации клиентами, выполняющими доступ к приложению. JavaScript конструирует новый объект project, когда приложение стартует при использовании Application Manager. Каждый клиент, получающий доступ к приложению, использует один и тот же объект project. Резюме по объекту project см. в разделе "Предопределённые Объекты. Обзор.".

В отличие от предыдущих релизов, в этом релизе машина выполнения JavaScript не создаёт и не уничтожает объект project для каждого запроса. Если Вы остановили работу приложения, объект project этого приложения уничтожается. Новый объект project создаётся для приложения, когда оно стартует снова. Типичный период существования объекта project - дни или недели.

JavaScript конструирует набор объектов project для каждого Netscape HTTP-процесса, запущенного на сервере. JavaScript конструирует объект project для каждого приложения, запущенного на каждом отдельном сервере. Например, если один сервер запущен на порте 80, а другой - на порте 142 на той же самой машине, JavaScript конструирует отдельный набор объектов project для каждого процесса.

Свойства


У объекта project нет предопределённых свойств, поскольку он предназначен для содержания специфических для приложений данных, доступных для многих клиентов. Вы можете создавать свойства любого верного типа JavaScript, включая ссылки на другие JavaScript-объекты. Если Вы храните ссылку на другой объект в объекте project, машина выполнения не уничтожает объект, на который ссылаются, по окончании клиентского запроса, в котором объект создаётся. Объект доступен и в течение последующих запросов.

Хороший пример свойства объекта project - следующий доступный ID потребителя. Приложение может использовать это свойство для отслеживания последующих присваиваемых IDs. Любому клиенту, получающему доступ к приложению и не имеющему ID потребителя, присваивается этот ID, и его значение будет увеличиваться для каждого первоначального доступа.

Помните, что объект project существует только в течение периода работы приложения на сервере. Когда приложение останавливается, объект project уничтожается вместе со всеми значениями его свойств. Поэтому, если у Вас имеются данные приложения, которые нужно сохранять постоянно, их необходимо сохранять в БД (см. Часть 3, "LiveWire Database Service") или в файле на сервере (см. "Служба Файловой Системы").

Совместное Использование Объекта project


Для каждого приложения имеется только один объект project. Таким образом, код, исполняемый в любом запросе к данному приложению, может получить доступ к тому же объекту project. Поскольку сервер является многопоточным, могут иметься несколько активных запросов в данный момент времени, либо от одного и того же клиента, либо от разных клиентов.

Для поддержания целостности данных Вы обязаны гарантировать исключительный доступ к свойству объекта project при изменении значения свойства. Неявной блокировки, как это было в предыдущих релизах, больше нет; Вы обязаны запрашивать исключительный доступ. Легче всего сделать это через использование методов lock и unlock объекта project. См. раздел "Безопасное Совместное Использование Объектов с Помощью Блокировки.".

Объект server


Объект server содержит глобальные данные для всего сервера в целом и предоставляет метод для обеспечения совместного использования информации разными приложениями, работающими на сервере. Объект server также автоматически инициализируется информацией о сервере. Резюме по объекту server см. в разделе "Предопределённые Объекты. Обзор.".

Машина выполнения JavaScript конструирует новый объект server, когда сервер стартует, и уничтожает объект server, когда сервер останавливается. Каждое приложение, запущенное на сервере, использует один и тот же объект server.

JavaScript конструирует объект server для каждого Netscape HTTPD-процесса (на сервере), запущенного на машине. Например, может иметься серверный процесс на порте 80 и другой - на порте 8080. Это совершенно отдельные серверные процессы, и JavaScript конструирует объект server для каждого из них.

Свойства


В следующей таблице описаны свойства объекта server.

Таблица 6.2  Свойства объекта server
Свойство Описание Пример

hostname

Полное имя хоста сервера, включая номер порта


www.netscape.com:85

host

Имя сервера, субдомена и домена


www.netscape.com

protocol

Используемый протокол соединения


http:

port

Используемый номер порта сервера; по умолчанию 80 для HTTP


85

jsVersion

Версия сервера и платформа


3.0 WindowsNT

Например, Вы можете использовать свойство jsVersion для обусловливания возможностей на базе серверной платформы (или версии), на которой приложение работает, как показано здесь:


if (server.jsVersion == "3.0 WindowsNT")
   write ("Application is running on a Windows NT server.");

Помимо этих автоматически инициализируемых свойств, Вы можете создавать свойства для хранения данных, совместно используемых многими приложениями. Свойства могут иметь любой допустимый в JavaScript тип, включая ссылки на другие JavaScript-объекты. Если Вы сохраняете ссылку на другой объект в объекте server, машина выполнения не разрушает объект, на который ссылаются, по окончании запроса, в ходе которого он (объект server) был создан. Объект остаётся доступным для последующих запросов.

Как и случае с объектом project, объект server имеет ограниченный период существования. Когда web-сервер останавливается, объект server разрушается вместе со всеми значениями свойств. Поэтому, если у Вас имеются данные приложения, которые нужно сохранять постоянно, их необходимо сохранять в БД (см. Часть 3, "LiveWire Database Service") или в файле на сервере (см. "Служба Файловой Системы").

Совместное Использование Объекта server


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

Также Вы обязаны гарантировать, что имеется исключительный доступ к свойству объекта server, когда изменяется значение этого свойства. Неявной блокировки, как это было в предыдущих релизах, теперь нет; Вы обязаны запрашивать исключительный доступ. Легче всего сделать это через использование методов lock и unlock объекта server. См. раздел "Безопасное Совместное Использование Объектов с Помощью Блокировки".

Технология Обслуживания Объекта client


Объект client ассоциирован как с определённым приложением, так и с определённым клиентом. Как было сказано в разделе "Объект client", машина выполнения создаёт новый объект client всякий раз при поступлении нового запроса от клиента к серверу. Однако целью является сохранение свойств объекта client от одного запроса до следующего. Для этого машине выполнения нужно сохранить свойства объекта client между запросами.

Есть два основных подхода при работе со свойствами объекта client: можно работать с ними на стороне клиента или на сервере. Эти два вида клиентской техники либо сохраняют имена свойств и их значения непосредственно в куках на клиенте, либо в URLs на генерируемой HTML-странице. Все три вида серверной техники сохраняют имена свойств и их значения в структуре данных в памяти сервера, но различаются по используемой для индексирования структуры этих данных схеме.

Вид техники выбирается, когда Вы используете JavaScript Application Manager для инсталяции или модификации приложения, как указано в разделе "Установка Нового Приложения". Это даёт Вам (или менеджеру сайта) возможность изменять технику обслуживания без перекомпилирования приложения. Однако поведение Вашего приложения может меняться в зависимости от действующей техники обслуживания объекта client, как описано в следующих разделах. Обязательно объясните Вашему менеджеру сайта, от какого вида техники зависит работа Вашего приложения. Иначе менеджер может изменить эти установки и нарушить работу Вашего приложения.

Поскольку некоторые виды этой техники сохраняют информацию в структуре данных на сервере или в куки-файле на клиенте, машина выполнения JavaScript дополнительно должна определять, когда избавиться от этих свойств. В разделе "Период Существования Объекта client" рассматривается, как машина выполнения определяет это, и описываются методы, которые можно использовать для изменения этого поведения.

Сравнение Видов Техники Обслуживания Объекта client


Каждый вид техники имеет свои преимущества и недостатки, и то, что является недостатком в одной ситуации, может оказаться преимуществом в другой. Вам необходимо выбрать вид техники, наиболее подходящей для Вашего приложения. Виды техники описаны более детально в последующих разделах; в этом разделе даётся общее сравнение.

В таблице выполнено общее сравнение клиентской и серверной техники.

Таблица 6.3  Сравнение клиентской и серверной техники обслуживания
Серверная Клиентская

1.

Не ограничивается количество хранимых свойств или занимаемое ими пространство.

Ограничения на свойства.

2.

Занимает дополнительную память сервера в промежутке между клиентскими запросами.

Не использует дополнительную память сервера в промежутке между клиентскими запросами.

Эти различия относительны. Отсутствие ограничения на количество и размер свойств может быть и недостатком, и преимуществом. Вообще нужно ограничивать размер данных приложения, доступных через Internet, чтобы не перегрузить память Вашего сервера. Иначе лучше использовать клиентскую технику. Однако, если у вас приложение для Intranet (внутренней сети), где нужно хранить большой объём данных, можно допустить это на сервере, так как количество клиентов ограничено.

3.

Свойства хранятся в памяти сервера и теряются при рестарте сервера или приложения.

Свойства не хранятся в памяти сервера и не теряются при рестарте сервера.

Если свойства являются настройками пользователя, Вам может понадобиться сохранить их между рестартами сервера; если они относятся к отдельной сессии, может понадобиться, чтобы они были стёрты.

4.

Не увеличивает или незначительно увеличивает сетевой трафик.

Увеличивает сетевой трафик.

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

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

На Рисунке 6.3 и на Рисунке 6.4 видно, какая информация хранится при использовании каждого вида техники, где она хранится и передаётся ли по сети. На Рисунке 6.3 дана информация для клиентской техники.

Рисунок 6.3   Клиентская техника


На Рисунке 6.4 дана информация для серверной техники.

Рисунок 6.4   Серверная техника

Имеются некоторые общие для видов (серверной и клиентской) техники вопросы. Для обоих типов техники, использующих куки, браузер обязан поддерживать протокол Netscape cookie protocol. В обоих случаях, когда браузер на клиентской машине закрывается, информация сохраняется в cookie-файле на клиентской машине. В других случаях ограничений нет.

Техника серверных кук создаёт единственную куку для идентификации соответствующего объекта client. В противоположность этому, техника клиентских кук создаёт отдельную куку для каждого свойства объекта client. На технику клиентских кук, следовательно, скорее повлияет ограничение в 20 кук на приложение.

В технике клиентских кук свойства объекта client высылаются клиенту, когда высылается первая часть HTML-страницы. Если Вы изменяете позднее значения свойств объекта client при выполнении действий на странице, эти изменения не отсылаются клиенту и теряются. Это ограничение не действует для другой техники.

Для обеих техник, использующих кодирование в URL, если Ваше приложение конструирует URL на этапе выполнения или использует функцию redirect, необходимо либо вручную присоединять свойства объекта client, которые должны быть сохранены, либо использовать addClient, чтобы машина выполнения присоединила эти свойства. Хотя присоединение свойств не является обязательным для других техник, Вам может понадобиться сделать это, чтобы изменение техники не нарушило работу Вашего приложения.

Кроме того, при использовании техник кодирования URL, как только браузер перейдёт на страницу за пределами приложения или даже отправит форму приложению с использованием метода GET, все свойства объекта client будут утеряны. Свойства не теряются в такой ситуации для других видов техники. Ваш выбор техники частично определяется тем, должны ли существовать свойства объекта client в такой ситуации.

Ваш выбор используемой техники опирается на требования Вашего приложения. Техника клиентских кук не использует дополнительной памяти сервера (как при серверной технике) и высылает информацию только один раз для страницы (в противоположность клиентской технике кодирования URL). Эти факты могут сделать использование техники клиентских кук предпочтительным для больших Internet-приложений. Однако в некоторых случаях другая техника может оказаться более подходящей. Например, серверный IP-адрес работает быстрее, не увеличивая сетевого трафика. Можно использовать это для приложений Вашей Intranet, для которых скорость работы является критичной.

Клиентская Техника


Есть два вида клиентской техники:

Сравнение этих видов техники см. в разделе "Сравнение Видов Техники Обслуживания Объекта сlient".

Когда приложение использует клиентские виды техники, машина выполнения кодирует свойства объекта client в ответ на клиентский запрос в шапке/header ответа (для клиентской куки) или в URLs в теле ответа (для клиентского кодирования URL).

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

Использование Клиентской Куки/Cookie


В технике клиентских кук машина выполнения JavaScript на сервере использует протокол Netscape cookie protocol для передачи клиенту свойств объекта client и их значений. Она создаёт по одной куке для каждого свойства объекта client. Свойства высылаются клиенту один раз в шапке/header ответа генерируемой HTML-страницы. Netscape cookie protocol описан в книге Клиентский JavaScript. Руководство .

Для исключения конфликтов с другими куками, которые Вы можете создать в Вашем приложении, машина выполнения создаёт имя куки, добавляя NETSCAPE_LIVEWIRE. перед началом имени свойства объекта client. Например, если client имеет свойство custID, машина выполнения создаёт куку под названием NETSCAPE_LIVEWIRE.custID. Когда информация куки высылается клиенту, машина выполнения делает всё необходимое кодирование специальных символов в значении свойства, как описано в книге Клиентский JavaScript. Руководство .

Иногда Вашему приложению может понадобиться взаимодействие операторов JavaScript на сервере и на стороне клиента. Поскольку это вид техники высылает клиенту свойства объекта client как куки, Вы можете использовать это как способ облегчить это взаимодействие. См. дополнительно "Взаимодействие Между Сервером и Клиентом".

При использовании этой техники машина выполнения сохраняет свойства объекта client, когда она в первый раз очищает внутренний буфер, содержащий сгенерированную HTML-страницу. Исходя из этого, для того чтобы предотвратить потерю любой информации, Вы должны как можно раньше присвоить значения всем свойствам объекта client в скриптах на каждой странице. В особенности Вы должны гарантировать, что свойства объекта client будут высылаться перед тем как (1) машина выполнения сгенерирует 64KB содержимого HTML-страницы (она автоматически очищает буфер вывода в этой точке), (2) Вы вызовете функцию flush для очистки буфера вывода или (3) Вы вызовете функцию redirect для изменения клиентских запросов. Дополнительно см. разделы "Очистка Буфера Вывода" и "Процессинг Времени Выполнения на Сервере".

По умолчанию, когда Вы используете технику клиентских кук, машина выполнения не устанавливает явно время окончания срока действия кук. В этом случае куки заканчивают работать, когда пользователь закрывает браузер. (Это поведение по умолчанию для всех кук.) Как указано в разделе "Период Существования Объекта client", Вы можете использовать метод expiration объекта client для изменения срока окончания действия. Если Вы используете client.expiration, машина выполнения устанавливает соответствующий срок окончания работы куки в cookie-файле.

При использовании техники клиентских кук метод client.destroy уничтожает все значения свойств объекта client, но не влияет на то, что хранится в cookie-файле на клиентской машине. Не используйте для удаления кук из cookie-файла или памяти браузера метод client.destroy; вместо него используйте client.expiration с аргументом 0 секунд.

В целом Netscape-куки имеют нижеследующие ограничения. Эти ограничения применяются тогда, когда Вы используете куки для хранения свойств объекта client:

Использование Клиентского Кодирования URL


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

Размер строки URL ограничен 4KB. Следовательно, когда Вы используете клиентское кодирование URL, общий размер имён свойств и их значений не может превышать 4KB. Любая информация свыше лимита 4KB будет усекаться.

Если Вы генерируете URLs динамически или используете функцию redirect, Вы можете добавлять свойства объекта client или другие свойства к URL. Когда Вы вызываете redirect или генерируете URL, компилятор не присоединяет автоматически свойства объекта client. Если присоединение необходимо, используйте функцию addClient. См. раздел "Присоединение Свойств Объекта client к URL Вручную".

В технике клиентского кодирования URL значения свойств добавляются к URL по мере обработки этих URL. Нужно следить, чтобы Ваши URL имели одинаковые свойства и значения. Например, рассмотрим код:


<SERVER>
...
client.numwrites = 2;
write (addClient(
   "<A HREF='page2.html'>Some link</A>"));
client.numwrites = 3;
write (addClient(
   "<A HREF='page3.html'>Another link</A>"));
...
</SERVER>

Когда машина выполнения обрабатывает первый оператор write, она использует 2 как значение свойства numwrites, а при обработке второго оператора write она использует в качестве значения 3.

Итак, если Вы используете метод client. destroy в середине страницы, только ссылки, шедшие на странице до вызова этого метода получат значения, присоединённые к URL. Те же, которые идут после вызова этого метода, не имеют присоединённых значений. Следовательно, значения свойств объекта client передаются на некоторые страницы, но не на все. Это может быть нежелательно.

Если страница имеет ссылку на URL за пределами Вашего приложения, Вам не понадобится присоединять клиентский статус. Тогда не используйте статическую строку в качестве значения HREF. Вместо этого вычисляйте значение. Это предотвратит автоматическое присоединение машиной выполнения клиентского статуса к URL. Например, у вас имеется ссылка:


<A HREF="mailto:me@royalairways.com">

Машина выполнения присоединяет свойства объекта client. Чтобы этого не происходило, используйте очень похожую ссылку:


<A HREF=`"mailto:me@royalairways.com"`>

При этой технике объект client не перестаёт действовать, поскольку существует только в URL-строке, находящейся на клиенте. Следовательно, метод client.expiration не производит никаких действий.

При клиентском кодировании URL Вы теряете все свойства объекта client, когда отправляете форму, используя метод GET, и когда выполняете доступ к другому приложению. Ещё раз - Вам может быть нужно или не нужно терять эти свойства, в зависимости от потребностей Вашего приложения.

В отличие от техники клиентских кук, клиентское кодирование URL не требует ни поддержки web-браузером протокола Netscape cookie, ни записи информации на клиентской машине.

Серверная Техника


Есть три вида серверной техники:

Сравнение разных видов техники см. в разделе "Сравнение Видов Техники Обслуживания Объекта сlient".

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

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

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

Недостатком является, разумеется, то, что эти виды техники используют память сервера в промежутке между клиентскими запросами. Для приложений, используемых большим количеством потребителей, это может иметь важное значение. Конечно, это можно также рассматривать и как преимущество, так как Вы можете сохранять столько информации, сколько необходимо.

Использование IP-Адреса


Техника с использованием IP-адреса индексирует структуру данных на основе IP-адресов приложения и клиента. Эта простая техника является также и самой быстрой, поскольку вообще не требует отправки информации клиенту. Так как индекс базируется на IP-адресах приложения и клиента, эта техника создаёт отдельный индекс для каждой пары приложение/клиент, работающей на сервере.

Эта техника хорошо работает, когда все клиенты имеют фиксированные IP-адреса. Она работает ненадёжно, если клиент не имеет гарантированно фиксированного IP-адреса, например, если клиент использует протокол Dynamic Host Configuration Protocol (DHCP) или провайдера Internet, который динамически размещает IP-адреса. Эта техника также не работает у клиентов, использующих прокси-сервер, поскольку все пользователи прокси сообщают один и тот же IP-адрес. Поэтому данная техника используется в основном только для приложений Intranet.

Использование Серверных Кук


Техника серверных кук использует длинное уникальное имя, генерируемое машиной выполнения для индексации структуры данных на сервере. Машина выполнения использует протокол Netscape cookie для хранения генерируемого имени как куки/cookie на клиенте. Она не сохраняет имена и значения свойств как куки. Поэтому данная техника создаёт одну куку, в то время как клиентская техника кук создаёт отдельную куку для каждого свойства объекта client.

Сгенерированное имя отсылается клиенту только один раз в шапке/header HTML-страницы. Вы можете получить доступ к этому имени через функцию ssjs_getClientID, описанную в разделе "Уникальное Обращение к Объекту client". Эта техника использует тот же самый cookie-файл, что и техника клиентских кук; эти виды техники отличаются тем, что информация сохраняется в cookie-файле. Протокол Netscape cookie protocol описан в книге Клиентский JavaScript. Руководство .

Итак, поскольку клиенту отсылается только генерируемое имя, а не реальные имена и значения свойств, не имеет значения, где на Вашей странице изменяются свойства объекта client. Это контрастирует с техникой клиентских кук.

По умолчанию машина выполнения устанавливает период действия серверной структуры данных в 10 минут и не устанавливает срок действия кук, отправляемых клиенту. Как указано в разделе "Период Существования Объекта client", Вы можете использовать метод expiratio объекта client для изменения срока действия и для установки периода действия куки.

При использовании серверной куки метод client.destroy уничтожает все значения свойств объекта client.

В общем, Netscape-куки имеют ограничения, перечисленные в разделе "Использование Клиентских Кук". Если Вы используете серверные куки, эти ограничения вряд ли будут достигнуты, так как создаётся только одна кука (содержащая индекс).

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

Использование Серверной Кодировки URL


Техника серверного кодирования URL использует длинное уникальное имя, генерируемое машиной выполнения для индексации структуры данных на сервере. В этом случае, вместо того чтобы сделать это генерируемое имя клиентской кукой, сервер присоединяет имя к каждому URL на генерируемой HTML-странице. Следовательно, имя высылается столько раз, сколько имеется ссылок на генерируемой HTML-странице. (Имена и значения свойств не присоединяются к URLs, только генерируемое имя.) Ещё раз: Вы можете получить доступ к этому генерируемому имени с помощью функции ssjs_getClientID, описанной в разделе "Уникальное Обращение к Объекту client".

Если Вы генерируете URLs динамически или используете функцию redirect, Вы можете добавлять свойства к URL. Поэтому, когда Вы вызываете redirect или генерируете URL, компилятор не присоединяет индекс автоматически. Если Вы хотите оставить индекс для свойств объекта client, используйте функцию addClient. См. также "Присоединение Свойств Объекта client к URL Вручную".

Если Ваша страница имеет ссылку на URL вне Вашего приложения, Вам может и не понадобиться присоединение клиентского индекса. Тогда не используйте статическую строку как значение атрибута HREF. Вместо этого вычисляйте это значение. Это предотвратит автоматическое присоединение машиной выполнения клиентского индекса к URL. Например, у Вас имеется ссылка:


<A HREF="mailto:me@royalairways.com">

В это случае машина выполнения присоединит индекс объекта client. Чтобы этого не происходило, используйте очень похожую ссылку:


<A HREF=`"mailto:me@royalairways.com"`>

При серверном кодировании URL вы теряете идентификатор объекта client (и, соответственно, свойства и их значения) при отправке формы с методом GET. Вы можете терять или не терять эти свойств, в зависимости от потребностей Вашего приложения.

Период Существования Объекта client


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

Вызов Окончания Действия Свойств Объекта client


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

Таблица 6.4  Срок действия по умолчанию свойств объекта client на основе вида используемой техники
Для данного вида техники... Свойства Объекта client...

клиентская кука

Перестают действовать, когда браузер закрывается.

клиентское кодирование URL

Никогда не перестают действовать.

серверная кука

Удаляются из структуры данных на сервере через 10 минут. Кука на клиенте перестаёт действовать при выходе из браузера. Свойства объекта client более не доступны, как только структура данных удаляется или браузер закрывается.

серверное кодирование URL

Удаляются из структуры данных на сервере через 10 минут.

серверный IP-адрес

Удаляются из структуры данных на сервере через 10 минут.

Приложение может управлять периодом ожидания JavaScript перед зачисткой свойств объекта client. Для изменения величины этого периода используйте метод expiration, как в следующем примере:


client.expiration(30);

В ответ на это вызов машина выполнения зачищает свойства объекта client по прошествии 30 секунд. Для серверной техники этот вызов заставит сервер удалить свойства объекта из структур данных через 30 секунд. Для этих двух видов техники такой вызов устанавливает окончание срока действия через 30 секунд.

Если объект client перестаёт действовать, когда имеется активный клиентский запрос с использованием этого объекта, машина выполнения ждёт окончания этого запроса, прежде чем уничтожить объект client.

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

Уничтожение Объекта client


Приложение может явно уничтожать объект client методом destroy:


client.destroy();

Когда приложение вызывает destroy, JavaScript удаляет все свойства из объекта client.

Если Вы используете технику клиентских кук для работы с объектом client, метод destroy уничтожает все значения свойств объекта client, но не влияет на то, что хранится в клиентском cookie-файле. Чтобы удалить и значения свойств из этого cookie-файла, не используйте метод destroy; вместо него используйте expiration с аргументом 0 секунд.

Если Вы используете технику клиентского кодирования URL для работы с объектом client, метод destroy удаляет все свойства объекта client. Ссылки на странице до вызова destroy оставляют свойства объекта client в своих URL, а ссылки, расположенные после вызова метода, не имеют свойств. Поскольку маловероятно, что Вам понадобится, чтобы  только некоторые URL страницы содержали свойства объекта client, Вы, вероятно, должны будете вызывать destroy либо вверху, либо внизу страницы, когда используете работу с клиентскими URL. См. также "Использование Клиентского Кодирования URL".

Присоединение Свойств Объекта client к URL Вручную


При использовании кодирования URL на клиенте или на сервере для работы с объектом client машина выполнения обычно должна сохранять соответствующую информацию (имена и значения свойств объекта client или индекс серверной структуры данных) во всех URL, высылаемых клиенту, вне зависимости от того, являются ли эти URL как статический HTML или были сгенерированы операторами серверного JavaScript.

Машина выполнения автоматически присоединяет соответствующую информацию к гиперссылкам HTML, находящимся вне тэгов SERVER. Так, например, предположим, что Ваша HTML-страница содержит следующие операторы:


<HTML>
For more information, contact
<A HREF="http://royalairways.com/contact_info.html">
Royal Airways</a>
...
</HTML>

Если приложение использует кодирование URL для объекта client, машина выполнения автоматически присоединит client -информацию в конец URL. Вы не должны ничего делать специально для поддержки этого поведения.

Однако ваше приложение может использовать функцию write для динамической генерации оператора HTML, содержащего URL. Вы можете также использовать функцию redirect для старта нового запроса. Когда Вы используете операторы серверного JavaScript для добавления URL к генерируемой HTML-странице, машина выполнения предполагает, что Вы специфицировали полный URL для отправки в нужном Вам виде. Она не присоединяет автоматически клиентскую информацию даже при использовании кодирования URL для работы с объектом client. Если Вам нужно присоединить клиентскую информацию, Вы обязаны сделать это сами.

Вы используете функцию addClient для добавления вручную соответствующей client -информации. Эта функция принимает URL и возвращает новый URL с присоединённой информацией. Например, предположим, что контактный URL варьируется в зависимости от значения свойства client.contact. Вместо вышеприведённого HTML Вы можете ввести следующее:


<HTML>
For more information, contact
<server>
if (client.contact == "VIP") {
   write ("<A HREF='http://royalairways.com/vip_contact_info.html'>");
   write ("Royal Airways VIP Contact</a>");
}
else {
   write ("<A HREF='http://royalairways.com/contact_info.html'>");
   write ("Royal Airways</a>");
}
</server>
...
</HTML>

Теперь машина выполнения не присоединяет свойства объекта client к URL. Если Вы используете один из видов техники кодирования URL для работы с объектом client, может возникнуть проблема. Тогда, если Вы хотите отправить свойства объекта client с этим URL, используйте такой код:


<HTML>
For more information, contact
<server>
if (client.contact == "VIP") {
   write (addClient(
      "<A HREF='http://royalairways.com/vip_contact_info.html'>"));
   write ("Royal Airways VIP Contact</a>");
}
else {
   write (addClient(
       "<A HREF='http://royalairways.com/contact_info.html'>"));
   write ("Royal Airways</a>");
}
</server>
...
</HTML>

Также всякий раз, когда Вы применяете функцию redirect для перенаправления клиентского запроса, Вы должны использовать addClient для присоединения информации, как здесь:


redirect(addClient("mypage.html"));

В противоположность этому, если Ваша страница имеет ссылку на URL вне Вашего приложения, Вам может не понадобиться присоединение клиентской информации. Тогда не используйте статическую строку в значении атрибута HREF. Вместо этого вычисляйте значение. Это предотвратит автоматическое присоединение машиной выполнения клиентского индекса или свойств к URL. Например, у вас имеется ссылка:


<A HREF="mailto:me@royalairways.com">

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


<A HREF=`"mailto:me@royalairways.com"`>

Хотя приложение первоначально инсталировано для использования техники без кодирования URL для работы с client, оно может быть позднее модифицировано для использования техники кодирования URL. Следовательно, если Ваше приложение генерирует динамические URL или использует redirect, Вам всегда нужно будет использовать addClient.

Безопасное Совместное Использование Объектов с Блокировкой/Locking


Рабочая среда для версии 3.x или 4.x Netscape-сервера является многопоточной; то есть она обрабатывает более одного запроса в единицу времени. Поскольку эти запросы могут требовать выполнения JavaScript, то более чем один поток выполнения JavaScript может быть активным в одно и то же время.

Если несколько потоков одновременно пытаются изменить свойство одного и того же объекта JavaScript, они могут привести этот объект в несоответствующее состояние. Участок кода, в котором необходимо выполнять один, и только один, поток выполнения в единицу времени, называется критическим разделом/сritical section.

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

Важно!

В отличие от предыдущих релизов, неявная блокировка объектов project и server теперь отсутствует.

Чтобы лучше понять, что происходит, рассмотрим следующий пример. Предположим, Вы создаёте совместно используемый объект project.orders для отслеживания заказов пользователей. Вы обновляете project.orders.count каждый раз при получении нового заказа, используя следующий код:


var x = project.orders.count; 
x = x + 1;
project.orders.count = x;

Предположим, что project.orders.count первоначально установлено в 1 и что поступили два новых заказа в двух разных потоках. Произойдёт следующее:

  1. Первый поток сохраняет project.orders.count в переменной x.
  2. Прежде чем продолжить, второй поток запускается и сохраняет то же самое значение в своей копии переменной x.
  3. С этого момента оба потока имеют значение 1 в x.
  4. Второй поток завершает своё выполнение и устанавливает project.orders.count в 2.
  5. Первый поток продолжает выполнение, не зная, что значение project.orders.count изменилось, и также устанавливает 2 в х.

Итак, конечное значение project.orders.count будет 2, хотя корректным должно быть 3.

Чтобы избежать проблем такого рода, Вам нужно получить исключительный доступ к свойствам совместно используемых объектов перед тем как записывать в них. Для этих целей Вы можете конструировать Ваши собственные экземпляры класса Lock, работающие с любым совместно используемым объектом. Кроме того, объекты server и project имеют методы lock и unlock, которые Вы можете использовать для ограничения доступа к этим объектам.

Использование Экземпляров Класса Lock


Представьте lock (замок/блокировку) как именованный флаг, который Вы обязаны устанавливать перед входом в критичный раздел. Если Вы запрашиваете именованный флаг и кто-то уже имеет его, Вы будете ждать, пока этот второй не освободит флаг. В процессе ожидания Вы не сможете изменять то, что не должны изменять. После получения Вами флага кто-либо ещё будет ожидать и не сможет ничего изменить, пока Вы не освободите флаг. Если возникнет ошибка или таймаут закончится до того, как Вы получите флаг, Вы можете снова вернуться в режим ожидания, либо делать что-нибудь другое, как, например, дать Вашим пользователям знать, что приложение очень занято, чтобы выполнить данную операцию сейчас. Вы не должны вмешиваться в процесс ожидания (изменяя совместно используемую информацию)! Рисунок 6.5 иллюстрирует этот процесс.

Рисунок 6.5   Thread (поток) 2 ожидает, пока thread 1 имеет lock (замок)

В терминах программирования замок/lock представлен экземпляром класса Lock. Вы можете использовать экземпляр класса Lock для получения исключительного доступа к любому совместно используемому объекту. Обычно Вы создаёте экземпляры Lock на начальной странице Вашего приложения (по причинам, которые будет изложены позднее).

На других страницах, перед критичным для совместно используемого объекта разделом (например, перед разделом, который запрашивает и изменяет значение свойства), Вы вызываете метод lock экземпляра Lock. Если этот метод возвращает true, Вы получаете замок и можете продолжать. В конце критичного раздела Вы вызываете метод unlock Lock -экземпляра.

Когда клиентский запрос в одиночном потоке выполнения вызывает метод lock, любой другой запрос, вызывающий метод lock для того же Lock -экземпляра, ожидает, пока первый поток не вызовет метод unlock, пока не закончится таймаут или пока не возникнет ошибка. Это верно независимо от того, находится второй запрос в другом потоке для того же клиента или в потоке для другого клиента.

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

Важно!

Использование замков находится всецело под управлением разработчика и требует кооперации. Машина выполнения не заставляет Вас ни вызывать lock, ни учитывать блокировку, полученную кем-либо другим. Если Вы не спрашиваете, Вы можете изменять всё что захотите. Поэтому очень важно выработать привычку всегда вызывать lock и unlock при входе и выходе из критичного раздела кода и проверять return-значение метода lock, чтобы гарантировать, что блокировка получена. Можно представлять это в терминах флага: если Вы не запрашиваете флаг, вы не будете находиться в режиме ожидания. Если Вы не находитесь в режиме ожидания, Вы можете изменять то, что изменять нельзя.

Вы можете создать столько замков, сколько Вам необходимо. Один и тот же замок может использоваться для управления доступом к нескольким объектам, либо каждый объект (или даже каждое свойство) может иметь собственный замок.

Замок/lock сам по себе является просто объектом JavaScript; Вы можете сохранить ссылку на него в любом другом объекте JavaScript. Таким образом, например, обычной практикой является конструирование экземпляра Lock и сохранение его в объекте project.

ПРИМЕЧАНИЕ:

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

Следующий код показывает, как отследить заказы потребителей в совместно используемом объекте project.orders, рассмотренном ранее, и как обновлять project.orders.count каждый раз при получении нового заказа. Включите в начальную страницу приложения такой код:


// Создать новый Lock и сохранить в project.


project.ordersLock = new Lock();
if (! project.ordersLock.isValid()) {
   // Невозможно создать Lock. Перенаправить на страницу обработки ошибок.
   redirect ("sysfailure.html");
}

Этот код создаёт экземпляр класса Lock и проверяет (вызовом метода isValid), не возвращено ли что-нибудь неправильное при его создании. Очень редко Ваш экземпляр Lock конструируется неправильно. Это случается только тогда, когда машина выполнения запущена вне системных ресурсов при создании объекта.

Вы обычно создаёте экземпляры Lock на начальной странице, поэтому Вам не нужно получать замок перед созданием экземпляров Lock. Начальная страница запускается только один раз - при старте приложения на сервере. Поэтому Вам гарантируется, что создаётся только один экземпляр каждого замка.

Если, однако, Ваше приложение создаёт замок на какой-либо иной странице, множественные запросы могут вызывать эту страницу в это время. Один запрос может проверять наличие замка и не обнаружить его, в то время как другой запрос создаёт замок, а третий запрос создаёт второй замок. Тем временем первый запрос вызывает метод lock своего объекта. Затем второй запрос вызывает метод lock своего объекта. Оба запроса теперь "думают", что они имеют безопасный доступ к критичному разделу кода и продолжают свою работу, нарушая работу другого.

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


// Начало критичного раздела -- получить замок.


if ( project.ordersLock.lock() ) {

   var x = project.orders.count; 
   x = x + 1;
   project.orders.count = x;


   // Конец критичного раздела -- освободить замок.


   project.ordersLock.unlock();
}
else
   redirect("combacklater.html");

Этот код запрашивает замок. Если замок получен (то есть, если метод lock возвратил true), выполняется вход в критичный раздел, вносятся изменения и, наконец, замок освобождается. Если метод lock возвращает false, то данный код не получает замка. В этом случае приложение перенаправляет на страницу, которая сообщает, что приложение в данный момент не может выполнить запрос.

Специальные Замки/Locks для Объектов project и server


Каждый из объектов project и server имеет методы lock и unlock. Вы можете использовать эти методы для получения исключительного доступа к свойствам этих объектов.

В этих методах ничего нового нет. Вам также необходима кооперация с другими участками кода. Вы можете представлять эти методы как имеющие флаги: один флаг с именем "project", а другой - флаг с именем "server." Если другой раздел кода не вызывает project.lock, первый может изменять любые свойства объекта project.

В отличие от метода lock класса Lock, Вы не можете специфицировать таймаут для метода lock объектов project и server. То есть, когда Вы вызываете project.lock, система ожидает бесконечно долго освобождения замка. Если Вы хотите ожидать только в течение определённого периода, используйте экземпляр класса Lock.

В примере использованы методы lock и unlock для получения исключительного доступа к объекту project для модификации свойства ID потребителя:


project.lock()
project.next_id = 1 + project.next_id;
client.id = project.next_id;
project.unlock();

Исключение Мёртвой Блокировки/Deadlock


Вы используете замки для защиты критичных участков кода. На практике это означает, что один запрос ожидает, пока другой выполняет критичный код. Вы обязаны соблюдать осторожность при использовании замков для защиты критичных разделов. Если один запрос ожидает освобождения замка, полученного другим запросом, а этот второй запрос ожидает освобождения замка, полученного первым запросом, ни один из запросов не сможет продолжить работу. Эта ситуация называется deadlock/тупик/мертвая блокировка.

Рассмотрим предыдущий пример обработки заказов потребителей. Предположим, что приложение разрешает два действия. В одном - пользователь вводит нового потребителя; в другом - пользователь вводит новый заказ. Как часть создания нового потребителя приложение также создаёт новый заказ потребителя. Это действие выполняется на одной странице приложения, давая примерно такой код:


// Создать нового потребителя (customer).


if ( project.customersLock.lock() ) {

   var id = project.customers.ID; 
   id = id + 1;
   project.customers.ID = id;

   // Стартовать новый заказ (order) для этого нового потребителя.
   if ( project.ordersLock.lock() ) {


      var c = project.orders.count; 
      c = c + 1;
      project.orders.count = c;
      project.ordersLock.unlock();
   }

   project.customersLock.unlock();
}

Во втором типе действия пользователь вводит новый заказ потребителя. Как часть процесса ввода нового заказа: если потребитель ещё не является зарегистрированным потребителем, приложение создаёт нового потребителя. Это действие выполняется на другой странице приложения, где может быть примерно такой код:


// Стартовать новый заказ.


if ( project.ordersLock.lock() ) {

   var c = project.orders.count; 
   c = c + 1;
   project.orders.count = c;


   if (...код определения неизвестного потребителя...) {

      // Создать нового потребителя.
      // Этот внутренний замок может вызвать проблемы!
      if ( project.customersLock.lock() ) {

        
 var id = project.customers.ID; 
         id = id + 1;
         project.customers.ID = id;

         
project.customersLock.unlock();
      }
   }

   project.ordersLock.unlock();
}

Заметьте, что каждый из этих фрагментов кода пытается получить второй замок, уже получив один. Это может вызвать проблемы. Предположим, что один поток начинает создание нового потребителя; он получает замок customersLock. В это же самое время другой поток начинает создание нового заказа; он получает замок ordersLock. Теперь первый поток запрашивает замок ordersLock. Поскольку второй поток уже получил этот замок, первый поток должен ждать. Предположим, однако, что второй поток теперь запрашивает замок customersLock. Первый поток уже имеет этот замок, поэтому второй поток должен ждать. Теперь потоки ждут друг друга. Поскольку никто их них не специфицировал таймаут, оба они будут ждать бесконечно.

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


// Создать нового потребителя.


if ( project.customersLock.lock() ) {

   var id = project.customers.ID; 
   id = id + 1;
   project.customers.ID = id;

   project.customersLock.unlock();
}

// Стартовать новый заказ для этого нового потребителя.
if ( project.ordersLock.lock() ) {


   var c = project.orders.count; 
   c = c + 1;
   project.orders.count = c;


   project.ordersLock.unlock();
}

Второй фрагмент будет примерно таким:


// Стартовать новый заказ.

if ( project.ordersLock.lock() ) {

   var c = project.orders.count; 
   c = c + 1;
   project.orders.count = c;

   project.ordersLock.unlock();
}

if (...код для определения неизвестного потребителя...) {

   // Создать нового потребителя.
   if ( project.customersLock.lock() ) {

      var id = project.customers.ID; 
      id = id + 1;
      project.customers.ID = id;

      project.customersLock.unlock();
   }
}

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


function fn1 () {
   if ( project.lock() ) {
      // ... какие-то действия ...
      project.unlock();
   }
}

function fn2 () {
   if ( project.lock() ) {
      // ... какие-то другие действия ...
      project.unlock();
   }
}

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


function fn1 () {
   if ( project.lock() ) {
      // ... какие-то действия ...
      fn2();
      project.unlock();
   }
}

Вот вы и получили тупик/deadlock. Это, конечно, немного смешно, когда единственный запрос ожидает от самого себя освобождения флага!

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.



Оглавление | Назад | Вперёд | Индекс

Глава 13
Приложения-Образцы Videoapp и Oldvideo

В этой главе описано приложение-образец videoapp, иллюстрирующее использование службы LiveWire Database Service. Рассмотрено, как сконфигурировать рабочую среду для запуска приложений videoapp и oldvideo.

В главе имеются следующие разделы:

О Приложениях Videoapp и Oldvideo


Netscape-серверы поставляются с двумя приложениями-образцами для работы с базами данных, videoapp и oldvideo, которые иллюстрируют работу LiveWire Database Service. Эти приложения весьма похожи; они отслеживают прокат видео в воображаемом видео-салоне. Приложение videoapp демонстрирует использование объектов DbPool и Connection. Приложение oldvideo демонстрирует использование предопределённого объекта database.

Есть несколько небольших ограничений на использование этих приложений:

Конфигурирование Среды


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

ПРИМЕЧАНИЕ:

Ваш сервер БД обязан быть настроен и запущен перед началом создания видео-БД, и Вы обязаны сконфигурировать сервер и клиента БД так, как указано в Главе 10, "Конфигурирование Базы Данных".

Кроме того, скрипты создания БД используют утилиты БД, поставляемые с Вашими БД. Вы уже должны знать, как пользоваться этими утилитами.

Соединение с БД и Рекомпиляция


Приложение videoapp находится в директории $NSHOME\js\samples\videoapp, где $NSHOME это директория установки Netscape-сервера. Приложение oldvideo находится в директории $NSHOME\js\samples\oldvideo.

Для каждого приложения Вы обязаны изменить строку с информацией о соединении в исходном HTML-файле start.html, чтобы настроиться на среду окружения Вашей БД. О параметрах соединения см. раздел "Пул Соединений Базы Данных"; дополнительно см. также описание метода connect в книге Серверный JavaScript. Справочник .

Для приложения videoapp измените эту строку:


project.sharedConnections.pool = 
   new DbPool ("<Server Type>", "<Server Identifier>", "<User>", "<Password>", "<Database>", 2, false)

Для приложения oldvideo измените эту строку:


database.connect ("INFORMIX", "yourserver", "informix", "informix", "lw_video")

Сохраните изменения и рекомпилируйте приложение. Для рекомпиляции приложения из командной строки запустите его build-файл, расположенный в директории приложения. Убедитесь, что переменная окружения PATH содержит путь к компилятору (обычно это $NSHOME\bin\https).

Рестартуйте приложения в JavaScript Application Manager'е.

Создание Базы Данных


Имеются два набора скриптов создания БД для videoapp и oldvideo, находящиеся в соответствующих этим приложениям директориях. Наборы скриптов идентичны. Если Вы запустите один набор, оба приложения смогут использовать БД.

При первом запуске скриптов Вы можете получать ошибки, касающиеся стирания БД или таблиц, которые ещё не существуют. Это нормально; можно спокойно игнорировать эти сообщения.

Informix


Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Informix-клиент, как указано в разделе "Informix." Кроме того, убедитесь, что переменная окружения PATH содержит путь к $INFORMIXDIR\bin и что Ваш клиент сконфигурирован для использования утилит Informix.

SQL-файлы для создания видео-БД (lw_video) в Informix находятся в двух директориях:


$NSHOME\js\samples\videoapp\ifx 
$NSHOME\js\samples\oldvideo\ifx

ПРИМЕЧАНИЕ:

Не забудьте, что пути в этом учебнике, если они относятся и к NT, и к Unix, даются в формате NT. В Unix Вы используете $NSHOME/js/samples/videoapp/ifx.

  1. В Unix войдите в систему как пользователь "informix" и запустите скрипт оболочки ifx_load.csh для videoapp и для oldvideo.

  2. В NT дважды щёлкните в группе программ Informix Server иконку Command-Line Utilities, чтобы открыть окно DOS, затем запустите следующие команды:
    
    cd c:\netscape\server\js\samples\videoapp\ifx
    ifx_load.bat
    Вы можете также запустить эти команды из директории oldvideo\ifx:
  3. Теперь Вы можете запускать приложение, сделав предварительно изменения, описанные в разделе "Соединение с Базой Данных и Рекомпиляция".

Oracle


Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Oracle-клиент, как указано в разделе "Oracle." Помимо этого, Ваш клиент обязан быть сконфигурирован для запуска утилит Oracle. Чтобы запускать SQL Plus, Вам может понадобиться установить переменную окружения ORACLE_SID.

SQL-файлы для создания видео-БД в Oracle, находятся в двух директориях:


$NSHOME\js\samples\videoapp\ora
$NSHOME\js\samples\oldvideo\ora
  1. И в Unix, и в NT: стартуйте SQL Plus. Из промпта SQL> введите такую команду:
  2. 
    Start $NSHOME\js\samples\videoapp\ora\ora_video.sql
    Вы можете также запустить этот скрипт из директории oldvideo. Этот SQL-скрипт не создаёт новую БД. Он создаёт таблицы Oracle в текущем экземпляре.
  3. В Unix: запустите скрипт-файл ora_load для загрузки видео-таблиц с данными. В NT: запустите пакетный файл ora_load.bat для загрузки видео-таблиц с данными. Вы обязаны отредактировать соответствующий файл для подключения к Вашему серверу; инструкции об этом содержатся в файле.
  4. Теперь можно запускать приложение, сделав изменения, описанные в разделе "Соединение с Базой Данных и Рекомпиляция".

Sybase


Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Sybase-клиент, как указано в разделе "Sybase." Кроме того, в Unix убедитесь, что переменная окружения PATH содержит $SYBASE\bin и DSQUERY указывает на ваш сервер.

SQL-файлы для создания видео-БД в Sybase, находятся в двух директориях:


$NSHOME\js\samples\videoapp\syb
$NSHOME\js\samples\oldvideo\syb
  1. Запустите соответствующий скрипт из командной строки. В Unix это:
  2. 
    syb_video.csh 
    userid password
    
    
    Например:
    
    $NSHOME\js\samples\videoapp\syb\syb_load.csh sa
    В NT это скрипт:
    
    syb_load
     userid
    password
    
    
    Например:
    
    c:\netscape\server\js\samples\videoapp\syb\syb_load sa
    Можно также запустить скрипт из директории oldvideo.
  3. Теперь можно запускать приложение, сделав изменения, описанные в разделе "Соединение с Базой Данных и Рекомпиляция".

ПРИМЕЧАНИЕ:

Если у Вас на машине установлены и Sybase, и MS SQL Server или DB2, потенциально может возникнуть конфликт имён. Эти производители поставляют утилиты с одинаковыми названиями (bcp и isql). При запуске этих скриптов убедитесь, что переменная окружения настроена для запуска корректной утилиты.

Microsoft SQL Server (только для NT)


Прежде чем использовать нижеуказанные инструкции, Вы обязаны сконфигурировать Ваш Sybase-клиент, как указано в разделе "ODBC." Кроме того, в Unix установите DSQUERY так, чтобы она указывала на Ваш сервер.

SQL-файлы для создания видео-БД в MS SQL Server, находятся в двух директориях:


$NSHOME\js\samples\videoapp\mss
$NSHOME\js\samples\oldvideo\mss
  1. Из командной строки DOS запустите пакетный файл:
  2. 
    mss_load 
    userid password
    
    
    Например:
    
    c:\netscape\server\js\samples\videoapp\mss\mss_load sa
  3. Теперь можно запускать приложение, сделав изменения, описанные в разделе "Соединение с Базой Данных и Рекомпиляция".

ПРИМЕЧАНИЕ:

Если у Вас на машине установлены и Sybase, и MS SQL Server или DB2, потенциально может возникнуть конфликт имён. Эти производители поставляют утилиты с одинаковыми названиями (bcp и isql). При запуске этих скриптов убедитесь, что переменная окружения настроена для запуска корректной утилиты.

DB2


SQL-файлы для создания видео-БД в DB2, находятся в двух директориях:


$NSHOME\js\samples\videoapp\db2
$NSHOME\js\samples\oldvideo\db2
  1. (Только в Unix) Ваша переменная окружения PATH обязана содержать директории $DB2PATH/bin, $DB2PATH/misc и $DB2PATH/adm.
  2. Прежде чем запустить эти скрипты, Вы обязаны уже иметь установленный DB2 Software Developer's Kit (DB2 SDK).
  3. Также, прежде чем Вы сможете запустить скрипты для создания таблиц, Вы обязаны отредактировать их, чтобы изменить некоторые параметры. В Unix это скрипт db2_load.csh; в NT это скрипт db2_load.bat. Отредактируйте соответствующий файл db2_load и измените следующие параметры, отражающие Ваше окружение:
  4. Убедитесь, что Ваши файлы /etc/services имеют вхождения для экземпляра или имени службы, если Вы создаёте БД на удалённом DB2-сервере.
  5. Запустите соответствующую версию скрипта из окна команд DB2. Скрипт db2_load запускает скрипты db2_video.sql и import.sql. Эти вспомогательные скрипты создают видео-таблицы и загружают их данными из файлов *.del. Они не создают новую БД. Они создают таблицы DB2 в псевдониме локальной БД, специфицированном в скрипте db2_load.

ПРИМЕЧАНИЕ:

Если у Вас на машине установлены и DB2, и Sybase или MS SQL Server, потенциально может возникнуть конфликт имён. Эти производители поставляют утилиты с одинаковыми названиями (bcp и isql). При запуске этих скриптов убедитесь, что переменная окружения настроена для запуска корректной утилиты.

Запуск Videoapp


В этом разделе говорится о запуске приложения videoapp. Это значительно более сложный пример, нежели образцы, рассмотренные в Главе 4, "Быстрое Начало с Примерами Приложений". В этой главе дан только его обзор. Вы должны просмотреть также некоторые файлы, чтобы получше познакомиться с приложением.

После создания видео-БД и изменения параметров соединения с БД Вы можете запустить приложение:


http://
server.domain
/videoapp

После соединения с БД менеджер Application Manager выводит домашнюю страницу videoapp,
как показано на Рисунке 13.1.

Рисунок 13.1   Домашняя страница Videoapp

Если соединение с БД невозможно установить, Вы увидите сообщение об ошибке. Убедитесь, что введены корректные параметры соединения с БД, как указано в разделе "Соединение с Базой Данных и Рекомпиляция", приложение рекомпилировано и рестартовало.

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

Вы можете использовать videoapp как customer или как administrator. Как customer Вы можете:

Как administrator Вы можете:

Запустите приложения и сделайте несколько выборов для выполнения различных действий.

Взгляд на Исходные Файлы


Исходные HTML-файлы videoapp, перечисленные в следующей таблице, обильно комментируются.

Таблица 13.1  Первичные исходные файлы приложения videoapp

home.html

Страница по умолчанию. Имеет ссылки на pick.html, status.html, rentals.html, customer.html и delete.html. Если нет соединения с БД, эта страница перенаправляет клиента на страницу start.html.


start.html

Соединяет приложение с БД, стартует транзакцию и переводит обратно на home.html.


abort.html

Отменяет одну транзакцию и начинает новую.


save.html

Подтверждает/Commits транзакцию и начинает новую.


pick.html

Позволяет потребителю взять клип напрокат. Содержит фрэймы для category.html, videos.html и pickmenu.html.

Файл category.html показывает категории видео.

Файл videos.html показывает все видео в выбранной категории и соединён с rent.html для аренды определённых видео.

Файл pickmenu.html показывает другие страницы.


status.html

Выводит видео, имеющиеся у потребителя в данный момент. Если потребитель не выбрал ID, перенаправляет его на страницу client.html, на которой можно выбрать customer ID.


rentals.html

Выводит список всех взятых видео. Когда администратор щёлкает на названии одного их них, выбранная позиция отправляется на return.html, которая выполняет действия по возвращению видео, затем направляет обратно на rentals.html.


customer.html

Администратор может ввести здесь нового потребителя. Отправляет введённые в форму данные на add.html, где выполняются действия по вводу нового потребителя, затем возвращает на customer.html.


delete.html

Здесь администратор может удалить потребителя. Выводит список потребителей со ссылками на remove.html, где удаляется специфицированный ряд из таблицы потребителей, затем возвращает на delete.html.


modify.html

Администратор может изменить здесь данные потребителя. Выводит список из первых 5 потребителей со ссылками на страницы modify1.html и modify2.html. Эти страницы обновляют специфицированный ряд в таблице потребителей и возвращают обратно на modify.html. Файл modify3.html выводит следующих потребителей, 5 за один раз.

Архитектура Приложения


Этот раздел ориентирует Вас на реализацию некоторой функциональности в videoapp. Он описывает, как приложение работает с БД и детали процедуры аренды видео. Другие задачи похожи.

Соединение и Процесс Работы


Когда пользователь инициирует сессию с приложением videoapp, входя на начальную страницу (home.html), videoapp проверяет, имеется ли уже соединение с БД. Если это так, videoapp предполагает, что не только приложение, но и пользователь уже соединены с БД, и продолжает работу.

Если соединение не установлено, videoapp перенаправляет на страницу start.html. На ней приложение создаёт единый пул соединений с БД, используемый всеми потребителями, получает соединение для пользователя и стартует транзакцию с БД для этого соединения. Затем перенаправляет обратно на home.html для продолжения. Пользователь никогда не видит перенаправления.

Транзакция базы данных стартует на странице start.html  и остаётся открытой, пока пользователь явно не сохранит или не отменит изменения, щёлкнув кнопку Save Changes или Abort Changes. При этом запускается save.html или abort.html. Эти страницы подтверждают или откатывают изменения открытой транзакции, а затем немедленно начинают новую транзакцию. Поэтому соединение потребителя всегда остаётся открытым.

Получив соединение с БД, videoapp выводит пользователю главную страницу. С неё пользователь может сделать выбор - такой как аренда клипа или добавление нового потребителя. Каждая из этих опций выводит разные страницы, которые содержат операторы серверного JavaScript. Многие страницы имеют операторы, использующие соединение для взаимодействия с БД, выводя информацию или внося изменения в БД.

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

Взятие Клипа Напрокат


Страница pick.html содержит набор фрэймов, где пользователь может взять клип напрокат. Набор фрэймов состоит из страниц category.html, videos.html и pickmenu.html.

Страница category.html запрашивает в БД список известных категорий клипов. Затем выводит эти категории в виде списка ссылок в таблице левого фрэйма. Если пользователь щёлкает на одной из ссылок, videoapp выводит video.html в правом фрэйме. Есть несколько интересных моментов, касающихся серверного кода, выполняющего эти задачи. На странице Вы можете найти такие строки:


var userId = unscramble(client.userId)
var bucket = project.sharedConnections.connections[userId]
var connection = bucket.connection

Эти операторы имеются на большинстве страниц videoapp. Они запрашивают соединение из того места, где оно хранится в объекте project. Следующая строка получает новый курсор, применимый для данной задачи:


cursor = connection.cursor("select * from categories");

Вариант этого оператора имеется в начале большинства задач.

Вот следующий интересный набор операторов:


<SERVER>
...
while (cursor.next()) {
   catstr = escape(cursor.category)
</SERVER>

<TR><TD><A HREF=`"videos.html?category=" +
catstr` TARGET="myright">
<SERVER>write(cursor.category);</SERVER></A>
</TD>
</TR>
<SERVER>

} // окончание цикла while

Этот цикл создаёт в курсоре ссылку для каждой категории. Обратите особое внимание на оператор:


<A HREF=`"videos.html?category=" +
catstr` TARGET="myright">

Эта строка создаёт ссылку на videos.html. Она содержит в URL имя категории. Предположим, это категория Comedy. Оператор создаёт такую ссылку:


<A HREF="videos.html?category=Comedy" TARGET="myright">

Когда пользователь щёлкает на ссылке, сервер переходит на страницу videos.html и устанавливает значение свойства category объекта request в Comedy.

Страница videos.html может обрабатываться из pick.html или из category.html. В первом случае свойство category не устанавливается, поэтому страница выводит сообщение, предлагающее пользователю выбрать категорию. Если category правильно установлено, videos.html входит в БД для вывода информации обо всех клипах данной категории. Эта страница использует ту же технику, что и category.html, для конструирования информации и создания ссылок на странице rent.html.

Страница rent.html фактически записывает взятые пользователем напрокат клипы. Она получает информацию из запроса и обновляет таблицу в БД для отражения новой аренды. Эта страница выполняет обновление, но не подтверждает изменения, пока пользователь не выберет Save Changes или Abort Changes.

Страница pickmenu.html просто выводит кнопки для возврата на домашнюю страницу или на страницу для добавления нового потребителя.

Модифицирование videoapp


Как способ применения функциональности LiveWire рассмотрим пример модернизации videoapp. Вот что можно сделать:

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Вперёд | Индекс

Серверный JavaScript 1.4.
Руководство по Использованию.

Перевод выполнил Александр Пирамидин.
Прошу все замечания и предложения направлять по e-mail: a_pyramidin@yahoo.com


В этой книге рассматривается использование ядра и серверного JavaScript версии 1.4. JavaScript это созданный фирмой Netscape межплатформенный объектно-ориентированный язык скриптов (сценариев) для клиентских и серверных приложений.

Оглавление

Введение

Что Нового в Этой Версии?
Поддержка JavaScript 1.4
Изменения в Менеджере Приложений JavaScript
Что Вы Уже Должны Знать
Версии JavaScript
Где Найти Информацию о JavaScript
Обновление Предыдущей Версии
Обратная Совместимость с Предыдущими Версиями
Соглашения по Документам

Глава 1  JavaScript. Обзор.

Что Такое JavaScript?
Ядро, Клиентский и Серверный JavaScript
Ядро JavaScript
Клиентский JavaScript
Серверный JavaScript
JavaScript и Java
Отладка в JavaScript
Visual JavaScript
JavaScript и Спецификация ECMA
Соотношение Между Версиями JavaScript и ECMA
Документация JavaScript и Спецификация ECMA
JavaScript и Технология ECMA

ЧАСТЬ I. Разработка Серверных Приложений.

Глава 2  Введение

Архитектура Приложений JavaScript
Системные Требования
Информация о Конфигурации
Подключение Серверного JavaScript
Защита Менеджера Приложений
Настройка LiveConnect
Локализация Компилятора

Глава 3  Технология Разработки Приложений JavaScript

Основные Этапы Создания Приложения
Менеджер Приложений JavaScript
Создание Исходных Файлов Приложения
Компиляция Приложения
Инсталяция Нового Приложения
URL Приложения
Управление Доступом к Приложению
Модификация Приложения
Удаление Приложения
Старт, Остановка и Рестарт Приложения
Запуск Приложения
Отладка Приложения
Использование Менеджера Приложений для Отладки
Использование URL Отладки
Использование Функции debug
Публикация Приложения
Менеджер Приложений. Детали.
Конфигурация, Установки по Умолчанию.
За Кулисами

ЧАСТЬ II. Возможности Серверного JavaScript.

Глава 4  Быстрый Старт. Образец Приложения.

О Приложениях-Образцах Серверного JavaScript
Hello World
Что Делает Hello
Исходный Скрипт
Модифицирование Hello World
Hangman
Исходные Файлы
Отладка Hangman

Глава 5  Основы Серверного JavaScript

Что Делать и Где
Обзор Процессов Времени Выполнения
Серверный Язык. Обзор.
Прототипы
Использование
Окружение
Классы и Объекты
Внедрение JavaScript в HTML
Тэг SERVER
Обратные Кавычки
Когда Использовать Эту Технику?
Процессинг Времени Выполнения на Сервере
Конструирование HTML-Страницы
Генерация HTML
Очистка Буфера Вывода
Переход к Новому Клиентскому Запросу
Доступ к Переменным CGI
Сообщение Между Сервером и Клиентом
Отправка Сообщений с Клиента на Сервер
Отправка Значений с Сервера Клиенту
Использование "Куков"
Сбор Мусора
Обработка Ошибок в Серверном JavaScript

Глава 6  Обслуживание Сессий

Предопределённые Объекты. Обзор.
Объект request
Свойства
Работа с Картами Изображений
Объект client
Свойства
Уникальное Обращение к Объекту client
Создание Специального Объекта client
Объект project
Свойства
Совместное Использование Объекта project
Объект server
Свойства
Совместное Использование Объекта server
Техника Работы с Объектом client
Сравнение Разных Техник Обслуживания Клиента
Клиентская Техника
Серверная Техника
Период Существования Объекта client
Присоединение Свойств client'а к URL Вручную
Безопасное Использование Объектов с Блокировкой
Использование Lock-Экземпляров
Специальные Lock для Объектов project и server
Как Избежать Мёртвых Блокировок

Глава 7  Дополнительная Функциональность JavaScript

Почтовая Служба
Служба Файловой Системы
Проблемы Безопасности
Создание File-Объекта
Открытие и Закрытие Файла
Блокировка Файлов
Работа с Файлами
Пример
Работа с Внешними Библиотеками
Указания по Написанию Внешних Функций
Идентификация Файлов Библиотек
Регистрация Внешних Функций
Использование Внешних Функций в JavaScript
Манипуляции с Запросами и Ответами
Шапка Запроса
Тело Запроса
Шапка Ответа

ЧАСТЬ III. Служба LiveWire Database Service

Глава 8  Соединение с БД

Взаимодействие с Базами Данных
Соединение с БД
Пулы Соединений с БД
Однопоточные и Многопоточные БД
Рекомендации
Обслуживание Пулов Соединений
Совместное Использование Фиксированного Набора Пулов Соединений
Совместное Использование Массива Пулов Соединений
Индивидуальные Соединения с БД
Обслуживание Соединения по Нескольким Запросам
Ожидание Соединения
Запрашивание Свободного Соединения

Глава 9  Работа с БД

Взаимодействие с Реляционной БД
Автоматическое Отображение Результатов Выполнения Запроса
Выполнение Произвольных Операторов SQL
Манипуляции с Результатами Выполнения Запросов с Помощью Курсоров
Создание Курсора
Отображение Значений Записи
Отображение Выражений и Агрегатных Функций
Навигация с Помощью Курсоров
Работа со Столбцами
Изменение Информации Базы Данных
Обслуживание Транзакций
Методы Управления Транзакциями
Работа с Двоичными Данными
Вызов Хранимых Процедур
Обмен Информацией
Этапы Использования Хранимых Процедур
Регистрация Хранимой Процедуры
Определение Прототипа для Хранимой Процедуры
Выполнение Хранимой Процедуры
Работа с Наборами Результатов
Работа с Возвращаемыми Значениями
Работа с Параметрами Вывода
Исключения Informix и Sybase

Глава 10  Конфигурирование Базы Данных

О Службе LiveWire Database Service
Проверка Конфигурации Вашей БД
Поддерживаемые Клиенты БД и ODBC-Драйверы
DB2
Informix
Удалённый Informix
Локальный Informix
ODBC
ODBC DSN (Только NT)
OpenLink ODBC-Драйвер (Только Solaris)
Visigenic ODBC-Драйвер (Только Unix)
Oracle
Удалённый Oracle
Локальный Oracle
Sybase
Удалённый Sybase
Локальный Sybase
Sybase (Только Unix)

Глава 11  Конвертация Типов Данных

О Конвертации Типов Данных
Работа с Датами и БД
Конвертация Типа Данных Базой Данных

Глава 12  Обработка Ошибок LiveWire

Проверка Ошибочных Условий
Возвращаемые Значения
Число
Объект
Булево
Строка
Пустое
Методы для Работы с Ошибками
Статус-Коды

Глава 13  Приложения-Образцы Videoapp и Oldvideo

О Приложениях Videoapp и Oldvideo
Конфигурирование Окружения
Соединение с БД и Перекомпиляция
Создание БД
Запуск Videoapp
Исходные Файлы
Архитектура Приложения
Модифицирование Videoapp

ЧАСТЬ IV Работа с LiveConnect

Глава 14  LiveConnect. Обзор.

Что Такое LiveConnect?
Работа с Оболочками
Взаимодействие JavaScript и Java
Объект Packages
Работа с Массивами Java
Обращение к Классу и Пакету
Аргументы Типа char
Пример Вызова Java из JavaScript
Взаимодействие Java и JavaScript
Использование Классов LiveConnect
Доступ к Серверному JavaScript
Конвертация Типов Данных
Конвертация из JavaScript в Java
Конвертация из Java в JavaScript

Словарь

Индекс

Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Глава 3  Технология Разработки Приложений JavaScript

В этой главе рассматриваются вопросы процесса разработки Вашего приложения, такие как использование компилятора приложений JavaScript и Менеджера Приложений Netscape-серверов для инсталяции или отладки Вашего приложения.
Информацию об использовании только клиентского JavaScript см. в книге Клиентский JavaScript 1.3. Руководство.

В этой главе имеются следующие разделы:

Основные Этапы Создания Приложения


Обычно HTML статичен: после того как Вы написали HTML-страницу, её содержимое фиксируется. Фиксированное содержимое пересылается  с сервера клиенту, когда клиент выполняет доступ к странице по её URL. С помощью JavaScript Вы можете создавать HTML-страницы, которые могут изменяться вслед за изменением данных или в ответ на действия пользователя. На Рисунке 3.1 показана базовая процедура создания и запуска приложения JavaScript.

Рисунок 3.1    Создание и Запуск Приложения JavaScript

Для создания приложения JavaScript Вы должны выполнить следующие шаги:

  1. Создать исходные файлы. Исходные файлы могут быть HTML-файлами с внедрённым JavaScript, файлами, содержащими только JavaScript, или исходными файлами на Java. (См. "Создание Исходных Файлов Приложения".)

  2. Заметьте, что Виртуальная Машина JavaScript (VM), используемая в Netscape Enterprise Server 4.0, реализует значительные улучшения в процессинге локальных переменных (то есть переменных, объявленных внутри функций), по сравнению с NES 3.6. Отсюда следует, что нужно минимизировать использование глобальных переменных (то есть тех, которые объявлены между тэгами <server> и </server>) и переписать приложения так, чтобы максимально использовать функции. Это значительно увеличит скорость работы приложения.
  3. Построить приложение с использованием компилятора приложений JavaScript для создания исполняемого байт-кода (файла .web). (См. "Компиляция Приложения".) Скомпилировать исходные файлы Java в файлы классов.
  4. Опубликовать web-файл, все необходимые файлы HTML, изображений и клиентского JavaScript и откомпилированные файлы Java-классов в соответствующие директории на сервере. Вы можете использовать Netscape Web Publisher для публикации Ваших файлов, как описано в книге Web Publisher User's Guide.
  5. Установить приложение в первый раз (см. "Инсталяция Нового Приложения") с помощью Менеджера Приложений JavaScript. Вы можете также использовать Менеджер Приложений для рестарта приложения после его перестроения/rebuilding (см. "Старт, Остановка и Рестарт Приложения"). Инсталяция или рестарт приложения заставляют машину выполнения JavaScript запустить это приложение на выполнение.
    После инсталяции приложения Вам может потребоваться защитить его. См. раздел "Публикация Приложения". Вам не нужно рестартовать приложение после его начальной инсталяции.
  6. Запустить приложение, щёлкнув Run в Менеджере Приложений или загрузив URL приложения в браузер. (См. "Запуск Приложения" и "URL Приложения".) Например, чтобы запустить Hello World, загрузите в браузер http:// server.domain /world/. Вы можете выполнить также отладку приложения, щёлкнув Debug в Менеджере Приложений. (См. "Отладка Приложения".)
  7. После того как Вы завершили разработку и тестирование Вашего приложения, Вам нужно будет опубликовать его, чтобы сделать доступным для пользователей. Процесс публикации обычно включает в себя инсталяцию приложения на конечном сервере и изменение прав доступа. (См. "Публикация Приложения".)

Прежде чем Вы сможете разрабатывать приложения на JavaScript, Вам нужно будет запустить машину выполнения на сервере и, возможно, защитить Менеджер Приложений JavaScript от неавторизованного доступа. Дополнительно см. разделы "Информация Конфигурации" и Глава 2, "Введение.".

Менеджер Приложений JavaScript. Обзор.


Прежде учиться создавать приложения JavaScript, Вы должны ознакомиться с Менеджером Приложений JavaScript. Вы можете использовать Application Manager для выполнения следующих задач:

Добавления нового JavaScript-приложения.

Модификации любых атрибутов уже установленного приложения.

Останова, старта и рестарта установленного приложения.

Запуска и отладки активного приложения.

Удаления установленного приложения.

Application Manager сам является приложением на JavaScript, демонстрирующим мощь и гибкость JavaScript. Вы запускаете JavaScript Application Manager по следующему URL в Navigator'е:


http://
server.domain
/appmgr

В ответ Application Manager отобразит страницу, показанную на Рисунке 3.2 для Netscape Enterprise Server 3.x и на Рисунке 3.3 - для Enterprise Server 4.0.

Рисунок 3.2    Application Manager в Enterprise Server 3.x


Рисунок 3.3    Application Manager в Enterprise Server 4.0

Application Manager отображает в прокручиваемом левом фрэйме (кадре/окне) все приложения JavaScript, установленные в данный момент на сервере. Выберите нужное приложение, щёлкнув на его имени в прокручиваемом списке.

Правый фрэйм отображает для выбранного приложения следующую информацию:

Описание этих полей см. в разделе "Инсталяция Нового Приложения".

Для добавления нового приложения щёлкните вверху кнопку Add Application.

Щёлкните Configure (в Enteprise Server 3.x) или Preferences (в Enterprise Server 4.0) для конфигурирования установок по умолчанию для Application Manager.
Щёлкните Documentation, чтобы перейти на страницу технической поддержки Netscape JavaScript, где имеются ссылки на разнообразную документацию. Щёлкните Help для получения дополнительных инструкций об использовании Application Manager.

Создание Исходных Файлов Приложения


Первым шагом на пути создания приложения JavaScript будет создание и редактирование исходных файлов с кодом. Файл с расширением web для приложения JavaScript может быть исходным файлом одного из двух видов:

Если Вы используете JavaScript в HTML-файле, Вы обязаны следовать правилам, указанным в разделе "Внедрение JavaScript в HTML".

Не используйте никаких специальных тэгов в файлах .js; компилятор приложений JavaScript на сервере и интерпретатор JavaScript на стороне клиента считают такие файлы написанными на JavaScript. Поскольку HTML-файл используется и на клиенте, и на сервере, один файл JavaScript обязан использоваться либо на сервере, либо на клиенте; он не может использоваться и там, и там. Следовательно, файл JavaScript может содержать либо клиентский, либо серверный JavaScript, но один файл не может содержать и клиентские, и серверные объекты или функции.

Компилятор приложений JavaScript компилирует и связывает HTML- и JavaScript-файлы, содержащие серверный JavaScript, в единый платформонезависимый байт-код web-файла (имеющего расширение .web), как описано в разделе "Компиляция Приложения".

Вы инсталируете web-файл, запускаемый машиной выполнения JavaScript, как описано в разделе "Инсталяция Нового Приложения".

Компиляция Приложения


Вы компилируете приложение JavaScript, используя компилятор приложений JavaScript, jsac. Компилятор создаёт web-файл из исходных файлов на языках HTML и JavaScript.

Примечание

Netscape Enterprise Server 4.0 поддерживает компилятор JavaScript Application Compiler версии 24.13. Заметьте, что приложение, скомпилированное с  использованием "=" в качестве операции Equal, не сможет использовать новый компилятор. Вы обязаны использовать "==" в качестве операции Equal (==).

Для облегчения доступа к компилятору Вам может понадобиться добавить директорию, в которой он установлен, в переменную окружения PATH. От том, как это сделать, см. раздел "Локализация Компилятора" в Главе 3, "Технология Разработки Приложений JavaScript."

Вам нужно также добавить директорию <server_root>/bin/httpd/lib в LD_LIBRARY_PATH (или LIBPATH, или SHLIB_PATH на Unix-платформах), либо <server_root>/bin/https/bin в PATH на Windows NT-платформах.

Вам нужно компилировать только те страницы, которые содержат серверный JavaScript или оба - клиентский и серверный JavaScript. Вам не нужно компилировать страницы, содержащие только клиентский JavaScript. Вы, конечно, можете сделать это, но скорость работы будет выше, если Вы оставите страницы с клиентским JavaScript без компиляции.

Компилятор доступен из командной строки. Используйте следующий синтаксис командной строки для компиляции и компоновки приложений JavaScript на сервере:


jsac [-h] [-c] [-v] [-d] [-l]
   [-o outfile.web]
   [-i inputFile]
   [-p pathName]
   [-f includeFile]
   [-r errorFile]
   [-a 1.2]
   script1.html [...scriptN.html]    [funct1.js ... functN.js]

Элементы в квадратных скобках не обязательны. Синтаксис дан на нескольких строках для большей ясности. Файлы script N .html и funct N .js это входные файлы для компилятора. Должен быть как минимум один HTML-файл. По умолчанию файлы HTML и JavaScript ищутся в текущей директории. Специфицируемые Вами файлы обязаны быть JavaScript- или HTML-файлы; Вы не можете специфицировать другие файлы, такие, например, как .GIF.

На всех платформах Вы можете использовать тире (-) или слэш (/) для обозначения опций командной строки. То есть, следующие строки эквивалентны:


jsac -h
jsac /h

Заметьте, что, поскольку слэш обозначает опции командной строки, входной файл не может начинаться с символа / (слэш) для обозначения абсолютного пути (в Unix). Таким образом, следующий вызов неверен:


jsac -o myapp.web /usr/vpg/myapp.html

Это ограничение не распространяется на путь, который Вы предоставляете как аргумент командной строки; только на входные файлы. В NT Вы можете использовать обратный слэш (\) для указания абсолютного пути во входном файле, как в следующем вызове:


jsac -o myapp.web \usr\vpg\myapp.html

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

Доступны следующие опции командной строки:

Например, следующая команда компилирует и компонует две HTML -страницы с JavaScript, main.html и hello.html, и файл серверного JavaScript, support.js, создавая двоичный исполняемый файл с именем myapp.web. Кроме того, в процессе компиляции компилятор печатает в командной строке информацию о ходе компиляции.


jsac -v -o myapp.web main.html hello.html support.js

В следующем примере команда компилирует файлы, перечисленные в файле looksee.txt, в бинарный исполняемый файл под названием looksee.web:


jsac -f looksee.txt -o looksee.web

Здесь looksee.txt может содержать:


looksee1.html
looksee2.html
\myapps\jsplace\common.js
looksee3.html

Установка Нового Приложения


Вы не можете запустить приложение, и клиенты не могут получить к нему доступ, пока Вы не установите его. Инсталяция приложения идентифицирует его на сервере. После установки Вы можете перестроить/rebuild и запустить приложение любое число раз. Приложение нужно переустановить только тогда, когда Вы его удалили. Вы можете установить до 120 приложений JavaScript на один сервер.

Прежде чем устанавливать, Вы обязаны поместить все файлы, имеющие отношение к приложению, в соответствующую директорию путём публикации файлов. Иначе Вы получите сообщение об ошибке при попытке инсталяции. Из соображений безопасности, Вы можете не захотеть публиковать свои исходные файлы JavaScript на сервер публикации. См. в разделе "URL Приложения" об ограничениях на размещение файлов.

Чтобы установить новое приложение с помощью Application Manager, щёлкните Add Application. В ответ Application Manager выведет в правом фрэйме форму, показанную на Рисунке 3.4. (Цветовая схема в Enterprise Server 4.0 будет другой).

Рисунок 3.4    Форма Add Application

Заполните поля в форме Add Application следующим образом:

После того как Вы предоставили всю требуемую информацию, нажмите Enter для инсталяции приложения, Reset для очистки всех полей или Cancel для отмены операции.

Вы обязаны остановить и рестартовать сервер после добавления или изменения внешних библиотек. Вы можете рестартовать сервер из Server Manager; см. руководство администратора сервера.

URL Приложения


При установке приложения Вы обязаны задать ему имя. Это имя определяет базовый URL приложения: тот URL, который клиенты используют для доступа к странице по умолчанию данного приложения JavaScript.
Базовый URL приложения имеет форму:


http://server.domain/appName

Здесь server это имя HTTP-сервера, domain это домен Internet (включая субдомены), а appName это имя приложения, которое Вы ему дали при инсталяции. Отдельные страницы приложения достигаются через URL приложения в форме:


http://server.domain/appName/page.html

Здесь page это имя страницы приложения. Например, если Ваш сервер называется coyote, а домен имеет имя royalairways.com, базовый URL для приложения hangman будет:


http://coyote.royalairways.com/hangman

Если клиент запрашивает этот URL, сервер генерирует HTML для страницы по умолчанию приложения и высылает её клиенту. URL приложения страницы winning в этом приложении:


http://coyote.royalairways.com/hangman/youwon.html
Важно!

Прежде чем инсталировать приложение, убедитесь, что выбранное Вами имя приложения не присвоило существующий URL на Вашем сервере. Машина выполнения JavaScript направляет все клиентские запросы по URL, соответствующим URL приложения, в директорию, специфицированную для web-файла. Таким образом можно "обмануть" нормальную корневую директорию.
Например, предположим, клиент запрашивает URL, который начинается с префикса из предыдущего примера:


http://coyote.royalairways.com/hangman

В этом случае машина выполнения на сервере ищет документ в директории samples\hangman, а не в нормальной корневой директории сервера. Сервер обслуживает в этой директории страницы, которые не компилируются в приложение.

Вы можете поместить Ваши исходные (неоткомпилированные) файлы серверного JavaScript в ту же директорию, что и web-файл; однако Вы должны делать это только для отладки. Если Вы публикуете Ваше приложение для общего пользования, Вы, по соображениям безопасности, не должны публиковать неоткомпилированные файлы серверного JavaScript.

Управление Доступом к Приложению


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

Если Вы работаете на рабочем сервере за брандмауэром/firewall, то можете не беспокоиться об ограничении доступа в процессе разработки приложения. Удобно не иметь ограничений доступа в процессе разработки приложения, так как Вы можете быть уверены в защищённости приложения от атак за стеной firewall. Если Вы используете учебные данные на стадии разработки, то риск ещё меньше. Однако, если Вы публикуете Ваше приложение, Вы должны быть уверены, что любой посетитель Вашего приложения может им пользоваться.

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

Модификация Приложения


Чтобы модифицировать приложение, выберите имя приложения в списке приложений и щёлкните Modify.

Вы можете изменить любое поле, определённое при инсталяции приложения, за исключением имени приложения. Чтобы изменить имя приложения, необходимо удалить приложение, а затем реинсталировать его.

Если Вы модифицируете поля остановленного приложения, Application Manager автоматически запускает его. Если Вы модифицируете поля активного приложения, Application Manager автоматически останавливает и запускает его.

Удаление Приложения


Чтобы удалить приложение, выберите его в списке приложений и щёлкните Remove. Application Manager удалит приложение, и оно больше не сможет быть запущено на сервере. Клиенты не смогут больше получить доступ к приложению. Если Вы удалите приложение, а после этого захотите запустить его, нужно будет инсталировать его заново.

Хотя клиенты потеряют доступ к приложению, удаление его с помощью Application Manager не удаляет физически файлы приложения с сервера. Если Вы хотите полностью удалить файлы, сделайте это вручную.

Старт, Остановка и Рестарт Приложения


После инсталяции приложения его можно запустить на выполнение. Выберите приложение в списке приложений и щёлкните Start. Если приложение запущено успешно, его статус изменяется со Stopped на Active.

Вы можете запустить приложение, загрузив его URL:


http://server.domain/appmgr/control.html?name=appName&cmd=start

Здесь appName это имя приложения. Вы не можете изменить этот URL, если не имеете привилегий доступа к Application Manager.

Чтобы остановить приложение и сделать его таким образом недоступным для пользователей, выберите имя приложения в списке приложений и щёлкните Stop. Статус приложения изменится на Stopped, и клиенты не смогут запускать его. Вы обязаны остановить приложение, если хотите переместить web-файл или обновить приложение с рабочего сервера на конечном сервере публикаций.

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


http://server.domain/appmgr/control.html?name=appName&cmd=stop

Здесь appName это имя приложения. Вы не можете изменить этот URL, если не имеете привилегий доступа к Application Manager.

Вы обязаны рестартовать приложение каждый раз после его перестроения/rebuild. Чтобы рестартовать активное приложение, выберите его в списке приложений и щёлкните Restart. Фактически рестарт реинсталирует приложение; программа ищет специфицированный web-файл. Если верного web-файла нет, Application Manager генерирует ошибку.

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


http://server.domain/appmgr/control.html?name=appName&cmd=restart

Здесь appName это имя приложения. Вы не можете изменить этот URL, если не имеете привилегий доступа к Application Manager.

Запуск Приложения


После инсталяции и компиляции приложения Вы можете запустить его двумя способами:

Сервер сгенерирует HTML для специфицированной страницы и вышлет его клиенту.

Отладка Приложения


Для отладки приложения сделайте следующее:

Можно использовать функцию debug для вывода отладочной информации, как описано в разделе "Использование Функции debug".

После запуска отладки приложения JavaScript Вы не сможете остановить или рестартовать его. В этих случаях  Application Manager выдаст сообщение "Trace is active/Трассировка включена". Если это произойдёт, сделайте следующее:

  1. Закройте все окна отладки.
  2. Закройте все окна с данным приложением.
  3. В Application Manager выберите это приложение и щёлкните Run.

Теперь Вы можете остановить и рестартовать это приложение.

Использование Менеджера Приложений/Application Manager для Отладки


Для отладки приложения выберите его в списке приложений и щёлкните Debug. Application Manager откроет новое окно Navigator, в котором будет запущено приложение. Запустится также утилита трассировки в отдельном фрэйме, в окне, содержащем приложение, или вообще в другом окне. (Вы можете определить появление отладочного окна при конфигурировании установок по умолчанию для Application Manager, как описано в разделе "Конфигурирование Установок по Умолчанию").

Утилита трассировки выведет следующую отладочную информацию:

На Рисунке 3.5 показано то, что Вы можете увидеть при отладке приложения Hangman.

Рисунок 3.5   Отладка Приложения Hangman

Использование URL Отладки


Вместо Application Manager вам может больше подойти использование URL отладки приложения. Для отображения утилиты трассировки приложения в отдельном окне введите следующий URL:


http://server.domain/appmgr/trace.html?name=appName

Здесь appName это имя приложения. Для отображения утилиты трассировки в том же самом окне, что и окно приложения (но в отдельном кадре/фрэйме), введите URL в форме:


http://server.domain/appmgr/debug.html?name=appName

Вы не сможете воспользоваться двумя вышеуказанными  URL, если не имеете прав для запуска Application Manager. Для удобства можно сделать закладку на URL отладки.

Использование Функции debug


Вы можете использовать функцию debug в Вашем приложении JavaScript для помощи при отслеживании/трассировке проблем в приложении. Функция debug отображает значения для утилиты трассировки. Например, следующий оператор выводит значение свойства guess объекта request в окне трассировки вместе с некоторым идентифицирующим текстом:


debug ("Current Guess is ", request.guess);

Публикация Приложения


После завершения разработки и тестирования приложения Вы можете опубликовать его и сделать доступным для предполагаемых пользователей. Это требует выполнения двух шагов:

Вы должны скопировать web-файл приложения на сервер публикаций вместе с изображениям и неоткомпилированными файлами HTML и JavaScript, которые необходимы для работы приложения. О публикации файлов приложений см. дополнительно Netshare and Web Publisher User's Guide.

ПРИМЕЧАНИЕ:

В целом, по соображениям безопасности, Вы не должны публиковать файлы с исходным кодом.
В зависимости от приложения, Вы можете ограничить доступ для определённых пользователей или групп пользователей. В некоторых случаях любой пользователь может запускать приложение; тогда ограничений можно вообще не применять. Если приложение показывает специальную информацию или даёт доступ к файловой системе сервера, Вы должны предоставить доступ только авторизованным пользователям, имеющим соответствующие имена и пароли для входа.

Вы ограничиваете доступ к приложению, применяя стиль конфигурации сервера из Вашего Server Manager. Об использовании Server Manager и стилей конфигурации см. Enterprise Server 4.0 Administrator's Guide.

Менеджер Приложений. Детали.


В этом разделе показано, как изменять установки по умолчанию для Application Manager. Кроме того, говорится о формате файла, в котором Application Manager хранит информацию.

Конфигурирование Установок по Умолчанию


Чтобы конфигурировать установки по умолчанию для Application Manager, щёлкните Configure (в Enteprise Server 3.x) или Preferences (в Enterprise Server 4.0) в верхнем фрэйме Application Manager'а. В ответ Application Manager отобразит форму, показанную на Рисунке 3.6.

Вы можете специфицировать следующие значения по умолчанию:

Если Вы устанавливаете новое приложение, используются значения полей по умолчанию в качестве начальных значений.

Дополнительно Вы можете специфицировать следующие установки:

За Кулисами


Application Manager является удобным интерфейсом для модифицирования файла конфигурации $NSHOME\https- serverID \config\jsa.conf, где $NSHOME это директория, в которой установлен сервер, а serverID это идентификатор ID сервера. В случае фатальной ошибки Вам может потребоваться отредактировать этот файл самостоятельно. Вообще-то это не рекомендуется, но здесь мы даём информацию для такого случая.

Каждая строка файла jsa.conf соответствует приложению. Первый элемент каждой строки это имя приложения. Остальные элементы имеют формат name=value, где name это имя поля установки, а value это значение поля. Возможные значения name:

Файл jsa.conf имеет ограничение размера в 1024 строки, каждая строка может иметь не более 1024 символов. Если поля, введённые в Application Manager, превосходят этот лимит, строка усекается. Это ведёт обычно к потере последнего элемента, файлов внешних библиотек. Если это произошло, уменьшите количество используемых внешних библиотек и добавьте библиотеки в другие приложения. Поскольку установленные библиотеки доступны всем приложениям, любое приложение может использовать их.

Строка, начинающаяся с #, обозначает комментарий. Такая строка игнорируется. Можно также включать в файл пустые строки.

Не записывайте несколько строк, специфицируя одно и то же имя приложения. Это вызовет ошибки в работе Application Manager'а.

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

╘ Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Оглавление | Назад | Вперёд | Индекс

Часть 1
Разработка Серверных Приложений

Глава 2. Введение

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

Глава 3. Технология Разработки Приложений JavaScript

В этой главе описан процесс разработки Вашего приложения: как использовать компилятор приложений JavaScript и менеждер Application Manager серверов Netscape для установки или отладки Вашего приложения. Об использовании только клиентского JavaScript см. книгу Клиентский JavaScript. Руководство .

Оглавление | Назад | Вперёд | Индекс

Дата последнего обновления: 29 сентября 1999 г.

© Copyright ╘ 1999 Sun Microsystems, Inc. Некоторая часть Copyright ╘ 1999 Netscape Communications Corp. Все Права Зарезервированы.


Этот сайт использует фрэймы, но Ваш браузер их не поддерживает.
По этой гиперссылке Вы можете перейти на страницу "Оглавление".