|
| Россия Worldwide |
Автор: Greg MurrayПеревод: Alexey PetrovОригинал: https://blueprints.dev.java.net/ajax-faq.html
Нам всем доводилось использовать технологию AJAX (Asynchronous Java Technology and XML, Асинхронная технология Java и XML) и многие из нас открывают здесь для себя целый новый мир.
Следует ли использовать AJAX?Вне всякого сомнения, AJAX сейчас популярен, но, может быть, он не совсем
подходит именно вам: его использование ограничено web-браузерами самых
последних версий, а также заставляет решать вопросы совместимости
web-браузеров и требует новых знаний и навыков.
Поэтому прежде чем вы с головой погрузитесь в AJAX, вам стоит прочитать
очень хороший блог (blog) Алекса Босворта (Alex Bosworth) на странице AJAX
Mistakes. AJAX и Java: совместная работа возможна?Конечно. Java прекрасно работает вместе с AJAX! Вы можете
использовать JavaEE-серверы (Java Enterprise Edition), чтобы создавать AJAX-страницы для клиентских web-приложений и обслуживать
поступающие от них AJAX-запросы, управлять на стороне сервера
состоянием объектов, связанных с клиентскими
приложениями, использующими AJAX, и предоставлять AJAX-клиентам различные серверные ресурсы.
Предоставляют ли серверные системы средства для работы с AJAX?5Вполне вероятно, что вы уже пользуетесь преимуществами
AJAX: многие существующие системы на основе Java обеспечивают
определенное AJAX взаимодействие, а новые системы и библиотеки
компонентов создаются с улучшенной поддержкой AJAX. Если вы еще не выбрали подходящую систему, я бы рекомендовал вам рассмотреть использование технологии 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).
Также важно понимать, что сутью 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 на своей странице и которые автоматически решают проблему несовместимости браузеров.
Какие JavaScript-библиотеки и системы предлагаются в помощь Java-разработчику?Существует множество JavaScript-библиотек и наборов компонентов (еще большее количество появляется новых), которые помогают справляться с такими малоприятными проблемами, как различия браузеров. Рекомендуется обратить внимание на 3 хорошие библиотеки - The Dojo Toolkit, Prototype и DWR.
Существует множество устаревших библиотек и совершенно новых библиотек для JavaScript, но вышеприведенный список дает обзор только нескольких неспециализированных библиотек. Вы можете выбрать как одну библиотеку, так и использовать несколько в соответствии с вашими потребностями. Вот более широкий список клиентских систем: Survey of AJAX/JavaScript Libraries. Какой тип возвращаемого значения - XML, plain text, JavaScript или HTML - следует использовать?Понятно, что символ 'X' в слове "AJAX" означает "XML", но поклонники AJAX быстро обратили внимание, что, по существу, ничто в AJAX не мешает использовать другие типы выходных наборов данных: JavaScript, HTML или plain text.
Mashup - это популярный термин, обозначающий создание совершенно нового web-приложения путем объединения данных от различных web-сервисов и другого online ПО. Хороший пример mashup - housingmaps.com, который наглядно объединяет объявления по жилью с craiglist.org и географические карты с maps.google.com. Существуют ли в AJAX проблемы с удобством использования (так мы будем далее переводить термин usability)?
В результате использования техники динамического обновления web-страницы с помощью данных,
полученных через AJAX-взаимодействие и DHTML, внешний вид страницы и ее
структура могут сильно измениться.
Другие соображения, полезные для разработчиков, использующих AJAX:
Degradability - это термин, используемый для описания технических приемов, предназначенных для адаптирования приложений к широкому диапазону web-браузеров. Многие AJAX-библиотеки имеют встроенную degradability. Но если вы будете создавать свою собственную AJAX-функциональность, просто следуйте практическим рекомендациям, предоставляемым организациями по выработке стандартов, такими как World Wide Web Conrsoritum (W3C), продвижению стандартов, такими как Web Standards-сообщество, и многими другими. В этом случае ваше приложение может работать эффективно в браузерах, которые не поддерживают AJAX, т.к. даже утратив часть своих эффектных возможностей при выполнении в таких менее "способных" браузерах, ваше приложение все равно будет готово к использованию. Помните, что не стоит применять AJAX только ради демонстрации собственной "крутизны". Мотив для создания приложения - чтобы люди его использовали. Но люди не станут пользоваться вашим приложением, если оно несовместимо с их web-браузером. Как отладить JavaScript?Существует не очень много инструментальных средств, которые бы поддерживали отладку как клиентской, так и серверной частей. Я уверен, что эта ситуация будет меняться по мере роста числа AJAX-приложений. В настоящее время я выполняю отладку клиентской и серверной частей приложения раздельно. Ниже приводится информация об отладке клиентской части приложения для некоторых наиболее популярных браузеров.
При использовании отладчиков может также применяться и знание общих
технических приемов, как например отладочный вывод ("Alert
Debugging"). Вы просто помещаете вызов функции "alert()" внутри кода
JavaScript подобно вызову System.out.println() в java-коде. Этот
маленький фрагмент годится для большинства случаев. Какой HTTP-метод - GET или POST - надо использовать для AJAX-вызовов?
HTTP метод GET следует использовать для получения данных, возвращаемых по URL-запросу, параметры которого не будут меняться. Если же состояние обновляется на сервере, следует использовать HTTP-метод GET.
Если же данные клиентского AJAX-запроса будут обновляться на сервере, должен использоваться HTTP-метод POST. Как предоставить многоязычную поддержку для 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. 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();
}
Функция Применение техники " 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".
В сервлете это можно сделать с помощью метода
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-приложений, выполняемых в браузере, у вас есть несколько вариантов:
Поскольку в последнее время обработка данных и управление ими все более смещаются на сторону клиента, возможно, потребуется пересмотреть варианты хранения состояния AJAX-клиента. Как отправить данные формы (или ее отдельной части) без обновления страницы?
При создании формы следует в элементе <form onSubmit="doAJAXSubmit();return false;" > <input type="text" id="tf1" /> <input type="submit" id="submit1" value="Update"/> </form>
Также для отправки формы можно использовать кнопку ( <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 более выгодно распределение управленческих функций между клиентом и сервером.
Выбор конкретного варианта управления зависит от целей, которые вы хотите достигнуть. Я предпочитаю распределять управление между клиентом и сервером. Есть ли проблемы с безопасностью при использовании AJAX?Если пользователь выберет режим просмотра исходного текста
HTML-страницы (view page source), он сможет увидеть все содержащиеся на
этой странице JavaScript-сценарии в виде обычного текста. Вам следует соблюдать осторожность и не раскрывать модель приложения таким образом, чтобы у недобросовестного пользователя появилась возможность получения доступа к исходным кодам или декомпиляции ваших серверных компонентов.< В случае обмена конфиденциальной информацией, стоит подумать над использованием протокола HTTPS для создания защищенного соединения. Когда надо использовать синхронный запрос вместо асинхронного?В аббревиатуре AJAX не зря присутствует слово "асинхронный". Синхронный запрос заблокирует обработку любых событий на странице до получения ответа от сервера (по сути, в этом случае браузер перестанет реагировать на любые действия пользователя до завершения синхронного запроса). И я практически не представляю, в каких случаях синхронный запрос был бы предпочтительнее асинхронного. Как насчет аплетов и plugins?Не торопитесь отказываться от тех частей вашего приложения, которые используют плагины или аплеты. Хотя AJAX и DHTML могут выполнять "drag and drop" и другие действия с GUI, все же для этих технологий существуют ограничения, особенно когда это касается поддержки браузеров. Аплеты и плагины существуют уже давно и они давно могут выполнять запросы аналогично AJAX. Аплеты содержат большой набор компонентов GUI и имеют API, который предоставляет разработчикам буквально все. Многие игнорируют аплеты и плагины, т.к. для их начальной
инициализации необходимо время при запуске приложения, а также нет
гарантии, что у клиента установлена нужная для работы аплета или плагина
версия JVM. Кроме того, аплеты и плагины не всегда способны манипулировать
объектами DOM на странице.
Один момент, на который стоит обратить внимание - совместное использование AJAX и аплетов/plugins. Например, Flickr
использует комбинацию 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>
Обратите внимание, что элемент <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>
Обратите внимание, что атрибуту Как организовать в отдельном потоке периодические опросы через AJAX?JavaScript в отличие от Java не имеет встроенной поддержки работы с потоками. JavaScript
функции вызываются, когда происходит некоторое событие на странице,
например, загрузка страницы, щелчок мыши, получение фокуса элементом
формы. Но вы можете использовать таймер с помощью вызова function checkForMessage() {
// начать AJAX-взаимодействие с использованием processCallback() в качестве callback-функции
}
// callback для запроса
function processCallback() {
// выполнить действия после обработки запроса
setTimeout("checkForMessage()", 10000);
}
Заметьте, что в приведенном примере циклический вызов функции |