AJAX (Asynchronous XML And JavaScript) -- это способ построения веб-приложений на основе объединения целого ряда технологий:
Аббревиатура AJAX, также как DHTML
 или
LAMP
, не является технологией, а
обозначает совместное использование группы существующих технологий.
В качестве платформы для выполнения AJAX-приложений может выступать любой популярный браузер последних версий: Mozilla Firefox, Microsoft Internet Explorer, Opera, Apple Safari.
Суть AJAX в том, что приложения, использующие его, становятся более интерактивными и похожими на традиционные приложения, выполняющиеся в операционной системе. Достигается это тем, что для каждого взаимодействия с пользователем можно обновить только часть страницы, а не перезагружать всю страницу целиком, как в традиционных веб-приложениях.

Рис. Модель веб-приложения

Рис. Сравнение традиционной модели
взаимодействия в веб-приложениях и AJAX
На самом деле идея сделать веб-приложения более похожими на обычные приложения в смысле пользовательского интерфейса не нова и такие возможности уже давно могли быть реализованы с помощью различных технологий: Macromedia Flash, Java Applets, Microsoft ActiveX и т.д. Однако, все они не получили очень широкого распространения из-за того, что использовали частные закрытые решения отдельных фирм, требовали установки дополнительного программного обеспечения и не имели достаточной переносимости между платформами. AJAX лишен этого недостатка.
Хотя AJAX не требует установки дополнительного программного обеспечения, для его работы все-таки необходимо, чтобы в браузере был включен JavaScript, поэтому чтобы приложения были по-настоящему переносимыми, это необходимо предусмотреть. В настоящее время для обхода этого недостатка были добавлены средства в ряд библиотек для поддержки AJAX и выработаны определенные техники для поддержки пользователей с выключенным JavaScript-ом.
Другие недостатки AJAX связаны с удобством использования -- нарушается работа кнопки «Назад» браузера и возможность делать закладки на определенное состояние приложения. Для обхода этих недостатков также разработаны и применяются различные техники.
Внедрение AJAX идет полным ходом как на любительских сайтах, так и на крупных
сайтах, обслуживающих миллионы запросов ежедневно
.
Приведем простой низкоуровневый пример веб-приложения, использующего AJAX, из которого хорошо видно какие технологии и как используются для достижения требуемого эффекта частичного обновления страницы. В примере не будут использованы никакие дополнительные средства, позволяющие упростить разработку AJAX-приложений и повысить уровень абстракции.
Для того, чтобы испытать данный пример необходимо иметь доступ к веб-серверу с поддержкой PHP. Полные исходные коды примера приведены на github-е (в архиве).
Серверная часть примера представляет собой PHP-скрипт, являющийся простейшим веб-сервисом. Понятие веб-сервиса в общем случае не ограничивается SOAP/WSDL-сервисами. Возможно применять и другие XML-протоколы. Один из наиболее популярных из них XML/RPC. В нашем примере для простоты между сервисом и клиентом будут передаваться чистые данные без какой-либо XML-разметки.
Функция разработанного веб-сервиса -- принимать на входе методом POST число и выдавать на выходе это число возведенное в квадрат. Число передается в виде строки и никакой проверки правильности входных данных не производится.
Серверная часть примера test.php
<?php // vim:ts=4 $x = $GLOBALS['HTTP_RAW_POST_DATA']; print($x * $x); ?>
Клиентская часть примера представляет собой HTML-файл с внедренными JavaScript-инструкциями. Клиент посылает веб-сервису число и асинхронно принимает ответ. Асинхронность означает, что веб-браузер не подвисает во время запроса и пользователь может продолжать работать пока запрос выполняется. (рис. 2)
Основой поддержки AJAX в браузере является объект XMLHttpRequest для браузеров Mozilla, Safari и прочих, и объект ActiveX Microsoft.XMLHTTP для браузеров фирмы Microsoft.
Ответ веб-сервиса выдается пользователю с помощью стандартной функции JavaScript alert(), но чаще всего он внедряется непосредственно в страницу с помощью DOM, встроенной в браузер.
Клиентская часть примера test.html
<html>
<head>
</head>
<body>
<script type="text/javascript" language="javascript">
// <![CDATA[		
var http_request = false;
function makeRequest(url) {
	http_request = false;
	if (window.XMLHttpRequest) { // Mozilla, Safari,...
		http_request = new XMLHttpRequest();
		if (http_request.overrideMimeType) {
			http_request.overrideMimeType('text/xml');
		}
	} else if (window.ActiveXObject) { // IE
		try {
			http_request = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				http_request = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
		}
	}
	if (!http_request) {
		alert('Giving up :( Cannot create an XMLHTTP instance');
		return false;
	}
	http_request.onreadystatechange = alertContents;
	http_request.open('POST', url, true);
	http_request.send('5');
}
function alertContents() {
	if (http_request.readyState == 4) {	// COMPLETED
		if (http_request.status == 200) {	// HTTP STATUS
			alert(http_request.responseText);
		} else {
			alert('There was a problem with the request.');
		}
	}
}
// ]]>	
</script>
<span
	style="cursor: pointer; text-decoration: underline"
	onclick="makeRequest('http://freedomnet.ru/services/simple/test.php')">
	Make a request
