- •Введение
- •Несколько слов о книге
- •Глава 1. Каким должен бытъ Web-интерфейс
- •Действия пользователя при работе с приложением
- •Накладные расходы при работе в сети
- •Асинхронное взаимодействие
- •Независимый и переходный образы использования
- •Четыре основных принципа Ajax
- •Браузер имеет дело с приложением, а не с содержимым
- •Сервер доставляет данные, а не содержимое
- •Реальное кодирование требует порядка
- •Применение богатых клиентов Ajax
- •Системы, созданные с использованием Ajax
- •Google Maps
- •Альтернативные технологии
- •Macromedia Flash
- •Java Web Start
- •Резюме
- •Ресурсы
- •Основные элементы Ajax
- •JavaScript изучался не зря
- •Определение внешнего вида с помощью CSS
- •Селекторы CSS
- •Свойства стилей
- •Простой пример использования CSS
- •Обработка DOM с помощью JavaScript
- •Поиск узла DOM
- •Создание узла DOM
- •Добавление стилей к документу
- •Свойство innerHTML
- •Асинхронная загрузка с использованием XML
- •Элементы IFrame
- •Объекты XmlDocument и XMLHttpRequest
- •Использование фуниции обратного вызова для контроля запроса
- •Жизненный цикл процедуры поддержки запроса
- •Отличия Ajax от классических технологий
- •Резюме
- •Ресурсы
- •Порядок из хаоса
- •Образы разработки
- •Реструктуризация и Ajax
- •Во всем надо знать меру
- •Реструктуризация в действии
- •Варианты применения реструктуризации
- •Несоответствие браузеров: образы разработки Fagade и Adapter
- •Управление обработчиками событий: образ разработки Observer
- •Повторное использование обработчиков событий: образ разработки Command
- •Обеспечение единственной ссылки на ресурс: образ разработки Singleton
- •"Модель-представление-контроллер "
- •Серверная программа Ajax, созданная без применения образов разработки
- •Реструктуризация модели
- •Разделение содержимого и представления
- •Библиотеки независимых производителей
- •Библиотеки, обеспечивающие работу с различными браузерами
- •Компоненты и наборы компонентов
- •Элементы, располагаемые на стороне сервера
- •Резюме
- •Ресурсы
- •Применение архитектуры MVC к программам различных уровней
- •Применение архитектуры MVC к объектам, присутствующим в среде браузера
- •Представление в составе Ajax-приложения
- •Отделение логики от представления
- •Отделение представления от логики
- •Контроллер в составе Ajax-приложения
- •Классические JavaScript-обработчики
- •Модель обработки событий W3C
- •Реализация гибкой модели событий в JavaScript
- •Модель в составе Ajax-приложения
- •Использование JavaScript для моделирования предметной области
- •Взаимодействие с сервером
- •Генерация представления на основе модели
- •Отражение объектов JavaScript
- •Обработка массивов и объектов
- •Включение контроллера
- •Резюме
- •Ресурсы
- •Программы, выполняемые на сервере
- •Создание программ на стороне сервера
- •N-уровневые архитектуры
- •Управление моделью предметной области на стороне клиента и на стороне сервера
- •Принципы создания программ на сервере
- •Серверные программы, не соответствующие основным принципам разработки
- •Использование архитектуры Model!
- •Использование архитектуры на базе компонентов
- •Архитектуры, ориентированные на использование Web-служб
- •Частные решения: обмен данными
- •Взаимодействие, затрагивающее только клиентскую программу
- •Пример отображения информации о планетах
- •Взаимодействие, ориентированное на содержимое
- •Взаимодействие, ориентированное на сценарий
- •Передача данных серверу
- •Использование HTML-форм
- •Использование объекта XMLHttpRequest
- •Управление обновлением модели
- •Резюме
- •Ресурсы
- •Создание качественного приложения
- •Отклик программы
- •Надежность
- •Согласованность
- •Простота
- •Как получить результат
- •Предоставление сведений пользователю
- •Поддержка ответов на собственные запросы
- •Обработка обновлений, выполненных другими пользователями
- •Создание системы оповещения
- •Основные принципы оповещения
- •Реализация базовых средств оповещения
- •Отображение пиктограмм в строке состояния
- •Отображение подробных сообщений
- •Формирование готовой системы
- •Предоставление информации в запросах
- •Информация о новизне данных
- •Простой способ выделения данных
- •Выделение данных с использованием библиотеки Scriptaculous
- •Резюме
- •Ресурсы
- •JavaScript и защита браузера
- •Политика "сервера-источника"
- •Особенности выполнения сценариев в Ajax-приложении
- •Проблемы с поддоменами
- •Взаимодействие с удаленным сервером
- •Взаимодействие с Web-службами
- •Защита конфиденциальной информации
- •Вмешательство в процесс передачи данных
- •Организация защищенного НТТР-взаимодействия
- •Передача шифрованных данных в ходе обычного HTTP-взаимодействия
- •Управление доступом к потокам данных Ajax
- •Создание защищенных программ на уровне сервера
- •Ограничение доступа к данным из Web
- •Резюме
- •Ресурсы
- •Что такое производительность
- •Скорость выполнения JavaScript-программ
- •Определение времени выполнения приложения
- •Использование профилировщика Venkman
- •Оптимизация скорости выполнения Ajax-приложения
- •Использование памяти JavaScript-кодом
- •Борьба с утечкой памяти
- •Особенности управления памятью в приложениях Ajax
- •Разработка с учетом производительности
- •Простой пример управления памятью
- •Как уменьшить объем используемой памяти в 150 раз
- •Резюме
- •Ресурсы
- •Сценарий двойной комбинации
- •Недостатки клиентского решения
- •Недостатки клиентского решения
- •Архитектура клиента
- •Разработка взаимодействия клиент/сервер
- •Реализация сервера: VB.NET
- •Написание кода сервера
- •Представление результатов
- •Применение каскадных таблиц стилей
- •Дополнительные вопросы
- •Запросы при выборе нескольких элементов
- •Переход от двойного связного выбора к тройному
- •Реструктуризация
- •Новый и улучшенный объект netContentLoader
- •Создание компонента двойного списка
- •Резюме
- •Глава 10. Опережающий ввод
- •Изучаем опережающий ввод
- •Типичные элементы приложений опережающего ввода
- •Google Suggest
- •Ajax как средство опережающего ввода
- •Структура серверной части сценария: С#
- •Сервер и база данных
- •Тестирование серверного кода
- •Структура клиентской части сценария
- •HTML
- •JavaScript
- •Обращение к серверу
- •Дополнительные возможности
- •Реструктуризация
- •День 1: план разработки компонента TextSuggest
- •День 3: включаем Ajax
- •День 4: обработка событий
- •День 5: пользовательский интерфейс всплывающего окна с предлагаемыми вариантами
- •Итоги
- •Резюме
- •Эволюционирующий портал
- •Классический портал
- •Портал с богатым пользовательским интерфейсом
- •Создание портала с использованием Java
- •Таблица пользователя
- •Серверная часть кода регистрации: Java
- •Структура регистрации (клиентская часть)
- •Реализация окон DHTML
- •База данных окон портала
- •Серверный код окна портала
- •Добавление внешней библиотеки JavaScript
- •Возможность автоматического сохранения
- •Адаптация библиотеки
- •Автоматическая запись информации в базе данных
- •Реструктуризация
- •Определение конструктора
- •Адаптация библиотеки AjaxWindows.js
- •Задание команд портала
- •Выводы
- •Резюме
- •Понимание технологий поиска
- •Классический поиск
- •"Живой" поиск с использованием Ajax и XSLT
- •Возврат результатов клиенту
- •Код клиентской части сценария
- •Настройка клиента
- •Инициализация процесса
- •Код серверной части приложения: РНР
- •Создание XML-документа
- •Создание документа XSLT
- •Объединение документов XSL и XML
- •Совместимость с браузером Microsoft Internet Explorer
- •Совместимость с браузерами Mozilla
- •Последние штрихи
- •Применение каскадных таблиц стилей
- •Улучшение поиска
- •Поддержка браузерами Opera и Safari
- •Использовать ли XSLT
- •Решение проблемы закладок
- •Реструктуризация
- •Объект XSLTHelper
- •Компонент "живого" поиска
- •Выводы
- •Резюме
- •Считывание информации из внешнего мира
- •Поиск XML-лент
- •Изучение структуры RSS
- •Богатый пользовательский интерфейс
- •Чтение лент
- •HTML-структура без таблиц
- •Гибкое CSS-форматироеание
- •Глобальный уровень
- •Предварительная загрузка средствами Ajax
- •Богатый эффект перехода
- •Правила прозрачности, учитывающие индивидуальность браузеров
- •Реализация затухающего перехода
- •Интеграция таймеров JavaScript
- •Дополнительные возможности
- •Введение дополнительных лент
- •Интеграция функций пропуска и паузы
- •Как избежать ограничений проекта
- •Обход системы безопасности браузеров Mozilla
- •Изменение масштаба приложения
- •Реструктуризация
- •Модель приложения
- •Представление приложения
- •Контроллер приложения
- •Выводы
- •Резюме
- •Отладчики
- •Для чего нужен отладчик
- •Средство Safari DOM Inspector для Mac OS X
- •Ресурсы
- •JavaScript — это не Java
- •Формирование объектов
Если, с другой стороны, регистрация прошла успешно, запрос перенаправляется на основную страницу портала. В этом случае следующим шагом является создание окон. Чтобы получить намеченный богатый пользовательский интерфейс, нам придется разработать довольно много кода DHTML, но на самом деле эта тяжелая работа уже выполнена, поскольку мы используем готовую DHTML-библиотеку JavaScript.
11.4. Реализация окон DHTML
Наш портал Ajax имеет богатый пользовательский интерфейс, позволяющий пользователю динамически размещать окна. Кроме того, пользователь может устанавливать размер окна (желательную ширину и высоту). При изменении указанных настроек мы можем с помощью Ajax реализовать взаимодействие с сервером и записать новые значения в собственной базе данных (причем пользователь даже не будет знать об этом). Чтобы разрешить подобное поведение, требуется разработать таблицу базы данных, в которой будут храниться свойства окна — высота, ширина и положение. Код серверной части сценария должен получать данные значения и соответствующим образом обновлять величины в базе данных. Написание DHTML-кода, совместимого с основными браузерами, может оказаться сложным, поэтому для реализации перетаскивания и изменения размеров окна мы используем сценарий библиотеки DHTML. Данная библиотека, JSWindow. js, представляет собой внешний файл JavaScript, содержащий код всех требуемых нам функций . (Эту библиотеку можно найти на Web-сайте данной книги.) Чтобы активизировать инфраструктуру Ajax, нам потребуется лишь незначительно изменить код данной библиотеки.
11.4.1. База данных окон портала
Нам нужна таблица базы данных, способная содержать свойства нескольких окон DHTML для каждого пользователя. Каждый пользователь может иметь несколько строк в данной таблице — по одной на каждое окно портала. Таблица применяется для извлечения последнего запомненного положения и размера окна при первом входе пользователя в систему. Когда пользователь что-то меняет, значения обновляются, чтобы при следующем посещении окна располагаться точно так же. Для создания таблицы portal_windows используется следующий SQL-код:
create table portal_windows(
id int primary key not null, user_id int not null, xPos int not null, yPos int not null,
width int not null, height int not null,
url varchar(255) not null, title varchar(255) not null
);
Рис. 11.10. Структура таблицы p o r t a l _ w i n d o w s
Каждый пользователь может иметь несколько окон с различными настройками. Эта проблема решается следующим образом. Столбец user_id связан с базой данных пользователей. Каждое окно должно иметь идентификатор и первичный ключ, которые можно использовать для хранения и обновления свойств. Не забудьте добавить к столбцу идентификатора окна автоматический инкремент. Данный идентифицирующий столбец используется кодом Ajax и библиотекой окон DHTML для получения и обновления СВОЙСТЕ окон, определенных пользователем.
Для хранения координат х и у нашего окна DHTML потребуются два столбца. Данная информация определяет положение окна на экране относительно левого верхнего окна браузера. Данные столбцы, содержащие координаты, обозначаются xPos и yPos. Кроме того, нужны еще два свойстве окна DHTML: ширина и высота. Они хранятся в таблице как целочисленные величины.
Последние два столбца базы данных определяют URL содержимого окна, а также заголовок содержимого, присвоенный пользователем для быстрого доступа. Все свойства, фигурирующие в таблице portal_windows базы данных, показаны на рис 11.10.
Далее требуется ввести определенные значения, заданные по умолчанию, и выполнить тестирование. В таблицу users мы можем добавлять любое число пользователей. Как показано на рис. 11.10, для пользователя 1 мы добавили три окна DHTML.
На рис. 11.11 показано, как три параметра окна DHTML предоставляю! информацию, требуемую для создания трех окон на экране, имеющих различные размеры и положения. В данном случае в трех окнах отображаются тр* Web-сайта: JavaRanch, Google и Eric's Ajax Blog. Создав таблицу базы данных, мы можем предоставлять указанную информацию пользователю прр его входе на портал. Насколько это просто, вы узнаете в следующем разделе
11.4.2. Серверный код окна портала
Предположим, что запрос регистрации прошел через фильтр безопасности Следующий этап — извлечение списка окон портала для аутентифицированного пользователя и возврат JavaScript-кода, сообщающего браузеру, чтс
Рис. 11.11. Данные, введенные для пользователя с идентификатором 1
нужно отображать на экране. В связи с этим мы определяем объект PortalWindow, представляющий строку информации в базе данных, как показано в листинге 11.7.
Листинг 11.7. PortalWindow.java public class PortalWindow { private int id=-l;
private User user=null; private int xPos=0; private int yPos=0; private int width=0; private int height=0; private String url=null; private String title=null;
public PortalWindow(
int id. User user, int xPos, int yPos, int width,int height,
String url, String title
) {
this.id = id; this.user = user; this.xPos = xPos; this.yPos = yPos; this.width = width; this.height = height; this.url = url; this.title = title;
}
public int getHeight() {return height;}
public void setHeight(int height) {this.height » height;} public int getld() {return id;}
public void setld(int id) {this.id = id;} public String getTitle() {return title;}
public void setTitle(String title) {this.title = title;} public String getUrl() {return url;}
public void setUrlfString url) {this.url = url;} public User getUser() {return user;}
public void setUser(User user) {this.user = user;} public int getWidth() {return width;}
public void setWidth(int width) {this.width • width;} public int getXPos() {return xPos;}
public void setXPos(int pos) {xPos = pos;J public int getYPos() {return yPos;}
public void setYPos(int pos) {yPos = pos;}
}
Как и прежде, объект представляет собой достаточно прямолинейное отображение структуры базы данных. В реальной задаче мы, возможно, использовали бы для облечения жизни ORM-систему, например Hibernate или iBATIS, но сейчас нам требуется, чтобы все было довольно простым и платформенно-независимым. Обратите внимание на то, что мы предоставляем для этого объекта как методы установки, так и методы получения, поскольку нам нужно, чтобы объекты обновлялись динамически в ответ на события на стороне клиента. Запрошенный при регистрации URL, portalLogin,servlet, отображается в сервлет, извлекающий все окна портала для этого пользователя и возвращающий в ответ указания JavaScript. Основной сервлет показан в листинге 11.8.
Листинг11.8.СервлетSelectServlet.Java
public class SelectServlet extends HttpServlet { protected void doPost(
HttpServletRequest request, HttpServletResponse response
) throws ServletException, IOException { HttpSession session=request.getSession(); User user={User)
// О Проверить сеанс (session.getAttributef"user"));
StringBuffer jsBuf=new StringBuffer(); if (user==null){
jsBuf.append(JSUtil.logout()) ; }else{
List windows=DBUtil // 0 Определить объект
.getPortalWindows(user); // в Использовать объект JSUtil
j sBuf.append(JSUtil.initUI() );
for (Iterator iter=windows.iterator();iter.hasNext();) PortalWindow window=(PortalWindow)(iter.next()); session.setAttribute("window_"+window.getld(),window) jsBuf.append
// О Объявить окно портала
(JSUtil.initWindow(window));
}
J
Writer writer=response.getWriter(); // 0 Записать в выходной поток.
writer.write(j sBuf.toString()); writer.flush();
> } |
. |
J |
||
|
|
|
|
|
458 Часть IV. Ajax в примерах
Здесь мы снова используем объект DBUtil для абстрагирования взаимодействий с базой данных и JSUtil — для генерации кода JavaScript. DBUtil предоставляет метод getPortalWindows () ©, принимающий в качестве аргумента объект User. Один из таких объектов фигурировал в информации о сеансе, поэтому теперь мы его извлекаем О. Фактический код JavaScript генерируется (как и ранее) объектом JSUtil. создающим код инициализации пользовательского интерфейса ©, объявляющим окна портала, извлеченные из базы данных О. и записывающим их непосредственно в выходной поток сервлета 0.
Напомним коротко, что представляют собой вспомогательные объекты которые мы постоянно используем, — DBUtil и JSUtil. Объект DBUtil используется для получения списка окон портала. Как отмечалось выше, в реальной задаче этот процесс было бы неплохо автоматизировать, используя Hibernate или похожую систему; но с обучающей целью мы используем приведенный в листинге 11.9 метод объекта DBUtil, являющийся реализацией доступа к таблице portal_windows в базе данных. В данном случае применяется прямолинейный код SQL, но представленный принцип легко перенести на любой удобный для вас язык.
Листинг 11.9. Метод getPortalWindows О. |
- |
^Щ |
public static List getPortalWmdows (User user){ |
|
|
List list=new ArrayList(); |
|
|
Connection conn=getConnection(); |
|
|
try{ |
|
|
String sql="SELECT * FROM portal_windows " +"WHERE user_id="+user.getld();
//О Построить выражение SQL
|
|
|
S t a t e m e n t s t m t = c o n n . c r e a t e S t a t e m e n t ( ) ; |
|
|
|
|
R e s u l t S e t r s = s t m t . e x e c u t e Q u e r y ( s q l ) ; |
|
|
|
|
PortalWindow |
w i n = n u l l ; |
|
|
|
w h i l e ( r s . n e x t ( ) ) { |
|
// |
@ |
Последовательно пройти результаты |
||
|
|
|
i n t i d = r s . g e t l n t ( " i d " ) ; |
|
|
|
|
i n t x = r s . g e t l n t ( " x P o s " ) ; |
|
|
|
|
i n t y = r s . g e t l n t ( " y P o s " ) ; |
|
|
|
|
i n t w = r s . g e t l n t ( " w i d t h " ) ; |
|
|
|
|
i n t h = r s . g e t l n t ( " h e i g h t " ) ; |
|
|
|
|
S t r i n g u r l = r s . g e t S t r i n g ( " u r l " ) ; |
|
|
|
|
S t r i n g t i t l e - r s . g e t S t r i n g ( " t i t l e " ) ; |
|
|
|
|
win=new |
PortalWindow( |
// |
© |
Добавить объект |
|
|
|
|
|
i d , u s e r , x , y , w , h , u r l , t i t l e ) ; |
|
|
|
|
l i s t . a d d ( w i n ) ; } |
|
|
|
r s . c l o s e ( ) ; |
|
|
|
|
s t r a t . c l o s e ( ) ; |
|
|
|
|
}catch |
(SQLException |
s q l e x ) { |
|
|
} |
|
|
|
r e t u r n |
l i s t ; |
|
}
Глава 11. Улучшенный Web-портал Ajax 459
Итак, мы формируем выражение SQL О, последовательно проходим по сгенерированному этим выражением набору результатов © и во всех случаях добавляем к нашему списку объект PortalWindow ©.
Далее мы используем вспомогательный объект JSUtil, генерируем код инициализации и объявляем объекты окна на JavaScript. Соответствующие методы по сути представляют собой упражнения по конкатенации строк, поэтому мы не будем приводить здесь класс целиком. Принцип его действия демонстрируется в приведенном ниже коде.
public static String initwindow(PortalWindow window) { StringBuEfer jsBuf=new StringBuffer{)
.append("CreateWindow{new NewWin('")
.append(window.getId())
.append("',")
,append(window.getXPos())
.append(",")
.append(window.getYPos())
.append(",")
.append(window.getWidth())
.append(",")
.append(window.getHeight())
.append(",'")
.append(window.getUrK))
.append("','")
.append(window.getTitle{))
. a p p e n d ^ " ) ) ; (BBSS)n11); return j s B u f . t o S t r i n g ( ) ;
}
Метод initwindow () генерирует код JavaScript для инициализации одного окна портала. Код JavaScript успешного запроса может выглядеть приблизительно так, как показано ниже: для всех окон последовательно вызывается функция initwindow () (для улучшения читаемости код был соответствующим образом отформатирован):
document.getElementByld('login' )
.innerHTML='Welcome back!' document.getElementByld('defaultConten')
.style.display=tquotenonetquote;
CreateWindow( new NewWin(
tquoteltquote,612,115,615,260,
tquotehttp://www.j avaranch.comtquote,tquoteJavaRanchtquote
)
);
CreateWindow( new NewWin(
tquote2tquote,10,115,583,260,
tquotehttp://www.google.comtquote,tquoteGoogletquote
)
>;
CreateWindow(
new NewWin(