Нам всем доводилось использовать технологию AJAX (Asynchronous Java
Technology and XML, Асинхронная технология Java и XML) и многие из нас открывают
здесь для себя целый новый мир.
В то время как многие программисты лишь случайно столкнутся с AJAX в рамках
существующих систем (так мы будем далее переводить термин framework), вы,
возможно, захотите исследовать эту технологию глубже или расширить уже имеющиеся
функциональности.
Этот FAQ предназначен для Java-разработчиков, которые хотели бы добавить
AJAX-функциональность в свои приложения.
- Следует ли
использовать AJAX?
- AJAX и Java:
совместная работа возможна?
-
Предоставляют ли серверные системы средства для работы с AJAX?
- С чего начать?
- Что необходимо
знать, чтобы создать собственную AJAX-функциональность?
-
Действительно ли надо изучить JavaScript?
-
Какие JavaScript-библиотеки и системы предлагаются в помощь
Java-разработчику?
- Какой
тип возвращаемого значения - XML, plain text, JavaScript или HTML - следует
использовать?
-
Существуют ли в AJAX проблемы с удобством использования (так мы будем далее
переводить термин usability)?
- Как
отладить JavaScript?
- Какой
HTTP-метод - GET или POST - следует использовать для AJAX-вызовов?
- Как
предоставить многоязычную поддержку для AJAX-запросов?
-
Как
обрабатывать параллельные AJAX-запросы?
-
Что
надо сделать на сервере для взаимодействия с AJAX-клиентом?
- Где следует
хранить состояние клиента при использовании AJAX?
- Как
отправить форму (или ее отдельную часть) без обновления страницы?
- Кто
должен управлять приложением - сервер или клиент?
- Есть ли
проблемы с безопасностью при использовании AJAX?
- Когда
надо использовать синхронный запрос вместо асинхронного?
- Как насчет
аплетов и плагинов?
- Как
обрабатывать нажатие кнопок "Back" и "Forward"?
- Как с
помощью AJAX переслать изображение?
- Как
организовать в отдельном потоке периодические опросы через AJAX?
Следует ли использовать AJAX?
Вне всякого сомнения, AJAX сейчас популярен, но, может быть, он не совсем
подходит именно вам: его использование ограничено web-браузерами самых последних
версий, а также заставляет решать вопросы совместимости web-браузеров и требует
новых знаний и навыков. Поэтому прежде чем вы с головой погрузитесь в AJAX, вам
стоит прочитать очень хороший блог (blog) Алекса Босворта (Alex Bosworth) на
странице
AJAX Mistakes.
С другой стороны, AJAX позволяет создавать web-приложения с богатыми
интерактивными возможностями, которые реагируют на действия пользователя и
выполняются
действительно быстро.
Хотя утверждение о том, что приложения, использующие AJAX, работают быстрее,
может показаться спорным, нельзя отрицать тот факт, что пользователи испытывают
чувство незамедлительной реакции приложения, так как AJAX обеспечивает для них
активную обратную связь в то время, как обновление данных происходит в фоновом
режиме "за кадром".
Если вы не боитесь решать вопросы совместимости web-браузеров и готовы к
получению новых навыков, AJAX - именно то, что вам нужно.
Для начала попробуйте изменить с помощью AJAX лишь небольшие части или
компоненты ваших приложений. Нам всем нравятся новые технологии, однако не стоит
забывать, что применение AJAX должно улучшать взаимодействие с пользователем, а
не быть ему помехой
.
AJAX и Java: совместная работа возможна?
Конечно. Java прекрасно работает вместе с AJAX! Вы можете использовать
JavaEE-серверы (Java Enterprise Edition), чтобы создавать AJAX-страницы для
клиентских web-приложений и обслуживать поступающие от них AJAX-запросы,
управлять на стороне сервера состоянием объектов, связанных с клиентскими
приложениями, использующими AJAX, и предоставлять AJAX-клиентам различные
серверные ресурсы.
Компонентная модель
JavaServer Faces отлично подходит для определения и использования
AJAX-компонентов.
Предоставляют ли серверные системы средства для работы с AJAX?5
Вполне вероятно, что вы уже пользуетесь преимуществами AJAX: многие
существующие системы на основе Java обеспечивают определенное AJAX
взаимодействие, а новые системы и библиотеки компонентов создаются с улучшенной
поддержкой AJAX.
Я не стану приводить здесь список всех систем, базирующихся на Java и
обеспечивающих работу с AJAX, из опасения что-то пропустить. Хороший список
приводится на сайте
www.ajaxpatterns.org/Java_Ajax_Frameworks.
Если вы еще не выбрали подходящую систему, я бы рекомендовал вам рассмотреть
использование технологии
JavaServer Faces (JSF) и инструментарий на базе этой технологии. Создание и
использование JSF-компонентов позволяет абстрагироваться от рассмотрения многих
деталей генерации JavaScript-кода, AJAX-взаимодействия клиента и сервера,
обработки DHTML-данных
и, таким образом, упростить применение технологии AJAX как разработчиками
JSF-приложений, так и плагинами в JSF-совместимых интегрированных средах
разработки (Integrated Development Environment, IDE), таких как
Sun
Java Studio Creator.
С чего начать?
Если система, которую вы используете, не вполне подходит для решения ваших
задач и вы хотите разработать свои собственные AJAX-компоненты или
дополнительную функциональность, начните со статьи
Asynchronous JavaScript Technology and XML (AJAX) With Java 2 Platform,
Enterprise Edition.
Самый простой пример с исходным кодом приводится в статье
Using AJAX
with Java Technology. Более полный список AJAX-ресурсов приводится на
странице Blueprints AJAX Home.
Полезно изучить статью
AJAX libraries
and frameworks, чтобы не изобретать велосипед при разработке собственных
клиентских AJAX-скриптов.
Книга AJAX in Action, написанная
Дейвом Крейном (Dave Crane) и Эриком Паскарело (Eric Pascarello) совместно с
Дарреном Джеймсом (Darren James) полезна Java-разработчику, поскольку содержит
готовые примеры JavaScript.
Что необходимо знать, чтобы создать свою собственную AJAX-функциональность?
Если вы не планируете пользоваться уже готовыми AJAX-компонентами, вам
следует изучить следующие технологии.
Dynamic HTML (DHTML)
- технология, которая является основой для AJAX. DHTML обеспечивает
взаимодействие пользователя с приложением в режиме реального времени средствами
браузера. DHTML - сочетает в себе JavaScript, Документную Объектную Модель
(Document Object Model, DOM) и Каскадные Таблицы Стилей (Cascading Style Sheets,
CSS).
- JavaScript - это
нестрого типизированный объектно-ориентированный язык сценариев,
поддерживаемый всеми наиболее популярными web-браузерами и необходимый для
организации AJAX-запросов. JavaScript код вызывается на странице в ответ на
некоторое событие, такое как завершение загрузки страницы, щелчок мыши или
нажатие клавиши на элементе формы.
- DOM -
это API для работы со структурированными документами такими как XML или
HTML. В большинстве случаев DOM представляет структуру XML- или HTML-
документов.
- CSS
позволяет вам определить внешний вид страницы: шрифты, цвета, размеры и
расположение. CSS предназначен для четкого разделения содержания от внешнего
представления, которое может быть изменено программно с помощью JavaScript.
Также важно понимать, что сутью
HTTP протокола является механизм запросов/ответов (request/response). Многие
трудноуловимые ошибки могут возникнуть, если вы игнорируете различия между
методами GET и POST при настройке клиентского объекта
XMLHttpRequest или при
обработке кодов HTTP-ответов во время обратных вызовов.
JavaScript соединяет воедино все остальные части клиентского интерфейса.
Во-первых, он используется для создания объекта XMLHttpRequest и запуска
асинхронных вызовов. Во-вторых, JavaScript позволяет анализировать и
обрабатывать возвращаемые с сервера данные и сообщения. И наконец, JavaScript
позволяет добавлять новое содержание в HTML документ и изменять CSS стили,
используя DOM API.
Действительно ли надо изучать JavaScript?
С одной стороны да, если вы планируете разрабатывать новую функциональность с
использованием AJAX в своих web-приложениях.
С другой стороны, JSF-компоненты (JSF
components) и их библиотеки могут скрывать детали, касающиеся JavaScript,
DOM и CSS. Эти компоненты могут сгенерировать для вас все необходимые составные
части для обеспечения поддержки взаимодействий с использованием AJAX. Визуальные
средства разработки, такие как
Java
Studio Creator, также позволяют применять JSF-компоненты c поддержкой AJAX
для создания эффективных web-приложений, позволяя при этом разработчикам не
заботиться о специфичных деталях реализации AJAX.
Если вы планируете разрабатывать свои собственные JSF-компоненты или
обрабатывать генерируемые ими события, важно, чтобы вы были знакомы с основами
JavaScript. Существуют клиентские
JavaScript-библиотеки (смотри ниже), которые можно вызывать из JavaScript на
своей странице и которые автоматически решают проблему несовместимости
браузеров.
Кроме этого существует интересный Internet-ресурс, знакомящий Java-разработчиков
с объектами JavaScript:
Иерархия
объектов и наследование в JavaScript (Object Hierarchy and Inheritance in
JavaScript).
Какие JavaScript-библиотеки и системы предлагаются в помощь
Java-разработчику?
Существует множество JavaScript-библиотек и наборов компонентов (еще большее
количество появляется новых), которые помогают справляться с такими
малоприятными проблемами, как различия браузеров. Рекомендуется обратить
внимание на 3 хорошие библиотеки - The Dojo Toolkit, Prototype и DWR.
- The Dojo Toolkit содержит API и
набор элементов GUI для поддержки разработки web-приложений со сложным
графическим интерфейсом.
Dojo включает в себя интеллектуальную систему для формирования структуры
web-приложения (packaging system), различные UI-эффекты, API для реализации
механизма "drag and drop", API элементов управления GUI, обработки событий,
API для хранения проектов и API для реализации AJAX-взаимодействия. Dojo
помогает решать общие проблемы пользователя (usability), такие как действия
при навигации между web-страницами, способность распознать нажатие кнопки
"Back" в браузере или изменения в строке ввода URL для создания закладки
(bookmarking), способность отключать лишнюю функциональность, если
AJAX/JavaScript не полностью поддерживаются клиентом-браузером.
По богатству возможностей, универсальности и удобству использования
JavaScript-библиотеку Dojo можно сравнить со швейцарским армейским ножом.
Она предоставляет широчайший набор опций и поддерживает как новые, так и
старые браузеры.
- Prototype специализируется на
AJAX-взаимодействиях и содержит AJAX-объект, который включает в себя
несколько объектов, предназначенных для выполнения основных задач, таких как
формирование HTTP-запросов, обновление части документа однократно или
периодически, вставка нового содержимого в документ, периодическое
обновление части документа. Кроме того, эта JavaScript-библиотека содержит
набор объектов для представления AJAX запросов и набор функций для доступа к
компонентам на странице и манипулирования DOM-объектами.
Script.aculo.us и
Rico являются надстройками над Prototype
и предоставляют UI-эффекты, поддержку "drag and drop", а также включают
общие элементы управления GUI, ориентированные на JavaScript.
Технологии Prototype достаточно в случаях, когда требуется только поддержка
AJAX-взаимодействий и решение некоторых основных задач. Если же необходимы и
UI-эффекты, подойдут Rico и Script.aculo.us.
- Yahoo UI Library
- это библиотека утилит и набор элементов управления GUI, использующий API
для поддержки сложных клиентских приложений. Она включает поддержку AJAX и
событий, распространяемую на все виды браузеров, анимацию, DOM, реализацию
механизма "drag and drop" и обмен событиями между браузерами. Yahoo UI
Library хорошо документирована и содержит много примеров.
- DWR (Dynamic Web Remoting) - это
система, включающая как клиентскую, так и серверную часть, который
ориентирован на использование разработчиками механизма вызовов удаленных
процедур (Remote Procedure Calls, RPC) между клиентскими сценариями на
JavaScript и серверными Java-объектами (plain old Java objects, POJO) ,
развернутых на Java EE web-контейнере.
На серверной стороне DWR использует сервлеты для взаимодействия с
Java-объектами и возвращает или объект-представление данного Java-объекта,
или XML-документ.
DWR легко кооперируется с другими технологиями Java. Если вам нужна среда с
тесно интегрированными клиентской и серверной частями, используйте DWR.
- Zimbra - клиент-серверная
система, ориентированная на обмен сообщениями и доставку e-mail в сложных
клиентских приложениях на базе JavaScript. Zimbra включает API для набора
инструментов UI, учитывающий различия между браузерами и предоставляющий
множество встроенных элементов управления GUI, API событий для обмена
событиями как между элементами управления UI, так и между клиентом и
сервером, вспомогательные классы, упрощающие разработку клиентской
функциональности на JavaScript, надстройку над DOM, которая облегчает
решение вопросов, касающихся несовпадения реализаций DOM в разных браузерах,
и сетевые API, которые помогают JavaScript-клиентам общаться через AJAX и
SOAP.
Существует множество устаревших библиотек и совершенно новых библиотек для
JavaScript, но вышеприведенный список дает обзор только нескольких
неспециализированных библиотек. Вы можете выбрать как одну библиотеку, так и
использовать несколько в соответствии с вашими потребностями. Вот более широкий
список клиентских систем:
Survey
of AJAX/JavaScript Libraries.
Какой тип возвращаемого значения - XML, plain text, JavaScript или HTML -
следует использовать?
Понятно, что символ 'X' в слове "AJAX" означает "XML", но поклонники AJAX
быстро обратили внимание, что, по существу, ничто в AJAX не мешает использовать
другие типы выходных наборов данных: JavaScript, HTML или plain text.
- XML - web-сервисы и AJAX, кажется, созданы друг для друга. Вы можете
использовать клиентский API c
для загрузки и анализа XML-данных с web-сервиса, поддерживающего архитектуру
REST (Representational State
Transfer). (Однако имейте ввиду, что для некоторых web-сервисов,
базирующихся на архитектуре SOAP,
возвращаемые данные могут быть достаточно большими и сложными и, таким
образом, не годиться для технологии AJAX).
- Plain Text - сгенерированный сервером текст может быть вставлен в
документ или проанализирован приложением-клиентом.
- JavaScript - этот вариант является расширением предыдущего варианта
plain text с тем лишь исключением, что сервер возвращает фрагмент сценария
JavaScript, включая объявление объектов JavaScript. Используя
JavaScript-функцию
eval(), вы можете затем создать этот объект
на стороне клиента.
JSON, который представляет собой спецификацию по обмену данными на
основе JavaScript-объектов, полагается именно на такую технику.
- HTML - включение сгенерированного сервером HTML-фрагмента
непосредственно в web-документ обычно является весьма эффективной
AJAX-техникой. Однако, бывает затруднительно сохранить соответствие между
HTML-кодом, созданном на сервере, и тем, что будет показано в браузере
клиента.
Mashup - это популярный термин, обозначающий создание совершенно нового
web-приложения путем объединения данных от различных web-сервисов и другого
online ПО. Хороший пример mashup -
housingmaps.com, который наглядно объединяет объявления по жилью с
craiglist.org и географические карты с
maps.google.com.
Существуют ли в AJAX проблемы с удобством использования (так мы будем далее
переводить термин usability)?
В результате использования техники динамического обновления web-страницы с
помощью данных, полученных через AJAX-взаимодействие и DHTML, внешний вид
страницы и ее структура могут сильно измениться.
Пользователь может захотеть в любое время нажать кнопки браузера "Back" или
"Forward", создать закладку для страницы, скопировать URL страницы из строки URL
браузера и поделиться ею с другом через e-mail или чат, распечатать страницу.
Поэтому при проектировании AJAX-приложений вам необходимо все тщательно
продумать, чтобы ожидаемое поведение при навигации, создании закладок, печати и
прочих действий в браузере было бы таким, как описано ниже.
- Навигация (Navigation).
Какой ожидается реакция вашего приложения на кнопки браузера "Back",
"Forward", "Refresh", "Bookmark"? Вы могли бы реализовать требуемое
поведение
самостоятельно (manually), но, может быть, проще использовать
JavaScript-среду, такую как
Dojo,
которая предоставляет API для манипуляций с историей загрузки страниц в
браузере и управления навигацией.
- Создание закладок и манипуляции с URL (Bookmarking and URL sharing).
Многие пользователи хотят создавать закладки или копировать/вставлять URL в
соответствующую строку браузера.
Dojo
содержит API для выполнения этих действия.
- Печать (Printing).
В некоторых случаях печать динамически формируемых страниц может
представлять сложность.
Другие соображения, полезные для разработчиков, использующих AJAX:
- Поддержка браузера (Browser Support).
Не все браузеры (и не все их версии) поддерживают полный набор функций
AJAX/DHTML. Смотрите quirksmode.org
со списком браузеров, поддерживающих AJAX, и возможными способами решения
проблем.
- Запрет на выполнение JavaScript.
Вы должны предвидеть, что произойдет, если пользователь запретит выполнение
JavaScript (может быть несколько законных причин, по которым поддержка
JavaScript и CSS может отключаться в web-браузере пользователя).
- Задержка (Latency).
Помните о задержке при проектировании приложения. Уже работающее приложение
будет отвечать на запросы гораздо быстрее, чем то, которое было только что
запущено на сервере, но к которому еще не было обращений. Также помните о
том, что если почти одновременно было сделано несколько клиентских запросов,
такой же порядок ответов сервера не гарантирован. Более детальное обсуждение
вопросов задержки можно найти на сайте
Проблемы задержек в AJAX: миф или реальность?
- Accessibilty.
Предоставление доступа к вашему сайту людям с ограниченными возможностями
(инвалидам) не только приветствуется, но также является требованием
законодательства во многих случаях при продажах. Существуют некоторые
удивительные адаптирующие технологии, которые помогают людям получать доступ
к Web-ресурсам, несмотря на ограниченные возможности зрения, слуха, речи,
физические ограничения. Изучив некоторые хорошо документированные методики и
немного поразмышляв, вы сможете сделать свои приложения совместимыми с этими
технологиями обеспечения доступа.
Degradability - это термин, используемый для описания технических приемов,
предназначенных для адаптирования приложений к широкому диапазону web-браузеров.
Многие AJAX-библиотеки имеют встроенную degradability. Но если вы будете
создавать свою собственную AJAX-функциональность, просто следуйте практическим
рекомендациям, предоставляемым организациями по выработке стандартов, такими как
World Wide Web Conrsoritum (W3C), продвижению
стандартов, такими как Web Standards-сообщество,
и многими другими. В этом случае ваше приложение может работать эффективно в
браузерах, которые не поддерживают AJAX, т.к. даже утратив часть своих эффектных
возможностей при выполнении в таких менее "способных" браузерах, ваше приложение
все равно будет готово к использованию.
Помните, что не стоит применять AJAX только ради демонстрации собственной
"крутизны". Мотив для создания приложения - чтобы люди его использовали. Но люди
не станут пользоваться вашим приложением, если оно несовместимо с их
web-браузером.
Как отладить JavaScript?
Существует не очень много инструментальных средств, которые бы поддерживали
отладку как клиентской, так и серверной частей. Я уверен, что эта ситуация будет
меняться по мере роста числа AJAX-приложений. В настоящее время я выполняю
отладку клиентской и серверной частей приложения раздельно. Ниже приводится
информация об отладке клиентской части приложения для некоторых наиболее
популярных браузеров.
- Firefox/Mozilla/Netscape - имеют очень полезный встроенный отладчик
Venkman. Я изначально
разрабатываю мои приложения в Firefox, а затем переношу их на другие
браузеры.
- Safari - имеет отладчик, который требуется включить в работу.
Подробности смотрите на:
Safari FAQ.
- Internet Explorer - имеется документация по отладке JavaScript:
MSDN Documentation. Также может быть полезна
панель инструментов разработчика (developer toolbar) для Internet
Explorer.
При использовании отладчиков может также применяться и знание общих
технических приемов, как например отладочный вывод ("Alert Debugging"). Вы
просто помещаете вызов функции "alert()" внутри кода JavaScript подобно вызову
System.out.println() в java-коде. Этот маленький фрагмент годится для
большинства случаев.
Некоторые системы, такие как
Dojo,
предоставляют API для трассировки отлаживаемых операторов.
Какой HTTP-метод - GET или POST - надо использовать для AJAX-вызовов?
HTTP метод GET следует использовать для получения данных, возвращаемых по
URL-запросу, параметры которого не будут меняться. Если же состояние обновляется
на сервере, следует использовать HTTP-метод GET. Если же данные клиентского
AJAX-запроса будут обновляться на сервере, должен использоваться HTTP-метод
POST.
Эти правила согласуются с
HTTP
idempotency recommendations. Их настоятельно рекомендуется соблюдать для
сохранения непротиворечивости архитектуры web-приложения.
Как предоставить многоязычную поддержку для AJAX-запросов?
Тот факт, что в AJAX-запросах используется XML, вовсе не означает, что вы
сможете без дополнительных настроек правильно посылать и принимать
локализованные данные. Для создания локализованных AJAX-компонентов, вам надо
сделать следующее:
В серверном компоненте при генерации AJAX-компонентов, необходимо задавать ту
же самую кодировку, что и для web-страницы:
response.setContentType("text/xml;charset=;UTF-8");
response.getWriter().write("<response>invalid</response>");
Для дополнительной информации по применению AJAX с JEE технологиями см.:
AJAX and Internationalization,
а для разработки многоязычных приложений:
Developing Multilingual Web Applications Using JavaServer Pages Technology.
Как обрабатывать параллельные AJAX-запросы?
Используя JavaScript, можно одновременно обрабатывать несколько
AJAX-запросов. Чтобы гарантировать правильный порядок их последующей обработки,
рекомендуется использовать технику
JavaScript Closures.
Пример ниже показывает использование XMLHttpRequest-объекта, скрытого внутри
другого JavaScript-объекта с именем AJAXInteraction. В качестве
аргументов функции AJAXInteraction() вы передаете URL, на который
посылается HTTP-запрос, и функцию (callback), которая вызывается после обработки
запроса сервером.
function AJAXInteraction(url, callback) {
var req = init();
req.onreadystatechange = processRequest;
function init() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
function processRequest() {
if (req.readyState == 4) {
if (req.status == 200) {
if (callback) callback(req.responseXML);
}
}
}
this.doGet = function() {
req.open("GET", url, true);
req.send(null);
}
this.doPost = function(body) {
req.open("POST", url, true);
req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
req.send(body);
}
}
function makeRequest() {
var ai = new AJAXInteraction("processme", function() { alert("Doing Post Process");});
ai.doGet();
}
Функция makeRequest() в приведенном примере создает объект
AJAXInteraction с 2 параметрами: URL со значением "processme" и
inline-функцию, которая будет показывать Alert-диалог с сообщением "Doing Post
Process". Когда выполняется вызов ai.doGet(), инициируется
AJAX-взаимодействие и, когда серверный компонент, связанный с URL "processme",
возвратит документ, тот передается callback-функции, которая была определена при
создании AJAXInteraction.
Применение техники " closures" гарантирует, что будет вызываться именно та
callback-функции, которая связана с соответствующим AJAX-взаимодействием. Однако
следует проявлять осторожность при создании большого числа closure-объектов в
том смысле, что создание новых объектов XmlHttpRequests (как это сделано в
примере) будет ограничено числом сокетов (sockets), используемых для передачи
запросов в данный момент времени. Это происходит вследствие ограничения на число
запросов, которые могут выполняться параллельно. Например, Internet Explorer
разрешает только 2
одновременных AJAX-запроса в данный момент времени. Другие браузеры могут
разрешать большее число запросов, но обычно от 3 до 5. Вы также можете
использовать
пул AJAXInteraction-объектов.
Следует отметить, что обычно, когда клиент выполняет несколько AJAX-вызовов,
аналогичный порядок возврата ответов от сервера не гарантирован. Применение
описанной выше техники в callback-функции closure-объекта гарантирует правильную
последовательность обработки.
Много полезного можно почерпнуть из обсуждения, озаглавленного
Ajaxian
Fire and Forget Pattern.
Что надо сделать на сервере для взаимодействия с AJAX-клиентом?
Заголовку "Content-Type" должно быть присвоено значение "text/xml". В
сервлете это можно сделать с помощью метода
HttpServletResponse.setContentType() - надо передать ему значение
"text/xml", когда возвращаемые данные имеют тип XML. Однако многие реализации
XMLHttpRequest дадут ошибку, если будет указан заголовок "Content-Type".
Фрагмент кода ниже показывает, как задать значение для "Content-Type":
response.setContentType("text/xml");
response.getWriter().write("<response>invalid</response>");
Вы можете также задать значение заголовка "Cache-Control", например, при
использовании автозаполнения, чтобы дать понять proxy-серверу и браузеру не
кэшировать полученные результаты:
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
response.getWriter().write("<response>invalid</response>");
Замечание для разработчиков: Internet Explorer автоматически будет
использовать кэшированные результаты AJAX-ответов на HTTP-запросы по методу GET,
если данный заголовок не задан, что может представлять трудность для
разработчиков. При разработке это следует учитывать и присваивать значение этому
заголовку.
Где следует хранить состояние клиента при использовании AJAX?
Как и в случае других web-приложений, выполняемых в браузере, у вас есть
несколько вариантов:
- На стороне клиента в cookies.
Размер данных в этом случае ограничен - примерно, 80 Кб (обычно около (4 Кб
* 20 cookies) на домен). Кроме того, данные могут быть не защищены, если их
не шифровать (при использовании JavaScript это трудно, но все же возможно).
- На стороне клиента в содержимом web-страницы.
Это более защищенный вариант, но он может затруднить работу. Подробности по
этой теме можно найти на
Storing State on the Client.
- На стороне клиента в файловой системе.
Это осуществимо лишь в том случае, если клиент предоставит приложениям,
выполняемым в браузере, право доступа на запись в файлы локальной файловой
системы. В зависимости от различных условий это может быть необходимо, но
надо соблюдать осторожность.
- На сервере.
Это ближе всего к традиционной модели, где клиент служит лишь для
визуализации данных, хранящихся на сервере. Поддержание синхронности данных
между клиентом и сервером может оказаться проблематичным, но для этого есть
решение:
Refreshing Data.
Поскольку в последнее время обработка данных и управление ими все более
смещаются на сторону клиента, возможно, потребуется пересмотреть варианты
хранения состояния AJAX-клиента.
Как отправить данные формы (или ее отдельной части) без обновления страницы?
При создании формы следует в элементе "form" назначить атрибуту
"onSubmit" имя соответствующей JavaScript-функции, которая
возвращает значение false:
<form onSubmit="doAJAXSubmit();return false;" >
<input type="text" id="tf1" />
<input type="submit" id="submit1" value="Update"/>
</form>
Также для отправки формы можно использовать кнопку (input-элемент
"button" в элементе "form"), назначив ей аналогичным
образом соответствующую JavaScript-функцию:
<form onSubmit="doAJAXSubmit();return false;" >
<input type="text" id="tf1" />
<input type="button" id="button1" onClick="doAJAXSubmit()" value="Update"/>
</form>
Обратите внимание, что значение атрибута формы "onSubmit" задано и
в этом примере. Это сделано для того, чтобы корректно обрабатывать ситуации,
когда пользователь, например, во время редактирования текстового поля нажмет
клавишу "Enter" и форма будет отправлена.
При обновлении страницы рекомендуется дождаться, пока AJAX-вызов успешно
обновит данные формы, а потом обновлять данные на странице. В противном случае
обновление может выполниться некорректно, но пользователь не будет об этом
знать. Я обычно во время частичного обновления данных вывожу информативное
сообщение, а после успешного завершения AJAX-взаимодействия обновляю
web-страницу.
Кто должен управлять приложением - сервер или клиент?
Управление приложением может быть сосредоточено у серверных компонентов, а
может быть распределено между клиентом и сервером. Это надо анализировать и
выбирать наиболее подходящий вариант. Для AJAX более выгодно распределение
управленческих функций между клиентом и сервером.
- Управление сосредоточено на сервере.
Ключевая проблема при централизованном управлении - обеспечение
синхронизации данных, представленных на клиентской web-странице, с
аналогичными данными, хранящимися на сервере. Для решения этой проблемы
можно, например, сделать так, что приложение будет хранить все свои данные
на сервере и передавать все изменения в клиентском представлении (DOM) с
помощью простого JavaScript-контроллера.
- Управление распределено между клиентом и сервером.
Эта архитектура использует JavaScript для обработки событий, манипуляций со
страницей, управления внешним видом страницы и визуализации модели данных у
клиента. Серверная же сторона отвечает за управление бизнес-логикой и
передачей измененных данных модели клиенту. В этом случае сервер ничего не
знает о внешнем представлении за исключением начальной страницы, данные для
которой отсылаются им в ответ на клиентский запрос.
-
Встречаются случаи, когда все AJAX-приложение может полностью состоять
только из одной страницы. При этом следует помнить, что если вы выбираете
этот тип управления, необходимо тщательно продумать вопросы навигации и
создания закладок.
Выбор конкретного варианта управления зависит от целей, которые вы хотите
достигнуть. Я предпочитаю распределять управление между клиентом и сервером.
Есть ли проблемы с безопасностью при использовании AJAX?
Если пользователь выберет режим просмотра исходного текста HTML-страницы
(view page source), он сможет увидеть все содержащиеся на этой странице
JavaScript-сценарии в виде обычного текста.
Но JavaScript по умолчанию не имеет доступа к локальной файловой системе, если
пользователь специально не предоставит такие права. AJAX-взаимодействие может
осуществляться только с теми серверными компонентами, которые содержатся на том
же сервере, откуда была загружена текущая web-страница. Для AJAX-взаимодействий
с внешними сервисами следует использовать proxy-шаблоны.
Вам следует соблюдать осторожность и не раскрывать модель приложения таким
образом, чтобы у недобросовестного пользователя появилась возможность получения
доступа к исходным кодам или декомпиляции ваших серверных компонентов.< В случае
обмена конфиденциальной информацией, стоит подумать над использованием протокола
HTTPS для создания защищенного соединения.
Когда надо использовать синхронный запрос вместо асинхронного?
В аббревиатуре AJAX не зря присутствует слово "асинхронный". Синхронный
запрос заблокирует обработку любых событий на странице до получения ответа от
сервера (по сути, в этом случае браузер перестанет реагировать на любые действия
пользователя до завершения синхронного запроса). И я практически не представляю,
в каких случаях синхронный запрос был бы предпочтительнее асинхронного.
Как насчет аплетов и plugins?
Не торопитесь отказываться от тех частей вашего приложения, которые
используют плагины или аплеты. Хотя AJAX и DHTML могут выполнять "drag and drop"
и другие действия с GUI, все же для этих технологий существуют ограничения,
особенно когда это касается поддержки браузеров. Аплеты и плагины существуют уже
давно и они давно могут выполнять запросы аналогично AJAX. Аплеты содержат
большой набор компонентов GUI и имеют API, который предоставляет разработчикам
буквально все.
Многие игнорируют аплеты и плагины, т.к. для их начальной инициализации
необходимо время при запуске приложения, а также нет гарантии, что у клиента
установлена нужная для работы аплета или плагина версия JVM. Кроме того, аплеты
и плагины не всегда способны манипулировать объектами DOM на странице.
Однако если ваше приложение всегда будет работать в одинаковом окружении или вы
можете позволить себе зависимость от конкретной версии< JVM или доступной версии
плагина (как в случае корпоративного окружения), решение на основе
аплетов/плагинов вполне обоснованно.
Один момент, на который стоит обратить внимание - совместное использование
AJAX и аплетов/plugins. Например, Flickr
использует комбинацию AJAX/DHTML-взаимодействий для маркировки картинок и plugin
для манипуляций отдельными фотографиями и их наборами.
Если вы разрабатываете свои собственные серверные компоненты, было бы хорошо,
чтобы они могли работать с обоими типами клиентов (AJAX/DHTML и аплет/plugin).
Как обрабатывать нажатие кнопок "Back" и "Forward"?
Конечно, вы можете создавать собственное решение для отслеживания текущего
состояния вашего приложения, но я рекомендую оставить это экспертам.
Dojo позволяет
выполнить навигацию независимо от браузера так, как показано в примере ниже:
function updateOnServer(oldId, oldValue, itemId, itemValue) {
var bindArgs = {
url: "faces/ajax-dlabel-update",
method: "post",
content: {"component-id": itemId, "component-value": itemValue},
mimetype: "text/xml",
load: function(type, data) {
processUpdateResponse(data);
},
backButton: function() {
alert("old itemid was " + oldId);
},
forwardButton: function(){
alert("forward we must go!");
}
};
dojo.io.bind(bindArgs);
}
Приведенный пример будет обновлять значение на сервере с помощью вызова
dojo.io.bind(). Обратите внимание, что свойствам, отвечающим за обработку
событий от кнопок браузера "Back" и "Forward", присвоены соответствующие
функции. Вы можете восстановить значение в oldValue или выполнить другие
нужные действия. Все детали реализации того, как обнаруживается событие от
нажатия соответствующей кнопки браузера, скрыто от разработчика внутри
библиотеки Dojo.
Ссылка
AJAX: How to Handle Bookmarks and Back Buttons содержит подробности по
данной проблеме и предлагает JavaScript-библиотеку Really Simple History
framework (RSH), специализирующуюся только на вопросах back- и
forward-навигации.
Как с помощью AJAX переслать изображение?
В некоторых приложениях, таких как Google
Maps вам может показаться, что, в процессе AJAX-взаимодействия пересылаются
изображения. В действительности происходит следующее: в качестве ответа на
AJAX-запрос пересылаются URL изображений и изображения, находящиеся по этим URL,
затем с помощью DHTML вставляются в документ.
В примере, приведенном ниже, в результате AJAX-взаимодействия возвращается
XML-документ и на основании его данных заполняется таблица категорий.
<categories>
<category>
<cat-id>1</cat-id>
<name>Books</name>
<description>Fun to read</description>
<image-url>books_icon.gif</image-url>
</category>
<category>
<cat-id>2</cat-id>
<name>Electronics</name>
<description>Must have gadgets</description>
<image-url>electronics.gif</image-url>
</category>
</categories>
Обратите внимание, что элемент image-url содержит URL
(местоположение) графического файла, представляющего данную категорию.
Callback-метод данного AJAX-взаимодействия выполнит анализ полученного
XML-документа и вызовет функцию addCategory() для каждой категории,
присутствующей в этом XML-документе. Функция addCategory() ищет в
теле документа таблицу "categoryTable" и добавляет в нее строку с
элементом-изображением.
<script type="text/javascript" >
...
function addCategory(id, name, imageSrc) {
var categoryTable = document.getElementById("categoryTable");
var row = document.createElement("tr");
var catCell = document.createElement("td");
var img = document.createElement("img");
img.src = ("images" + imageSrc);
var link = document.createElement("a");
link.className ="category";
link.appendChild(document.createTextNode(name));
link.setAttribute("onclick", "catalog?command=category&catid=" + id);
catCell.appendChild(img);
catCell.appendChild(link);
row.appendChild(catCell);
categoryTable.appendChild(row);
}
</script>
...
<table>
<tr>
<td width="300" bgoclor="lightGray">
<table id="categoryTable" border="0" cellpadding="0"></table>
</td>
<td id="body" width="100%">Body Here</td>
</tr>
</table>
Обратите внимание, что атрибуту src элемента img
задается полный путь к файлу изображения: "images" + imageSrc.
Само изображение будет загружено после того, как строка с указанным img-элементом
будет добавлена в таблицу categoryTable. В результате
последующего HTTP-запроса будет загружен графический файл с URL "images/books_icon.gif"
или "images/electronic_icon.gif"
Как организовать в отдельном потоке периодические опросы через AJAX?
JavaScript в отличие от Java не имеет встроенной поддержки работы с потоками.
JavaScript функции вызываются, когда происходит некоторое событие на странице,
например, загрузка страницы, щелчок мыши, получение фокуса элементом формы. Но
вы можете использовать таймер с помощью вызова setTimeout(),
передав в качестве аргументов имя функции, с которой этот таймер связан, и время
задержки в миллисекундах. Затем вы можете организовать цикл, вызывая ту же самую
функцию, как это показано в примере ниже:
function checkForMessage() {
// начать AJAX-взаимодействие с использованием processCallback() в качестве callback-функции
}
// callback для запроса
function processCallback() {
// выполнить действия после обработки запроса
setTimeout("checkForMessage()", 10000);
}
Заметьте, что в приведенном примере циклический вызов функции
checkForMessage() будет продолжаться бесконечно.
Можно изменять интервал таймера в зависимости от активности на странице или иных
условий. Кроме того, можно добавить логическое условие, чтобы прерывать цикл,
например, по результатам обработки AJAX-ответа.
|