</span>
</body>
</html>

Рис. Пользовательский интерфейс
примера
Заголовки пересылаемые при вызове веб-сервиса
POST /services/simple/test.php HTTP/1.1 Host: freedomnet.ru User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7 Accept: text/xml,application/xml,application/xhtml+xml,index.htm;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Content-Type: text/xml Content-Length: 1 Pragma: no-cache Cache-Control: no-cache 5 HTTP/1.x 200 OK Date: Wed, 09 Nov 2005 11:40:36 GMT Server: Apache/2.0.54 X-Powered-By: PHP/5.0.5 Content-Length: 2 Keep-Alive: timeout=10, max=100 Connection: Keep-Alive Content-Type: index.htm; charset=WINDOWS-1251 Content-Language: ru 25
В последнее время в сообществе веб-разработчиков AJAX является горячей темой. Неудивительно, что уже появилось множество библиотек поддержки AJAX для различных языков программирования. [2,3] Среди них можно выделить некоторую классификацию. Во-первых, по языку программирования:
По функциональности AJAX-библиотеки можно разделить на:
Рассмотрим компонентно-ориентированные библиотеки поддержки AJAX на примере компонентов для JavaServer Faces (JSF).
JavaServer Faces -- это набор серверных компонентов Java для создания
HTML-интерфейсов. Для него существуют компоненты, использующие
Ajax.
Рассмотрим компонент Progress Bar, который показывает ход выполнения некоторого процесса на сервере в виде заполняющейся полосы и процентов выполнения. (рис. 4)
Данный пример выполняется в любом Java-веб-контейнере, поддерживающем стандарт сервлетов. Я использовал Apache Tomcat 5.5. Полные исходные коды примера приведены на сайте https://bpcatalog.dev.java.net/nonav/ajax/progress-bar-jsf/frames.html.

Рис. Компонент Progress Bar
Текст JSP-страницы с компонентом Progress Bar
<%-- Copyright 2004-2005 Sun Microsystems, Inc.  All rights reserved.  You may not modify, 
use, reproduce, or distribute this software except in compliance with the terms of the 
License at: 
 http://developer.sun.com/berkeley_license.html
 --%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/blueprints/ajax/progress-bar" prefix="d" %>
<f:view>
<html>
<head>
<title>AJAX enabled Button and Progress Bar</title>
</head>
<body>
  <h:form id="form">
  <table>
    <tr><td><d:progressBar id="progressBar" 
                           value="#{process.percentage}" 
                           interval="#{process.pollInterval}" 
                           action="complete" />
        </td> <td> </td></tr>
        
  </table>
  
  <p>For a detailed description of this component, please see <a href="https://bpcatalog.dev.java.net/ajax/progress-bar-jsf/">the blueprints
  catalog entry</a>.</p>
</h:form>
</f:view>
</body>
</html> 
Переменная process соответствуют классу ProcessBean:
Класс ProcessBean
/* Copyright 2005 Sun Microsystems, Inc. All rights reserved. You may not modify, use, reproduce, or distribute this software except in compliance with the terms of the License at: http://developer.sun.com/berkeley_license.html
 */
/*
 * $Id: ProcessBean.java,v 1.2 2005/06/11 06:05:10 edburns Exp $
 */
 
package com.sun.j2ee.blueprints.bpcatalog.ajax.progressbar;
import java.util.Random;
public class ProcessBean {
    
    public ProcessBean() {
    }
    
    private int percentage = 0;
    private int increment = 10;
    
    public int getPercentage() {
        if (100 < percentage) {
            percentage = 0 - increment;
        }
        return percentage += increment;
    }
    
    /**
     * Getter for property randomPercentage.
     * @return Value of property randomPercentage.
     */
    public int getRandomPercentage() {
        
        return random.nextInt(101);
    }
    
