Объект Date
Изменен в Navigator 3.0.
Позволяет вам работать с датой и временем.
Объект document
Изменен в Navigator 3.0.
Содержит информацию о текущем документе и обеспечен методами отображения HTML-документа.
Объект form (массив forms)
Изменен в Navigator 3.0.
Позволяет пользователям вставлять текст и делать изменения из объектов формы таких как графические опции, селекторные кнопки и списки элементов. Вы можете также использовать форму для отправки данных серверу.
Объект frame (массив frames)
Изменен в Navigator 3.0.
Окно, которое может показывать на одном экране несколько независимо прокручиваемых фреймов, каждый из которых имеет свой собственный URL. Фреймы могут указывать на различные URL'и и быть ссылкой других URL'ей, все внутри одного экрана.
Объект hidden
Изменен в Navigator 3.0.
Текстовый объект формы, который не отображается в HTML форме. Объект hidden используется для передачи пар имя/значение при загрузке формы.
Объект history
Содержит информацию о URL'ях, которые клиент посещал внутри окна. Эта информация сохраняется и доступна через меню Go Navigator'а.
Объект link (массив links)
Изменен в Navigator 3.0.
Кусок текста или картинка, определенные как гипертекстовая ссылка. При выборе пользователем ссылки в тексте, в окно загружается документ, соответствующий этой гипертекстовой ссылке.
Объект location
Изменен в Navigator 3.0.
Содержит информацию о текущем URL.
Объект Math
Изменен в Navigator 3.0.
Встроенный объект, имеющий свойства и методы для математических констант и функций. Например, свойство PI объекта Math имеет значение Пи.
Объект navigator
Изменен в Navigator 3.0.
Содержит информацию о используемой версии Navigator'а.
Объект password
Изменен в Navigator 3.0.
Текстовое поле в HTML форме, значение которого на экране отображается звездочками (*). Когда пользователь вводит текст в это поле, звездочки (*) скрывают введенное значение.
Объект radio
Изменен в Navigator 3.0.
Установка статических кнопок (кнопок radio) в HTML форме. Установка кнопок radio позволяет пользователю выбрать один пункт из списка.
Объект reset
Изменен в Navigator 3.0.
Кнопка сброса (кнопка reset)в HTML форме. Кнопка reset сбрасывает все элементы в форме в их значения, установленные по умолчанию.
Объект submit
Изменен в Navigator 3.0.
Кнопка передачи данных (кнопка submit) в HTML форме. Кнопка submit вызывает передачу формы.
Объект text
Изменен в Navigator 3.0.
Поле ввода текста в HTML форме. Текстовое поле позволяет пользователю вводить слова, фразы или числовой ряд.
Объект textarea
Изменен в Navigator 3.0.
Многострочное поле ввода текста в HTML форме. Поле textarea позволяет пользователю вводить слова, фразы или числа.
Объект window
Изменен в Navigator 3.0.
Объект верхнего уровня для групп объектов document, location и history.
Объекты JavaScript
Наталия Бельтикова, Ирина Кузина (РНЦ "Курчатовский институт")
Операторы === и !==
Операторы === и !== проверяют на соответствие ( и не соответствие ) операнды одинаковых типов ( т.е. например оба операнда должны быть типа String ). При сравнении с помощью этих операторов не происходит преобразования типов. Их использование необходимо, когда нужно убедиться, что оба операнда имеют одинаковый тип и одинаковые ( или разные ) значения.
Пример:
10 === '10'
вернет false, тогда как
10 == '10'
вернет true.
Описание:
Метод acos возвращает числовое значение между 0 и Пи. Если значение number находится за пределами данного диапазона, возвращаемое значение всегда будет 0.
Метод alert используется для отображения сообщения, не требующего решения пользователя. Аргумент message определяет сообщение, которое содержит диалоговое окно.
Хотя alert является методом объекта window вам не нужно определять windowReference, при его вызове. Например, windowReference.alert() необязательно.
Метод anchor используется с методами write или writeln для программного создания и отображения якоря в документе. Якорь создается с помощью метода anchor, а write или writeln используется для отображения якоря в документе.
В синтаксисе строка text представляет собой текст, который увидит пользователь. Строка nameAttribute представляет собой атрибут NAME тага <A>.
Якоря, созданные с помощью метода anchor становятся элементами массива anchors. Информацию о массиве anchors смотрите в объекте .
Метод asin возвращает числовое значение между -Пи/2 и Пи/2. Если значение number находится за пределами данного диапазона, возвращаемое значение всегда будет 0.
Метод atan возвращает числовое выражение между -Пи/2 и Пи/2.
Этот метод выполняет действие равносильное выбору пользователем кнопки Back в окне Navigator'а. Метод back также равносилен history.go(-1).
Для форматирования и отображения строки в документе метод big используется с методами write или writeln.
Для форматирования и отображения строки в документе метод blink используется с методами write или writeln.
Метод blur используется для удаления фокуса с указанного элемента формы.
Для форматирования и отображения строки в документе метод bold используется с методами write или writeln.
Символы в строке индексируются слева направо. Индексом первого символа является 0, индексом последнего символа - stringName.length-1. Если вы указали index превышающий количество символов в строке, JavaScript возвратит пустую строку.
Органайзер
<SCRIPT LANGUAGE="JavaScript">
<!--
// Alex Alexandrov wrote:
// This scrpt was taken from a book called "Learn Advanced Java Script" Chapter 14.
// The guys who wrote that book wanted us to leave a copyright. So here it goes:
// THIS SCRPIT IS COPYRIGHTED//
// Be AWARE TO PUT IT ON YOUR PAGE//
// Boolean variable specified if alert should be displayed if cookie exceeds 4KB
var caution = false
// name - name of the cookie
// value - value of the cookie
// [expires] - expiration date of the cookie (defaults to end of current session)
// [path] - path for which the cookie is valid (defaults to path of calling document)
// [domain] - domain for which the cookie is valid (defaults to domain of calling document)
// [secure] - Boolean value indicating if the cookie transmission requires a secure transmission
// * an argument defaults when it is assigned null as a placeholder
// * a null placeholder is not required for trailing omitted arguments
function setCookie(name, value, expires, path, domain, secure) {
var curCookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "")
if (!caution (name + "=" + escape(value)).length <= 4000)
document.cookie = curCookie
else
if (confirm("Cookie превышает 4KB и будет вырезан !"))
document.cookie = curCookie
}
// name - name of the desired cookie
// * return string containing value of specified cookie or null if cookie does not exist
function getCookie(name) {
var prefix = name + "="
var cookieStartIndex = document.cookie.indexOf(prefix)
if (cookieStartIndex == -1)
return null
var cookieEndIndex = document.cookie.indexOf(";", cookieStartIndex + prefix.length)
if (cookieEndIndex == -1)
cookieEndIndex = document.cookie.length
return unescape(document.cookie.substring(cookieStartIndex + prefix.length, cookieEndIndex))
}
// name - name of the cookie
// [path] - path of the cookie ( must be same as path used to create cookie)
// [domain] - domain of the cookie (must be same as domain used to create cookie)
// * path and domain default if assigned null or omitted if no explicit argument proceeds
function deleteCookie(name, path, domain) {
if (getCookie(name)) {
document.cookie = name + "=" +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT"
}
}
function fixDate(date) {
var base = new Date(0)
var skew = base.getTime()
if (skew > 0)
date.setTime(date.getTime() - skew)
}
function initCookie(monthName) {
// initializes cookie with the following format:
// ^1^^2^^3^^4^...^30^^31^
// initialize accumulative variable
var text = ""
for (var i = 1; i <= 31; ++i) {
text += "^" + i + "^"
}
var now = new Date()
fixDate(now)
// set time to one month (31 days) in the future
now.setTime(now.getTime() + 1000 * 60 * 60 * 24 * 31)
setCookie(monthName + "Calendar", text, now)
}
function getSpecificReminder(num, monthName) {
var prefix = "^" + num + "^"
var totalCookie = getCookie(monthName + "Calendar")
var startIndex = totalCookie.indexOf(prefix, 0)
var startData = totalCookie.indexOf("^", startIndex + 1) + 1
if (num == 31)
var endData = totalCookie.length
else
var endData = totalCookie.indexOf("^", startData)
return totalCookie.substring(startData, endData)
}
function setSpecificReminder(num, monthName, newValue) {
var prefix = "^" + num + "^"
var totalCookie = getCookie(monthName + "Calendar")
var startIndex = totalCookie.indexOf(prefix, 0)
var startData = totalCookie.indexOf("^", startIndex + 1) + 1
if (num == 31)
var endData = totalCookie.length
else
var endData = totalCookie.indexOf("^", startData)
var now = new Date()
fixDate(now)
// set time to one month (31 days) in the future
now.setTime(now.getTime() + 1000 * 60 * 60 * 24 * 31)
setCookie(monthName + "Calendar", totalCookie.substring(0, startData) + newValue + totalCookie.substring(endData, totalCookie.length), now)
}
function getInput(num, monthName) {
if (!getCookie(monthName + "Calendar"))
initCookie(monthName)
var newValue = prompt("Введите запись соответствующей данной дате:", getSpecificReminder(num, monthName))
if (newValue) // user did not cancel
setSpecificReminder(num, monthName, newValue)
}
function getTime() {
// initialize time-related variables with current time settings
var now = new Date()
var hour = now.getHours()
var minute = now.getMinutes()
now = null
var ampm = ""
// validate hour values and set value of ampm
if (hour >= 12) {
hour -= 12
ampm = "PM"
} else
ampm = "AM"
hour = (hour == 0) ? 12 : hour
// add zero digit to a one digit minute
if (minute < 10)
minute = "0" + minute // do not parse this number!
// return time string
return hour + ":" + minute + " " + ampm
}
function leapYear(year) {
if (year % 4 == 0) // basic rule
return true // is leap year
return false // is not leap year
}
function getDays(month, year) {
// create array to hold number of days in each month
var ar = new Array(12)
ar[0] = 31 // January
ar[1] = (leapYear(year)) ? 29 : 28 // February
ar[2] = 31 // March
ar[3] = 30 // April
ar[4] = 31 // May
ar[5] = 30 // June
ar[6] = 31 // July
ar[7] = 31 // August
ar[8] = 30 // September
ar[9] = 31 // October
ar[10] = 30 // November
ar[11] = 31 // December
// return number of days in the specified month (parameter)
return ar[month]
}
function getMonthName(month) {
// create array to hold name of each month
var ar = new Array(12)
Основы технологии EJB
Для того чтобы понять, как работает и как устроена EJB-система, сначала необходимо рассмотреть ее основные части: EJB-компоненту (component), EJB-контейнер (container) и EJB-объект (object).
EJB-компонента (The Enterprise JavaBeans component)
Отдельная EJB-компонента представляет цобой компоненту в том же смысле что и традиоционный JavaBeans ``bean'' (``зерно''). Компоненты EJB выполняются внутри EJB-контейнера, который, в свою очередь, выполняется внутри EJB-сервера. Любой сервер, который в состоянии поддерживать EJB-контейнеры и предоставлять им необходимые сервисы, может быть EJB-сервером (то есть многие из существующих серверов могут быть просто расширены до поддержки Enterprise JavaBeans).
EJB-компонента представляет из себя Java-класс, который реализует некоторую бизнес-логику. Все остальные классы в EJB-системе либо реализуют поддержку клиент/сервер взаимодйествий между компонентами, либо реализуют некоторые сервисы для компонент.
EJB-контейнер (The Enterprise JavaBeans container)
EJB-контейнер -- это то место, где ``живет'' EJB-компонент. EJB-контейнер реализует для находящихся в нем компонент такие сервисы как транзакции (transaction), управление ресурсами, управление версиями компонент, их мобильностью, настраиваемостью, мобильностью, жизненным циклом. Так как EJB-контейнер реализует все эти функции, то разработчик EJB-компонент может не реализовывать их самостоятельно, а просто вызывать соответсвующие методы у контейнера (правила вызова методов у контейнера описываются в спецификации). Как правило, в одном EJB-контейнере живет несколько однотипных EJB-компонент.
EJB-объект (EJB-object) и удаленный интерфейс (remote interface)
Клиентские приложения вызывают методы на удаленных EJB-компонентах через EJB-объект (EJB-object). EJB-объект реализует ``удаленный интерфейс'' EJB-компоненты на сервере. Суть в том, что находящаяся на сервере EJB-компонента, помимо бизнес-функций, ради которых она была разработана, должна реализовывать также некоторые функции, определяемые спецификацией, которые служат для ``управления'' EJB-компонентой со стороны контейнера. EJB-объект реализует лишь бизнес-интерфейс для EJB-компоненты, являясь, в некотором смысле, ``промежуточным'' звеном между клиентом и EJB-компонентой.
EJB-объекты и EJB-компоненты представляют собой разные классы, хотя ``снаружи'' (при взгляде на их интерфейсы), они выглядят одинаково. Это происходит потому, что они реализуют один и тот же интерфейс (а именно, интерфейс, описанный для EJB-компоненты). Однако при этом они выполняют совершенно разные функции. EJB-компонента выполняется на сервере, внутри EJB-контейнера и реализует бизнес-логику, в то время как EJB-объект выполняется у клиента и удаленно вызывает методы у EJB-компоненты.
В качестве поясняющего примера рассмотрим видеомагнитофон. Предположим, что он является EJB-компонентой. EJB-объект, в таком случае, является аналогом пульта управления (remote control) этого магнитофона. У пульта управления есть все те же кнопки, что и на передней панели видеомагнитофона. Нажатие кнопки на пульте управления приведет к такому же эффекту, что и нажатие кнопки, расположенной на самом магнитофоне, но в результате только магнитофон, а не пульт управления, начнет выполнять функции.
Как работает система
Разработчику, однако, не нужно самому реализовывать EJB-объект. Этот класс создается специальным кодогенератором, поставляемым вместе в EJB-контейнером. Как уже было сказано, EJB-объект (созданный с помощью сервисов контейнера) и EJB-компонента (созданная разработчиком), реализуют один и тот же интерфейс. В результате, когда приложение-клиент хочет вызвать метод у EJB-компоненты, то сначала вызывается аналогичный (по имени) метод у EJB-объекта, что находится на стороне клиента, а тот, в свою очередь, связывается с удаленной EJB-компонентой и вызывает у нее этот метод (с теми же аргументами).
Поддержка Unicode:
В строках теперь стало возможным использование любых символов из таблицы Unicode, которые кодируются как шесть ASCII символов: \u и 4 цифры в шестнадцатеричной кодировке, например, \u0041 - латинская буква A из таблицы Unicode. Каждая такая последовательность добавляет только один символ к строке. Функции escape и unescape не подвергались изменениям и не используют Unicode - последовательности.
Следующий пример выведет на экран символ "копирайт" и строку "Netscape Communicator": alert("\u00A9 Netscape Communicator");
Следующая таблица содержит список наиболее часто используемых специальных символов и их коды в Unicode:
\u0009 | Tab | <TAB> |
\u000B | Vertical Tab | <VT> |
\u000C | Form Feed | <FF> |
\u0020 | Space | <SP> |
\u000A | Line Feed | <LF> |
\u000D | Carriage Return | <CR> |
\u000b | Back Space | <BS> |
\u0009 | Horizontal Tab | <HT> |
\u0022 | Double Quote | " |
\u0027 | Single Quote | ` |
\u005C | Backslash | \ |
Вы можете использовать Unicode для отображения символов в различных языках или технических символов. Для отображения символов Unicode у клиента должны быть установлены шрифты Unicode. Некоторые ОС, например Windows 95, поддерживают Unicode лишь частично.
Постановка задачи
Необходимо на основе стандартного броузера реализовать клиентскую часть запросной системы к базе данных. Пользователю система должна предоставлять:
Одновременное формирование произвольного числа запросов с использованием объектов HTML-формы; Автоматическое запоминание и инициализацию критериев текущего запроса; Просмотр, корректировку и сброс критериев текущего запроса; Создание нового запроса, удаление и выполнение текущего запроса.
Кроме того, клиентская часть системы должна быть способна к быстрому расширению и модификации, что с точки зрения разработчика означает, что ее код должна быть по возможности универсален и открыт.
Здесь мы привели только небольшой ряд требований, который может быть предъявлен к реальной запросной системе, ориентируясь на их достаточную распространенность. Однако ничто не мешает включить сюда, например, требование автоматической верификации введенной пользователем информации или возможность изменения логических отношений между критериями запроса. Только ограничение на объем статьи, а также нежелание автора уходить в описание пусть интересных, но все-таки второстепенных деталей, повлияло на исключение их из постановки задачи.
Необходимо также подчеркнуть, что в данной работе не рассматривается построение серверной части запросной системы. В этом смысле, вопрос о технологии, которая будет использована на сервере остается открытым и зависит, по-видимому, от требований предъявляемых конкретной разработкой. В данной же работе делается ориентация на обработку введенной информации CGI-скриптом.
Пример персонализации пользователя
Исходный код скрипта:
var username = GetCookie('username'); if (username == null) { username = prompt(' Пожалуйста, введите Ваше им\я\n (в противном случае нажмите cancel)',""); if (username == null) { alert('Ну хорошо, тогда я буду звать Вас ВебСёрфером'); username = 'ВебСёрфер'; } else { pathname = location.pathname; myDomain = pathname.substring(0,pathname.lastIndexOf('/')) +'/'; // Установка параметра expire на год вперед. var largeExpDate = new Date (); largeExpDate.setTime(largeExpDate.getTime() + (365 * 24 * 3600 * 1000)); SetCookie('username',username,largeExpDate,myDomain); } } function getCookieVal (offset) { var endstr = document.cookie.indexOf (";", offset); if (endstr == -1) endstr = document.cookie.length; return unescape(document.cookie.substring(offset, endstr)); } 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) return getCookieVal (j); i = document.cookie.indexOf(" ", i) + 1; if (i == 0) break; } return null; } function SetCookie (name, value) { var argv = SetCookie.arguments; var argc = SetCookie.arguments.length; var expires = (argc > 2) ? argv[2] : null; var path = (argc > 3) ? argv[3] : null; var domain = (argc > 4) ? argv[4] : null; var secure = (argc > 5) ? argv[5] : false; document.cookie = name + "=" + escape (value) + ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + ((path == null) ? "" : ("; path=" + path)) + ((domain == null) ? "" : ("; domain=" + domain)) + ((secure == true) ? "; secure" : ""); } document.write('<p align=center>Здравствуйте, ' + username + '</p>');
document.write('');
02.08 - 02.08 - 02.08 - 02.08 - 02.08 - 01.08 - 01.08 - 01.08 - 01.08 - 01.08 - 01.08 - 01.08 - 01.08 - 01.08 - 01.08 - 31.07 - 31.07 - 31.07 - 31.07 - 31.07 -
Архив новостей
(66)
2 Август, 17:53
(19)
2 Август, 17:51
(34)
2 Август, 15:40
(42)
2 Август, 15:35
(1)
2 Август, 14:54
(3)
2 Август, 14:34
(3)
2 Август, 14:15
(2)
2 Август, 13:34
(7)
2 Август, 13:04
(3)
2 Август, 12:28
BrainBoard.ru
Море работы для программистов, сисадминов, вебмастеров.
Иди и выбирай!
google.load('search', '1', {language : 'ru'}); google.setOnLoadCallback(function() { var customSearchControl = new google.search.CustomSearchControl('018117224161927867877:xbac02ystjy'); customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET); customSearchControl.draw('cse'); }, true);
IT-консалтинг | Software Engineering | Программирование | СУБД | Безопасность | Internet | Сети | Операционные системы | Hardware |
PR-акции, размещение рекламы — , тел. +7 495 6608306, ICQ 232284597 | Пресс-релизы — |
This Web server launched on February 24, 1997 Copyright © 1997-2000 CIT, © 2001-2009 |
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. |
А Вы знаете, что в нашей компании, Вы сможете заказать по самой выгодной цене в Москве. |
Примеры простых скриптов для клиента на языке JavaScript.
Составитель - Бельтикова Н.В., РНЦ "Курчатовский институт"
Простые скрипты
(4 примера); (2 примера); (2 примера); ; ; ; (2 примера); (3 примера). (3 примера).
Примеры скриптов посложнее
; (3+3 примера); .
Примеры скриптов от Алексея Александрова
; .
Источники информации
"Справочник Web-мастера", Стивен Спейнаур и Валери Куэрсиа,
Производительность
Плохая производительность - одно из основных обвинений противников Java. Я не разделяю этой позиции. Я убежден в том, что от можно добиться хорошей производительности для программы,написанной на Java, динамически создающей изображения. Как разработчик программного обеспечения, я могу дать вам совет: если вас не устраивает производительность, покупайте более совершенные компьютеры.
Расширение объекта Date
В предыдущих версиях JavaScript формат даты был зависим от платформы и различных установок. В новой реализации объект Date полностью платформо-независим. Объект Date теперь поддерживает дату и время в формате UTC ( Universal Coordinated Time ). Дата задается как количество миллисекунд, прошедших с 1 января 1970 года. День содержит 86400000 миллисекунд.
Следующий пример возвращает разницу межде timeA и timeB в миллисекундах:
timeA = new Date(); alert("подождем какое-то время"); timeB = new Date(); timeDifference = timeB - timeA;
Для работы с миллисекундами были добавлены методы getMilliseconds() и setMilliseconds(num_ms), getUTCMilliseconds() и setUTCMilliseconds(num_ms). Для устранения проблеммы 2000 года добавлены функции setFullYear, getFullYear, setUTCFullYear и getUTCFullYear. getFullYear возвращает полный год, например 1998, а setFullYear - устанавливает. Методы setYear и getYear оставлены для обратной совместимости.
Реализация
1. Объекты клиентской части
Язык JavaScript, базируется на объектно-ориентированной модели программирования, хотя его и нельзя назвать полноценным объектным языком. Так например, в этом языке отсутствует понятие класса. Тем не менее, наиболее эффективное решение указанной задачи видится в применении именно объектных возможностей JavaScript.
Анализ требований, предъявляемых нашей задачей, выявляет три базовых объекта, которые необходимо реализовать на JavaScript:
массив запросов [array_of_query]; запрос [query]; критерий запроса [criterion].
В языке JavaScript не предусмотрены конструкции для определения сложных типов данных, поэтому пользовательские объекты конструируются с помощью функций. Ниже приведена реализация средствами JavaScript конструктора первого в этом списке объекта - массив запросов [array_of_query].
function array_of_query() { // Свойства this.array_of_query = new Array() // Вводит массив объектов (запросов) this.id = -1 // Определяет уникальный идентификатор запроса // Методы this.array_size = array_size // Возвращает кол-во запросов в массиве this.add_query = add_query // Добавляет запрос в массив запросов this.del_query = del_query // Удаляет запрос из массива запросов this.index_query = index_query // Возвращает индекс запроса в массиве запросов }
Как видно, в данном конструкторе определены 2 свойства (переменные) и 4 метода. Конструирование конкретного объекта (или в терминологии объектно-ориентированного программирования - определение экземпляра класса) осуществляется в JavaScript следующим способом:
имя_объекта = new имя_функции_конструктора()
Для пояснения отдельных моментов, нам потребуется конкретный экземпляр такого объекта, поэтому сейчас полезно его ввести:
stack = new array_of_query()
Теперь самое время сказать несколько слов о реализации методов. Методы в JavaScript вводятся как обычные функции, причем из-за невозможности полной инкапсуляции метода в конкретный класс, наименование функционально подобных методов для различных конструкторов-классов должно быть различным. Ниже приведен код метода вышеприведенного объекта, который добавляет новый запрос в массив запросов.
function add_query(name) { this.id = this.id+1 this.array_of_query[this.array_of_query.length] = new query(name, this.id) return this.id
}
Здесь надо обратить внимание на наличие формального параметра в заголовке реализации функции, и на его отсутствие при описании функции в конструкторе объекта, которому принадлежит метод. Формальным параметром данного метода является наименование нового запроса, который вместе с генерируемым автоматически уникальным идентификатором, передается в конструктор, второго важного объекта - [query]. Приведем и его код:
function query(name,id) { // Свойства this.query_name = name // Имя запроса this.query_id = id // Уникальный идентификатор запроса this.query = new Array(); // Вводит массив объектов (критериев запроса) // Методы this.query_size = query_size // Возвращает количество критериев в запросе this.ini_criterion = ini_criterion; // Осуществляет явный ввод нового критерия this.add_criterion = add_criterion; // Добавляет новый критерий из формы this.del_criterion = del_criterion; // Удаляет критерий }
Итак, данный конструктор вводит в массив запросов новый запрос, который характеризуется именем (задаваемым пользователем и, вообще говоря, не обязательно уникальным) и уникальным идентификатором запроса, который генирируется автоматически методом объекта [array_of_query]. Необходимо отметить, что объекты [query] нельзя вводить явным способом., и единственный корректный способ ввода нового запроса - использование метода add_query.
Таким образом, после осуществления всех описанных выше шагов, в массив запросов всегда можно ввести запрос, который будет иметь имя, уникальный идентификатор, и включать в себя, на этом этапе, нулевое количество критериев запроса.
Перед рассмотрением третьего, наиболее важного объекта клиентской части - критерий запроса [criterion], необходимо дать дополнительные пояснения. Дело в том, что критерий запроса, как мы увидим, характеризуется сравнительно большим количеством свойств. Более того, конструктор этого объекта, в отличии от двух предыдущих, не может быть достаточно универсальным, и имеет привязку к требованиям, предъявляемым конкретной информационной системой.
С другой стороны, все свойства критерия запроса, за исключением его имени и значения, являются по сути - обслуживающими (действительно, программе, которая будет анализировать передаваемую броузером информацию, достаточно передать только имя поля формы и его значение). Но тот факт, что эти свойства, с формальной точки зрения, являются второстепенными, совсем снижает их важность.
Необходимо также разобраться в том, каким образом мы будем получать информацию о свойствах критерия запроса. Единственной информацией, которая нам требовалась ранее, было имя запроса и источник получения этой информации очевиден - это пользователь. Но пользователь не может задавать какие-либо свойства критерия запроса, все свойства критерия должна распознаваться и запоминаться незаметно для него.
В нашей задаче критерий запроса задается через произвольный объект HTML формы. Отсюда ясно, что вся информация о свойствах критерия запроса должна быть сокрыта именно в этом объекте, который и будут выступать главными поставщиком информации о свойствах критерия. Такой подход позволит достичь требуемого - распознование свойств критериев запроса будет проходить автоматически и незаметно для пользователя.
Конкретный способ решения этой задачи будет показан ниже, а пока приведем формальное описание (конструктор) третьего объекта - критерий запроса [criterion]:
function criterion(obj, row) { this.name=obj.name; // Имя объекта (для CGI-скрипта) this.title_name=obj.title_name; // Наименование объекта this.value=obj.value; // Значение объекта switch (obj.type) { // Тип объекта case "text": { this.type="text"; break } case "radio": { this.type="radio"; this.id=obj.id; // Для идентификации радио-кнопки this.title_value=obj.title_value; break } case "checkbox": { this.type="checkbox"; this.title_value=obj.title_value; break; } case "select-one": { this.type="select-one"; this.title_value=obj.options[obj.selectedIndex].text; this.index=index; break } case "select-multiple": { this.value=obj.options[row].value; this.type="select-multiple"; this.title_value=obj.options[row].text; this.index=obj.options[row].index; break } case "textarea": { this.type="textarea"; break } } this.service=obj.service; // Функциональное назначение объекта this.modif = modif; }
Еще раз подчеркнем, что этот конструктор ориентирован на реализацию только тех требований, которые были описаны в начале статьи. Так например, в нем отсутствует составляющая, которая может задавать реляционные отношения между различными критериями запроса .
К этому моменту осуществленно описание трех JavaScript объектов, которыми будет оперировать клиентская часть информационной системы. Этих трех объектов вполне достаточно для полной реализации всех заявленных требований. Мы не рассматривали подробно назначение всех методов этих объектов, поскольку сейчас важно сформулировать общий подход, опустив второстепенные детали. С другой стороны, количество этих методов совсем не велико, их назначение в большинстве случаев очевидно, а программная реализация крайне проста.
2. Режим HTML-формы
При построении развитой системы формирования запросов к БД возникает необходимость различной обработки HTML-форм. Наиболее распространенной задачей, как нам теперь уже известно, будет задача запоминания новых критерив запроса, и инициализации ранее введенных критериев. Однако эта задача не единственная.
Даже оставаясь в рамках той постановки задачи, которая была определена выше, возникает, например, задача переключения между различными запросами, которые могут одновременно формироваться в системе. Например, при формировании критериев запроса мы можем использовать форму, содержащую объект типа select-multiple (). С другой стороны, этот же объект select-multiple может быть использован в форме, которая будет выводить список всех имеющихся в данный момент запросов. Очевидно, что объекты таких форм, должны обрабатываться по разному. В первом случае, необходимо запомнить новый критерий запроса, во втором случае, сделать выделенный запрос текущим.
Самое очевидное и простое решение этой проблемы заключается в введении переменной, которая будет определять режим (способ обработки) формы. Тогда описанная выше ситуация, может быть разрешена, например, следующим образом:
<form ... rezim="1"> // для формы содержащей критерии запроса <form ... rezim="2"> // для форма в которой выводится список запросов
В функцию же, которая будет заниматься обработкой форм, достаточно включить следующий код:
function process_of_form(obj) { ... if (stack.kol() != 0) { // Проверяем наличие хоть одного запроса // Выясняем режим формы switch (obj.rezim) { case "1": { rezim_1(obj); break } // Функция обработки для форм с критериями запроса case "2": { rezim_2(obj); break } // Функция обработки для формы списка запросов default: { break } } // end switch } // end if ... }
Переменная, которая передается данной функции в качестве параметра функции, указывает на обрабатываемую форму, и после выяснения режима обработки этой формы, вызывается соответствующая функция. Содержимое полей форм, в которых не прописан режим обработки, просто игнорируется.
3. Размещение свойств критерия запроса в объектах HTML-формы
Рассмотрим теперь более подробно такую форму, которая содержит объекты, непосредственно участвующие в формировании критериев запроса к БД. Нас будут интересовать свойства, которые необходимо определить в объектах такой формы, и которые мы ранее назвали обслуживающими. Прежде чем привести содержимое одного из таких объектов, напомним, что именно объект формы выступает в качестве формального параметра для конструктора критерий запроса. Итак, содержимое объекта формы <input type="text"> выглядит следующим образом:
<input type="text" name="p1_t1" title_name="Поле ввода 1" service="0" ...>
Это самый простой объект формы, и назначение большинства переменных, которые прописаны в теге, стандартны. Пояснения заслуживают только два свойства, которые были введены нами дополнительно: title_name и service. Свойство (переменная) title_name отвечает за наименование поля ввода и используется во время просмотра критериев текущего запроса.
Переменная service задает функциональное назначение объекта. Действительно, в информационной системе может потребоваться и функциональное разделение критериев. В частности, может потребоваться ввод сервисной информации, которая определяет, например, способ вывода инормации, но никак не влияет на содержимое самого запроса к БД. Такого рода служебная информация должна отделяться от критериев запроса, и выводиться отдельно при просмотре содержимого запроса. Задавая различные значения переменной service мы решим эту задачу.
Рассмотрим теперь более сложный объект формы <input type="radio">:
<input type="radio" title_name="Радио-кнопка 1" name="p1_r1" service="0" id="p1_r1_1" title_value="Выбор 1" ...>
Помимо уже рассмотренных, его содержимое включает дополнительные переменные: id и title_value. Переменная id необходима для уникальной идентификации кнопок, принадлежащих одной селекторной группе, т.к. для всех кнопок, принадлежащих такой группе, значение переменной name должно быть одинаковым. В переменной title_value хранится наименование конкретной селекторной кнопки (в отличии от title_name, которое задает общее наименование группы селекторных кнопок), которое опять же потребуется при просмотре информации.
Представленная ниже таблица демонстрирует необходимые дополнительные переменные для различных объектов формы:
Наименование переменной /Тип объекта формы | text | Radio | checkbox | select-one | select-multiple | Textarea |
Name | + | + | + | + | + | + |
Title_name | + | + | + | + | + | + |
Id | - | + | - | - | - | - |
Title_value | - | + | + | - | - | - |
Service | + | + | + | + | + | + |
Для наглядности преимуществ, которые дает описанный выше подход, продемонстрируем два базовых алгоритма, которые могут быть использованы в подобной ситеме. Внешняя простота этих алгоритмов основывается на внутренней продуманности всей системы.
Первый из этих алгоритмов, занимается обработкой текстовых полей тех форм, которые содержат критерии запроса:
function do_text(current,obj) { // Определяем количество критериев в текущем запросе var kol=current.crit_kol() var flag=0, i=0; while (i<kol && flag == 0) { if (obj.name == current.query[i].name) { if (obj.value == "") current.del(current.query[i].name) else current.query[i].modif(obj.value) flag=1 } else i++; } if (flag == 0 && obj.value != "") current.add(obj) }
В качестве формальных параметров в функцию передается две переменные: current и obj. Переменная current это просто сокращенное название объекта текущий запрос, и может быть определена следующим образом:
current=stack.array_of_query[stack.index_query(UK)],
где UK - некоторая глобальная переменная, значением которой является уникальный идентификатор текущего запроса. Значение этой переменной определяется в момент обработки формы, которая выводит список запросов, и в которой, как мы уже знаем, переменная rezim имеет значение 2. Переменная obj,как и в функции process_of_form, указывает на обрабатываемую форму.
Алгоритм инициализации, например, поля checkbox также крайне прост:
function ini_checkbox(current,obj) { var kol=current.crit_kol() var flag=0, i=0; while (i<kol && flag == 0) { if (obj.name == current.query[i].name) { obj.checked=true; flag=1 } else i++; } }
5. Формирование формы для отправки на сервер
Последний важный вопрос, который осталось рассмотреть, касается создания формы для отправки на сервер. Здесь есть два момента, на которые следует обратить внимание.
Во-первых, форма, которая будет отправляться на сервер (т.е. форма, к которой мы будем применять метод submit() и объекты которой будут обрабатываться CGI-скриптом) должна создаваться в новом экземпляре броузера. Именно такой подоход позволяет нам обеспечить независимое формирование и выполнение произвольного числа запросов. Поэтому перед созданием формы, необходимо применить метод open(), который создаст новый экземпляр броузера.
Во-вторых, объекты отсылаемой на сервер формы должны состоять только из двух полей: имени переменной (name) и ее значении (value). Запись в форму, производится динамически, в цикле по всем критериям запроса, и, например для имени критерия запроса, выглядит следующим образом:
doc.writeln(""+stack.array_of_query [stack.index_query(UK)].query[i].name+""),
где i - переменная цикла по всем критериям текущего запроса.
Русские буквы в файлах properties.
Для чтения файлов properties используются методы загрузки ресурсов, которые работают специфичным образом. Собственно для чтения используется метод Properties.load, который не использует file.encoding (там кодировка жёстко указана), поэтому единственный способ указать русские буквы - использовать формат "\uxxxx" и утилиту .
Метод Properties.save работает по разному в версиях JDK 1.1 и 1.2. В версиях 1.1 он просто отбрасывал старший байт, поэтому правильно работал только с англицкими буквами. В 1.2 делается обратное преобразование в "\uxxxx", так что он работает зеркально к методу load.
Русские буквы в исходниках Java-программ.
Как уже упоминалось, при выполнении программы используется Unicode. Исходные же файлы пишутся в обычных редакторах. Я пользуюсь Far-ом, у Вас, наверняка есть свой любимый редактор. Эти редакторы сохраняют файлы в 8-битовом формате, а значит, что к этим файлам также применимы рассуждения, аналогичные приведённым выше. Разные версии компиляторов немного по разному выполняют преобразование символов. В ранних версиях JDK 1.1.x используется настройка file.encoding, которую можно поменять при помощи нестандартной опции -J. В более новых (как сообщил - начиная с 1.1.4) был введён дополнительный параметр -encoding, при помощи которого можно указать используемую кодировку. В скомпилированных классах строки представлены в виде Unicode (точнее в модифицированном варианте формата UTF8), так что самое интересное происходит при компиляции. Поэтому, самое главное - выяснить, в какой кодировке у Вас исходники и указать правильное значение при компиляции. По умолчанию будет использован всё тот же пресловутый file.encoding. Пример вызова компилятора: javac -encoding=KOI8_R ...
Кроме использования этой настройки есть ещё один метод - указывать буквы в формате "\uxxxx", где указывается код символа. Этот метод работает со всеми версиями, а для получения этих кодов можно использовать стандартную утилиту .
Русские буквы в Servlet-ах.
Ну, для чего эти самые Servlet-ы нужны, я думаю, Вы в курсе. Если нет - то лучше сначала прочитать документацию. Здесь же рассказывается только об особенностях работы с русскими буквами.
Так в чём же особенности? Когда Servlet посылает ответ клиенту, есть два способа послать этот ответ - через OutputStream (getOutputStream()) или через PrintWriter (getWriter()). В первом случае Вы записываете массивы байтов, поэтому применимы вышеописанные методы записи в файл. В случае же PrintWriter, он использует установленную кодировку. В любом случае необходимо правильно указать используемую кодировку при вызове метода setContentType(), для того, чтобы было правильное преобразование символов на стороне сервера. Это указание должно быть сделано перед вызовом getWriter() или перед первой записью в OutputStream. Пример:
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=windows-1251")); PrintWriter out = response.getWriter(); // Отладочный вывод названия кодировки для проверки out.println( "Encoding: " + response.getCharacterEncoding() ); ... out.close();
Это по поводу отдачи ответов клиенту. Со входными параметрами, к сожалению не так просто. Входные параметры кодируются броузером побайтно в соответствии с MIME-типом "application/x-www-form-urlencoded". Как рассказал русские буквы броузеры кодируют, используя текущую установленную кодировку. Ну и, разумеется, ничего о ней не сообщают. Соотвественно, например, в JSDK 2.0 и 2.1 это никак не проверяется. Собственно для раскодирования используются методы HttpUtils.parsePostData() и HttpUtils.parseQueryString(), которые просто обнуляют старший байт. Это зарегистрированная ошибка в JSDK (). К сожалению, эту ошибку закрыли как "Will not be fixed", с тем оправданием, что, дескать, раз в RFC на эту тему ничего не сказанно, то и делать мы ничего не будем. Однако, после переписки наших разработчиков в майл-листе дело, похоже, сдвинулось с мёртвой точки. По крайней мере на словах было обещано включить метод установки кодировки в спецификацию JSDK 2.3.
Пока же приходится обходиться своими средствами. Оригинальный способ работы с кодировками предлагает Russian Apache - расписано, как именно. Судя по отзывам, не имеет проблем с русскими и система .
решение проблемы так же предложил Вячеслав Педак.
Ну а самый простейший вариант извлечь таки символы - передавать в комплекте параметров имя кодировки (или, если вы уверены в текущей кодировке броузера, использовать предопределённую кодировку) и использовать метод перекодировки символов:
public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { // Кодировка сообщений // В связке MSIE 4.01 SP1 -> JSDK 2.0 servletrunner.exe всегда выдаёт "ISO-8859-1" String requestEnc = request.getCharacterEncoding(); // Некоторые servlet engine, не мудрствуя лукаво, возвращают null if( requestEnc==null ) requestEnc="ISO-8859-1"; String clientEnc = request.getParameter("charset"); if( clientEnc==null ) clientEnc="Cp1251"; String value = new String(request.getParameter("value").getBytes(requestEnc),clientEnc);
работает. :-)
В общем, опыт в написании Servlet-ов у меня небольшой, так что Ваши замечания будут приветствоваться.
Session и Entity beans
Существует два различных типа ``бинов'': session и entity. Рассмотрим их более подробно.
Session bean
Session bean представляет собой EJB-компоненту, связанную с одним клиентом. ``Бины'' этого типа, как правило, имеют ограниченный срок жизни (хотя это и не обязательно), и редко участвуют в транзакциях. В частности, они обычно не восстанавливаются после сбоя сервера. В качестве примера session bean можно взять ``бин'', который живет в веб-сервере и динамически создает HTML-страницы клиенту, при этом следя за тем, какая именно страница загружена у клиента. Когда же пользователь покидает вэб-узел, или по истечении некоторого времени, session bean уничтожается. Несмотря на то, что в процессе своей работы, session bean мог сохранять некоторую информацию в базе данных, его предназачение заключается все-таки не в отображении состояния или в работе с ``вечными объектами'', а просто в выполнении некоторых функций на стороне сервера от имени одного клиента.
Entity bean
Entity bean, наоборот, представляет собой компоненту, работающую с постоянной (persistent) информацией, хранящейся, например, в базе данных. Entity beans ассоциируются с элементами баз данных и могут быть доступны одновременно нескольким пользователям. Так как информация в базе данных является постоянной, то и entity beans живут постоянно, ``выживая'', тем самым, после сбоев сервера (когда сервер восстанавливается после сбоя, он может восстановить ``бин'' из базы данных).
Например, entity bean может представлять собой строку какой-нибудь таблицы из базы данных, или даже результат операции SELECT. В объектно-ориентированных базах данных, entity bean может представлять собой отдельный объект, со всеми его атрибутами и связями.
Клиент создает на EJB-сервере объекты и работает с ними так же, как если бы это были локальные объекты. Это до предела упрощает разработку клиентов -- практически нет разницы между написанием клиента для локальной машины и для клиента EJB-сервера. Разработчик может легко создавать, использовать и уничтожать объекты, а эти объекты, в свою очередь, выполняются на сервере. Итак, session beans в большинстве своем работают с информацией, относящейся к ``диалогу'' между клиентом и сервером, в то время как entity beans представляют собой экземпляры данных и работают с ``постоянными'' данными из баз данных.
Каждый экземпляр ``бина'' имеет свой уникальный идентификатор. Для entity объектов уникальный идентификатор, как правило, совпадает с (или каким-либо образом получается из) уникального идентификатора данных, которые он представляет. То есть в данном случае существует нечто вроде первичного ключа для всех entity beans. Идентификатор же session beans может быть практически любым -- например он может состоять из имени сервера и порта удаленного соединения, а может создаваться случайным образом.
Синтаксис:
Math.abs(number)
number любое числовое выражение или свойство существующего объекта.
1. password.blur()
2. select.blur()
3. textName.blur()
4. textareaName.blur()
password любое значение атрибута NAME объекта password или элемент массива elements.
select любое значение атрибута NAME объекта select или элемент массива elements.
textName любое значение атрибута NAME объекта text или элемент массива elements.
textareaName любое значение атрибута NAME объекта textarea или элемент массива elements.
stringName.bold()
stringName любая строка или свойство существующего объекта.
Math.ceil(number)
number любое числовое выражение или свойство существующего объекта.
stringName.charAt(index)
stringName любая строка или свойство существующего объекта.
index любое целое число от 0 до stringName.length-1 или свойство существующего объекта.
clearTimeout(timeoutID)
timeoutID задержка, установка которой была возвращена предыдущим вызовом метода setTimeout.
buttonName.click()
radioName[index].click()
checkboxName.click()
buttonName любое значение атрибута NAME объектов button, reset или submit или элемент массива elements.
radioName значение атрибута NAME объекта radio или элемент массива elements.
index целое число, представляющее кнопку radio в объекте radio.
checkboxName любое значение атрибута NAME объекта checkbox или элемент массива elements.
но являются событиями объекта
нет. События onLoad и onUnload определяются в таге <BODY>, но являются событиями объекта window.
но являются событиями для объекта
нет. События onLoad и onUnload определяются в таге <FRAMESET>, но являются событиями для объекта window.
я подготовил код, который будет
Для своего первого примера я подготовил код, который будет работать на платформе Java 1.1. Хотя виртуальные машины JVM 1.2 достаточно распространены, не все могут размещать программы на этой платформе. К сожалению, провайдеры не сильно спешат обновлять виртуальные машины на своих серверах. Как следствие, приходится разрабатывать сервлеты, работающие на платформе Java 1.1. Это не сильно затруднят задачу; тем не менее, есть некоторые сложности, связанные с формированием изображений, которые мы обсудим ниже.
Будем строить круговую диаграмму (pie chart), которую мы, для полноты картины, раскрасим и подпишем. На диаграмме будут изображены напитки, употребляемые разработчиками программного обеспечения. Посмотрим, как можно это сделать.
Для операций ввода/вывода изображений в Java 1.1 Sun предлагает библиотеку Jimi. Sun приобрел ее у небольшой компании. Перед тем, как начать распространять эту библиотеку, компания Sun перенесла классы в пакет com.sun, а в остальном ничего не изменила.
Следующие шаги необходимо проделать для формирования PNG изображения с использованием Jimi.
Создать окно приложения(Frame для получения изображения. Использую AWT изображение, создать реализацию класса Graphics. Нарисовать картинку с помощью объекта Graphics. Создать объект JimiWriter на основе потока данных, передаваемых клиенту. Преобразовать изображение в соответствующий формат и отправить его клиенту.
Для формирования и модификации изображений на платформе Java 1.1 необходимо использовать активную AWT компоненту. Как правило, сервлет не должен создавать AWT компоненты, которые обычно используются в приложениях с графическим интерфейсом пользователя. В этом случае, вам нужен графический (AWT) объект для того, что бы получить объект класса Graphics, с помощью которого можно рисовать новые картинки. Придется смириться с маленьким окошком на консоли Веб сервера. Если вам известны способы создания изображения в Java 1.1 без использования AWT компонент, пожалуйста, сообщите мне. Один из возможных вариантов, загрузить с диска сервера заранее подготовленный шаблон, например методом java.awt.Toolkit.createImage(). После того, как вы создали AWT изображение, вы можете получить реализацию класса Graphics и использовать ее для рисования. Имея в своем распоряжении объект Graphics, вы можете закрыть ненужное окно на консоли сервера. Я оставлю этот эксперимент заинтересованным читателям.
Напомню, что для связи с классом, рисующим круговую диаграмму, сервлет использует интерфейс ImageProducer. Поэтому наш класс JIMIProducer должен реализовывать этот интерфейс. Прежде всего, создадим AWT окно, AWT изображения и, наконец, объект Graphics:
Frame f = new Frame();
f.setVisible(true; image = f.createImage(ImageWidth, ImageHeight); graphics = image.getGraphics(); f.setVisible(false);
Ключевой метод класса JIMIProducer - drawSlice. Получая на входе метку и величину сегмента в градусах, этот метод рисует сегмент диаграммы, раскрашивает его и подписывает. Далее, я расскажу подробней, как это происходит.
Будем заполнять "внутренности" диаграммы по часовой стрелке, начиная с положения "три часа", то есть первую линию проведем из центра к окружности ограничивающей диаграмму в положении часовой стрелки в три часа дня (или ночи, как вам больше нравиться). Отступим по часовой стрелке необходимое количество градусов и нарисуем вторую линию, ограничивающую сегмент диаграммы. И так далее. Приведенный ниже код получает на входе величину сегмента в градусах и рисует границу этого сегмента. Он вызывается последовательно для всех сегментов, при этом предполагается, что в сумме угловые величины составят 360 градусов.
//************************************************* // Преобразуем угол в радианы // 1 градус = pi/180 радиан //************************************************* doubletheta = degrees * (3.14/180); currentTheta += theta;
//************************************************* // Переводим в декартовы координаты // x = r cos @ // y = r sin @ //************************************************* double x = Radius * Math.cos(currentTheta);
double y = Radius * Math.sin(currentTheta);
Point mark2 = newPoint(center); mark2.translate((int)x,(int)y); graphics.drawLine (center.x, center.y, mark2.x, mark2.y);
Затем, нужно раскрасить сегменты диаграммы. Для этого можно воспользоваться очень полезным методом fillArc():
graphics.setColor(colors[colorIndex++]); graphics.fillArc(Inset, Inset, PieWidth, PieHeight, -1 * lastAngle, -1 * degrees);
Последняя задача метода drawSlice() нарисовать метки сегментов. Расположение надписи рассчитывается, основываясь на метрике используемого шрифта. Окончательный вариант диаграммы можно посмотреть на рисунке.
Рис. 1. Окончательный вариант круговой диаграммы. (Не все броузеры показывают файлы формата PNG, поэтому здесь мы поставили GIF файл.)
Практически все интересуются сейчас курсами
Практически все интересуются сейчас курсами акций на бирже. Нарисуем (всем на радость) на нашей диаграмме курс акций компании Sun за одну из недель марта.
Для создания изображений в формате JPEG используется класс com.sun.image.codec.jpeg.JPEGImageEncoder. Повторюсь, что принадлежность к пакету com.sun означает, что этот класс не является частью основного API и к нему относятся все соответствующие предупреждения.
Класс JPEGImageEncoder "понимает", как перекодировать изображение java.awt.image.BufferedImage, так что его и будем использовать. Для создания класса BufferedImage нужно указать требуемые размеры изображения. После создания, класс BufferedImage предоставляет класс ava.awt.Graphics2D, который можно использовать для рисования на соответствующей классу BufferedImage картинке. Все просто? Итак, основные шаги, необходимые для формирования изображения в формате JPEG:
Создаем класс JPEGImageEncoder, предоставляя ему поток OutputStream данных передаваемых клиенту. Создаем класс BufferedImage необходимых размеров. Используем реализацию класса Graphics2D, предоставляемую классом BufferedImage, для рисования диаграммы. С помощью полученного ранее класса JPEGImageEncoder перекодируем нарисованное изображение в формат JPEG и пишем его в поток, отправляемый клиенту.
Обсудим некоторые детали рисования с использованием Graphics2D.
Для создания графика курса акций нужно, собственно, нарисовать несколько линий. Пакет Java 2D, java.awt.geom, содержит все необходимые для этого классы. Абстрактный класс Line2D определяет отрезок прямой. Он имеет две реализации, отличающиеся типом используемых координат. Класс Line2D.Double применяет примитивный тип double, а класс Line2D.Float - вещественные числа с плавающей точкой. Высокая точность совершенно излишня для нашего графика, но я не буду экономить и создам отрезки прямой классом Line2D.Double.
Приведем, в качестве примера, участок программы, рисующий горизонтальную ось графика:
horAxis = new Line2D.Double(HorzInset, ImageHeight - VertInset, ImageWidth - HorzInset, ImageHeight - VertInset); graphics.draw(horAxis);
Горизонтальная ось строится с небольшим отступом от границы экрана, предоставляя место для разметки. После создания вы рисуете линю, обращаясь к методу draw() объекта Graphics2D. Напомню, что вы получили его от реализации класса BufferedImage. Класс Graphics2D содержит методы для рисования графических примитивов, для наших целей более чем достаточно. На рисунке 2 приведен окончательный вариант графика.
Рис. 2. Окончательный вариант графика курса акций.
Создание серверных объектов
Итак, приложение-клиент соединяется с EJB-сервером и посылает ему запрос на создание ``бина'' (Enterprise JavaBean) для обработки своих запросов. Сервер отвечает на такой запрос созданием объекта на стороне сервера (экземпляр EJB-компоненты) и возвращает клиенту прокси-объект (EJB-объект), чей итерфейс совпадает с интерфейсом созданной EJB-компоненты и чьи методы перенаправляют вызовы собственно экземпляру компоненты. После этого приложение-клиент работает с EJB-объектом как с локальным объектом, даже и не подозревая, что всю работу выполняет не EJB-объект, а удаленная компонента на сервере. Необходимо заметить, что созданием и удалением EJB-компонент на сервере занимается EJB-контейнер.
Home interface
У каждой EJB-компоненты есть то, что называют ``родной интерфейс'' (home interface), который опеределяет методы создания, инициализации, удаления и (в случае entity beans) поиска экземпляров EJB-компонент на стороне сервера. ``Родной интерфейс'', по сути, описывает возможные взаимодействия между компонентой и контейнером, а конкретно -- описанные выше.
``Родной интерфейс'' для EJB-компоненты наследуется от интерфейса javax.ejb.EJBHome, который представляет базовую функциональность для взаимодйествия между контейнером и компонентой. Все методы этого интерфейса должны быть RMI-совместимы. Интерфейс также описывает один или более create() методов, которые все называются ключевым словом create, но тело которых различно. Все create методы возвращают объект с ``внешним'' (remote) для данной компоненты интерфейсом.
Когда приложение-клиент хочет создать ``бин'' на сервере, оно вначале использует Java naming and Directory Interface (JNDI) для нахождения объекта с искомым интерфейсом. JNDI представляет собой стандартное расширение Java-пакета и предоставляет глобальный сервис для любого Java-окружения, позволяя Java-программам находить и использовать существующие ресурсы просто по имени, а также позволяя просто извлекать информацию о ресурсах. Использование EJB сервисов, аналогичных JNDI, еще раз подчеркивает тот факт, что цель EJB-систем -- полная совместимость с Java API.
Когда клиент получил ссылку на объект с ``родным'' интерфейсом, он вызывет у этого объекта любой из методов create для создания экземпляра компоненты на сервере. При получении вызова create локальный (находящийся у клиента) объект с ``родным'' интерфейсом удаленно вызывает метод у EJB-контейнера, который и создает экземпляр ``бина'', возвращая клиенту EJB-объект. После этого приложение-клиент вызывает у EJB-объекта методы, исполнение которых перенаправляется на сервер (сначала контейнеру, а потом уже компоненте). Контейнер, при получении вызова к компоненте, просто вызывает у нее соответствующий метод. Единственное, за что ответственен при этом контейнер -- обработка некоторых ошибок (таких, например, как отсутствие искомого экземпляра класса) и соответственное возбуждение исключительных ситуаций.
Entity ``бины'', помимо упоминавшихся, имеют дополнительный интерфейс finder, который используется для поиска по уникальному ключу экземпляра ``бина''.
И, как уже говорилось, ``родной интерфейс'' включает в себя методы, сообщающие контейнеру о необходимости удалить экземпляр компонента. В этом случае сервер производит удаление экземпляра, и любая следующая попытка вызвать метод у удаленной компоненты приведет к возникновению исключительной ситуации.
Свойства:
Объект anchor не имеет свойств.
Массив anchors имеет следующие свойства:
length определяет число поименованных якорей в документе.
name отражает атрибут NAME
value отражает атрибут VALUE
checked позволяет вам в программе установить какой checkbox будет помечен галочкой.
defaultChecked отражает атрибут CHECKED.
name отражает атрибут NAME.
value отражает атрибут VALUE.
Свойство:
Объект frame является свойством
Массив frames является свойством и
Try.shtml
1999 г
Блоки try... catch... finally... в JScript 5.
Пояснение для людей не знакомых с данной конструкцией
Конструкция try – catch - finally предназначена для перехвата ошибок (исключений). Если в блоке try каком-то операторе возникает ошибка, JScript игнорирует остальные операторы и переходит в блок catch, где находится блок обработки исключений. Последним выполняется блок finally, в котором обычно выполняют некие заключительные действия. Допускается использование неполной конструкции - без catch или finally.
Скажу сразу, что бы не было никаких недоразумений: JScript – это JavaScript в интерпретации Microsoft, а 5-я версия предполагает наличие Internet Explorer 5.0 (в 4-м IE всего лишь 3-я версия JScript).
Не знаю как вы, а я, сколько программирую на J[ava]Script мечтал, что бы в этом языке появился наконец эта конструкция из двух слов, но шли годы, а заветные слова так и оставались зарезервированными и я уж было потерял всякую надежду, как вышел пятый IE...
И вот, однажды вечером, внося очередные изменения в свой JS Unix (http://www.chat.ru/~junix/) и роясь одновременно во внутренностях 5-го "зонда" взгляд мой зацепил знакомые "try, catch" и незнакомое "Error". Смутная надежда маленьким мерцающим огоньком загорелась в моей душе. Осторожно, не давая ей погаснуть я протянул руки к клавиатуре, набрал try... catch... и в место досадного "зарезервированные слова" получил радостное "предполагается наличие }". Надо было видеть меня в тот момент (или слышать), каюсь: я кричал, что Гейтс молодчина. Каюсь, потому что Гейтс – плохой дядя, сделал в пятой версии то, что надо было сделать еще в первой. Ну да ладно, это все замечательно, но надо было сделать так, что бы кроме пятого эксплорера, остальные браузеры не замечали этот блок. Хорошо, что в JScript есть такая замечательная вещь, как условная компиляция. Воспользовавшись ею можно скрыть все что угодно от посторонних глаз Netscape Navigator и Internet Explorer 4.01 и ниже. Таким образом, вся конструкция выглядит так (после точки с запятой – мои комментарии):
/*@cc_on @*/ | ; Включаем условную компиляцию | |
/*@if (@_jscript_version>4) | ; Проверяем версию JScript | |
try | ; Сам блок try | |
{@end @*/ | ||
Result=eval(expression); | ; Делаем что-то полезное | |
/*@if (@_jscript_version>4) | ||
} catch (err) | ; "Ловим" ошибку | |
{ | ||
alert(err.description); | ; Сообщение об ошибке | |
Result=''; | ||
} finally | ||
{ | ||
alert(Result); | ; Завершающие действия | |
}; | ||
@end @*/ | ||
/*@cc_off @*/ | ; Выключаем условную компиляцию |
err=new Error();
err=new Error(number);
err=new Error(number,description);
Свойство (и параметр конструктора) number – числовое значение (номер ошибки), свойство description (так же параметр конструктора) – строка, описание ошибки. Некоторые числовые значения и соответствующие им описания ошибок приведены в таблице ниже:
Существует способ программно возбудить исключение (создать ошибку) - достаточно вызвать оператор throw с созданным ранее объектом Error. При перехвате ошибки конструкцией try-catch созданный объект будет передан блоку catch. Примеры:
var err=new Error(-10,"Неверное число");
throw(err);
throw(new Error(-4,"Ошибка"));
Таким образом JScript пополнился еще одной полезной конструкцией, существенно упрощающей жизнь программиста.
Web-программист казанского центра Интернет Степанищев Е.В.
Undifined
Синтаксис
undifined
Переменные, которым не было присвоено значение, имеют значение undifined. Теперь вы можете использовать undifined для проверки того, было ли присвоено переменной значение. Методы и выражения JavaScript также возвращают значение undifined, если используемые переменные не имеют своего значения. undifined - это свойство объекта Global, которое имеет значение undifined.
Пример:
var input; if(input == undefined){ document.write("переменной input значение не присвоено"); }
UTC
UTC - метод объекта Date, теперь также поддерживает миллисекунды.
Date.UTC(year, month, date, [, hours[, min[, sec[, ms]]]])
Для поддержки UTC были введены getUTCFullYear(), getUTCMonth(), getUTCDate(), getUTCDay(), getUTCHour(), getUTCMinutes(), getUTCSeconds(), getUTCMilliseconds(), setUTCFullYear(year [, month[, date]]), setUTCMonth(month[, date]), setUTCDate(date), setUTCHour(hours[, min[, sec[,ms]]]), setUTCMinutes(min[, sec[, ms]]), setUTCSeconds(sec [, ms]), setUTCMilliseconds(ms) и toUTCString() ( превращает дату в строку, используя соглашение Universal Coordinates Time ). Рассматривать эти методы более подробно не имеет смысла, их предназначение вполне понятно из названия.
в разработке технологии Enterprise JavaBeans
Основная идея, лежавшая в разработке технологии Enterprise JavaBeans -- создать такую инфраструктуру для компонент, чтобы они могли бы легко ``вставляться'' (``plug in'') и удаляться из серверов, тем самым увеличивая или снижая функциональность сервера. Технология Enterprise JavaBeans похожа на технологию JavaBeans в том смысле, что она использует ту же самую идею (а именно, создание новой компоненты из уже существующих, готовых и настраиваемых компонент, аналогиично RAD-системам), но во всем остальном Enterprise JavaBeans -- совершенно иная технология.
Отличие от JavaBeans
Технология Enterprise JavaBeans описывается не спецификацией JavaBeans Component Specification, а совсем другим документом -- Enterprise JavaBeans Specification. Если JavaBeans имеют дело лишь с клиентскими компонентами (как правило, это GUI-компоненты, или компоненты, с ними связанные), то EJB описывает каким образом внутри EJB-системы взаимодействуют между собой клиенты и серверы, как EJB-системы взаимодействуют с другими системами и какова роль различных компонент этой системы.
Цели, лежащие в основе технологии EJB
Опубликованная в марте 1998 года EJB-спецификцаия версии 1.0 (Недавно была опубликована версия 1.1 спецификации) определяет следующие цели:
облегчить разработчикам создание приложений, избавив их от необходимости реализовывать с нуля такие сервисы, как транзакции (transactions), нити (threads), загрузка (load balancing) и другие. Разработчики могут сконцентрироваться на описании логики своих приложений, оставляя заботы о хранении, передаче и безопасности данных на EJB-систему. При этом все равно имеется возможность самому контролировать и описывать порученные системе процессы. описать основные структуры EJB-системы, описав при этом интерфейсы взаимодйествия (contracts) между ее компонентами. EJB преследует цель стать стандартом для разработки клиент/сервер приложений на Java. Таким же образом, как исходные JavaBeans (Delphi, или другие) компоненты от различных производителей можно было составлять вместе с помощью соответствующих RAD-систем, получая в результате работоспособные клиенты, таким же образом серверные компоненты EJB от различных производителей также могут быть использованы вместе. EJB-компоненты, будучи Java-классами, должны без сомнения работать на любом EJB-совместимом сервере даже без перекомпиляции, что практически нереально для других систем. EJB совместима с Java API, может взаимодействовать с другими (не обязательно Java) приложениями, а также совместима с CORBA.
Вывод окна сообщений.
Используя методы alert, confirm, prompt можно выводить сообщения пользователю. Сообщение, выводимое alert, используется для вывода предупреждений пользователю. Метод confirm используется для сообщений, требующих принятия решения пользователем. При использовании prompt окно сообщений содержит само сообщение и поле ввода текста, который при нажатии кнопки "OK" может передаваться серверу или использоваться при вызове другого скрипта.
Для этого в теле документа в тагах <FORM> используются обработчики событий onClick и методы alert, prompt, а для confirm используется функция test, описанная в тагах <SCRIPT>.
<script language="JavaScript">
function test() {
if (confirm("If you want to close the window, press 'OK'?")) { window.close()} }
</script>
<form>
<input name=kuku type=submit value="alert" onClick="alert('Message for users')">
<input name=tutu type=submit value="confirm" onClick="test()">
<input name=nunu type=submit value="prompt" onClick="prompt('Enter your name, please','')">
</form>
Web браузер как средство доступа к БД
Дмитрий Брязгин,
Опубликовано 11.02.2003
В работе рассматриваются некоторые аспекты построения клиентского приложения на базе WEB броузера. Необходимо отметить, что информационная система, в основе построения которой лежат Web-технологии, в определенных ситуациях может не только сохранить возможности классического приложения, т.е. приложения разработанного в рамках клиент-серверной технологии, но зачастую и расширить их. Кроме того, применение Web-технологий в этом классе задач имеет и свои преимущества. К наиболее важным из них, можно отнести отсутствие необходимости в установке и сопровождении клиентских приложений, а также затрат на покупку лицензий для программного обеспечения, которое бы осуществляло поддержку работы front-end приложений, что неизменно присутствует в клиент-серверной технологии.
С другой стороны, размытость стандартов в области WEB-технологий и некоторая "сыроватость" используемого здесь программного обеспечения являлись, до последнего времени, фактором сдерживающим их распространение. Тем не менее, в настоящий момент можно уже говорить не столько о возможности распространения WEB-технологий, сколько об успешности распространения таких технологий на задачи, решаемые, например, в корпоративных сетях.
Поводом к написанию данной статьи послужил практический опыт построения подобной системы, которым автор хочет поделиться. В небольшой статье нет возможности рассмотреть весь спектр проблем и их решений, однако, наиболее существенные моменты будут затронуты.
я показал, как можно создавать
В этой статье я показал, как можно создавать в программах на языке Java простые изображения, и воспользовался этой техникой для написания сервлета, формирующего картинку по запросу пользователя. Эта технология имеет огромное количество приложений, ограниченное, разве что, рамками воображения. Два вопроса стоит иметь в виду, разрабатывая приложения на основе изложенных идей: производительность алгоритма, создающего изображение, и ограничение пропускной способности канала связи сервера. Для решения последней проблемы, очевидно, нужно максимально уменьшить размер картинки, в первом случае применять стандартные методы оптимизации приложений.
Об авторе
KenMcCrary, сертифицированный Sun Java developer, живет в Нью-Йорке, Research Triangle Park. Он работал над большим количеством Java проектов. Вы можете посетить его сайт
Ресурсы
Оригинальные исходные тексты:
Слегка подправленный вариант с комментариями на русском:
Круговая диаграмма в формате PNG:
Информация по зопросу JSR-00015:
нформация по пакету JPEG:
Информация по библиотеке Jimi:
Информация по PNG:
Reprinted with permission from the March 2000 edition of JavaWorld magazine.
Copyright © ITworld.com, Inc., an IDG Communications company.
View the original article at: