AJAX FAQ для Java-разработчиков

Нам всем доводилось использовать технологию AJAX (Asynchronous Java Technology and XML, Асинхронная технология Java и XML) и многие из нас открывают здесь для себя целый новый мир.
В то время как многие программисты лишь случайно столкнутся с AJAX в рамках существующих систем (так мы будем далее переводить термин framework), вы, возможно, захотите исследовать эту технологию глубже или расширить уже имеющиеся функциональности.
Этот FAQ предназначен для Java-разработчиков, которые хотели бы добавить 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?

Вполне вероятно, что вы уже пользуетесь преимуществами 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-компонентов, вам надо сделать следующее:

* Присвойте набору символов (charset) на вашей web-странице ту кодировку, которая поддерживается выбранными вами языками. Я обычно использую UTF-8, поскольку она охватывает большинство языков. Вот мета-декларация для HTML/JSP-страницы, задающая кодировку данных:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

* В JavaScript-сценариях необходимо кодировать все параметры, передаваемые на сервер. JavaScript имеет функцию escape(), которая возвращает escape-последовательность (текстовую строку) в кодировке Unicode, где все национальные символы заменены своим шестнадцатиричным представлением. Более подробно см.: Сравнение escape(), encodeURI(), and encodeURIComponent().
* На серверной стороне задайте кодировку символов с помощью метода HttpServletRequest.setCharacterEncoding() перед тем, как вы будете извлекать локализованный параметр с помощью вызова HttpServletRequest.getParameter(). В случае UTF это будет выглядеть так: request.setCharactherEncoding("UTF-8");.

В серверном компоненте при генерации 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-ответа.

14 марта 2007 в 13:49
Материалы по теме
{"url":"http://www.fastvps.ru/", "src":"/images/advbanners/fastvps.png", "alt":"Хостинг Fastvps.ru. Наш выбор!"}
Заработок