    private Random random = new Random();
    /**
     * Holds value of property pollInterval.
     */
    private int pollInterval = 250;
    /**
     * Getter for property pollInterval.
     * @return Value of property pollInterval.
     */
    public int getPollInterval() {
        return this.pollInterval;
    }
    /**
     * Setter for property pollInterval.
     * @param pollInterval New value of property pollInterval.
     */
    public void setPollInterval(int pollInterval) {
        this.pollInterval = pollInterval;
    }
    
} 
Для написания примера AJAX-приложения на Java я выбрал библиотеку
DWR
.
Библиотека Direct Web Remoting (DWR) позволяет «экспортировать» код Java в код JavaScript веб-страницы и непосредственно вызывать Java-методы из веб-страницы. На самом деле эта библиотека реализует удаленные вызовы с помощью технологий AJAX. Кроме того она предоставляет удобные JavaScript-функции для манипулирования содержимым страницы через DOM.
Для выполнения данного примера необходим Java-веб-контейнер, поддерживающий стандарты сервлетов. Я использовал Apache Tomcat 5.5. Кроме того необходимо скачать и установить в контейнер библиотеку DWR. Полные исходные коды примера находятся на github-е (в архиве).
Приведенный пример будет аналогичен примеру из раздела 2 -- возведение числа в квадрат. Только на этот раз код примера будет выглядеть гораздо чище и понятнее, входное значение можно будет вводить непосредственно пользователю, а выходное значение будет внедряться в страницу, а не выводиться через функцию alert().
Java-код примера состоит всего из одного простого класса:
Calculator.java
package org.koliamorev.dwr;
public class Calculator {
	public float Square(float num) {
		return num * num;
	}
}
Этот класс через десриптор dwr.xml экспортируется в JavaScript код:
dwr.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dwr PUBLIC
    "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
    "http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
	<allow>
		<create creator="new" javascript="Calculator">
			<param name="class" value="org.koliamorev.dwr.Calculator" />
		</create>
	</allow>
</dwr>
В JSP-странице мы включаем сгенерированные заглушки для класса Calculator, а также вспомогательный JavaScript-код библиотеки DWR. Кроме того здесь мы задаем функцию назначенную для кнопки «Отправить» и функцию-callback для получения результатов вычислений.
index.jsp
<%@ page language="java" contentType="index.htm; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="index.htm; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<script type='text/javascript' src='dwr/engine.js'></script>
<script type='text/javascript' src='dwr/interface/Calculator.js'></script>
<script type='text/javascript' src='dwr/util.js'></script>
<script type='text/javascript'> 
// <![CDATA[
function sendNumber()
{
    var number = DWRUtil.getValue("number");
    DWRUtil.setValue("result", "");
    Calculator.Square(gotResult, number);
}
function gotResult(number)
{
    DWRUtil.setValue("result", number);
}
// ]]> 
</script>
<p>
  Введите число:
  <input id="number"/>
  <input type="button" value="Возвести в квадрат"
      onclick="sendNumber()"/>
</p>
<p>Ответ: <span id="result"></span></p>
</body>
</html> 
JavaScript-заглушки Java-классов генерируются каждый раз во время вызова страницы. Происходит это через специальный сервлет библиотеки DWR. Поэтому в дексрипторе веб-приложения web.xml мы назначаем переадресацию на этот сервлет всех вызовов адресов вида dwr/*.
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>dwr</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> </web-app>

Рис. Пользовательский интерфейс примера
Обмен данными с сервером
http://localhost:8080/dwr/dwr/exec/Calculator.Square
POST /dwr/dwr/exec/Calculator.Square HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7
Accept: text/xml,application/xml,application/xhtml+xml,index.htm;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Content-Type: text/xml
Content-Length: 119
Cookie: JSESSIONID=E0ACB6407919818A27C1EBA4DD0A6753
Pragma: no-cache
Cache-Control: no-cache
callCount=1
c0-scriptName=Calculator
c0-methodName=Square
c0-id=7260_1132038473906
c0-param0=string:3.1415926
xml=true
HTTP/1.x 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/plain;charset=ISO-8859-1
Transfer-Encoding: chunked
Date: Tue, 15 Nov 2005 07:07:53 GMT
<script type='text/javascript'>
var s0=9.869603;
window.parent.DWREngine._handleResponse('520_1132038593390', s0);
</script>
 
Технология AJAX и вопросы связанные с разработкой таких приложений в настоящее время очень популярны в среде веб-разработчиков и дизайнеров и быстро развиваются. Так, например, в следующих версиях браузера Mozilla планируется добавить более продвинутую поддержку XML в движок JavaScript. Это будет способствовать переходу на XML-формат для обмена данными в AJAX-приложениях (в настоящее время более удобными оказываются простые текстовые форматы). Постоянно открываются какие-либо новые аспекты связанные с этой технологией, отмечаются различные достоинства и недостатки. Но уже сейчас можно сказать, что AJAX прочно занял свое место на огромном количестве сайтов.
Отметим важные вопросы, которые не были рассмотрены в данном докладе: обратная совместимость AJAX-приложений с устаревшими браузерами, техники сохраняющие usability традиционных веб-приложений (кнопка «Назад», соответствие URL и состояния веб-приложения и т. д.).
~area~components.htm, 10.11.2005)
![[*]](footnote.png)
![[*]](footnote.png)
![[*]](footnote.png)
![[*]](footnote.png)
![[*]](footnote.png)