Moderní webové aplikace
3.5 Anatomie činnosti AJAXu
0Webové stránky využívající AJAX jsou stránky zapsané pomocí značkovacího jazyka HTML, nebo XHTML (mohou být samozřejmě generované na straně serveru, např. pomocí JSP).
Výhodou Javy na straně serveru (konkrétně Java Platform, Enterprise Edition) je přímá podpora validace dat, správa identity uživatele a především perzistentnost. Díky tomu je programátor ušetřen vytváření vlastních rutin pro tyto akce.
Obr.4: Model klasické webové aplikace a model aplikace postavené na AJAXu (převzato z [1] )
3.5.1 Generování události
Funkce JavaScriptu jsou volány důsledkem události vyvolané uživatelem. Je možné tedy namapovat funkci na event např. onClick na tlačítku. Pokud je tlačítko stisknuto, je volána tato metoda a stránka nadále zůstavá beze změny.
<input type=“button“ value=“Odeslat“ onClick=“odesli();“ />
3.5.2 Vytvoření objektu XMLHttpRequest
V závislosti na typu prohlížeče je vytvořen objekt XMLHttpRequest, je ověřen a provázán s obsluhou události návratu – callback() funkce. Pro otevření spojení jsou potřeba tři parametry: http metoda (v tomto případě POST či GET), adresu komponenty na straně serveru, která bude požadavek zpracovávat a boolovskou příznak, zda bude požadavek zpracováván asynchronně.
if(window.XMLHttpRequest)
var xmlhttp = new XMLHttpRequest;
else if(window.ActiveXObject)
var xmlhttp = new ActiveXObject („Microsoft.XMLHTTP“);
else
return false;
xmlhttp.open(metoda, url, typ);
xmlhttp.onreadystatechange = function() {
obsluha(xmlhttp);
};
3.5.3 Připojení na server
Odeslání požadavku je realizováno funkcí xmlhttp.send(content). Pokud je pro
spojení použitá metoda GET (tu je vhodné použít v případě, že pro stejný odesílaný obsah je očekáván pokaždé stejná odpověd), u které může být obsah ponechán prázdný, jsou data připojena jako parametr k url. V důsledku toho je limitována velikost (délka řetězce) těchto dat.
Pokud jsou data odesílaná metodou POST (ta se využívá v případě, že odesílaná data zasáhnou do stavu serverové aplikace), je nutné připojit hlavičku Content-type. V tomto případě není velikost odesílaných dat nijak omezena (snad jenom možným vypršením časového limitu na straně serveru).
xmlhttp.setRequestHeader(„Content-Type“,
„application/x-www-form-urlencoded“);
xmlhttp.send(content);
3.5.4 Zpracování požadavku serverem
public class SomeActionServlet extends HttpServlet {
private ServletContext context;
public void init(ServletConfig config) throws ServletException {
super.init(config);
this.context = config.getServletContext();
}
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
String parametr = request.getParameter(„parametr“);
if (parametr != null) {
response.setContentType(„text/xml“);
response.setHeader(„Cache-Control“, „no-cache“);
response.getWriter().write(„<odpoved>zpracovano</odpoved>“);
} else {
response.setContentType(„text/xml“);
response.setHeader(„Cache-Control“, „no-cache“);
response.getWriter().write(„<odpoved>chyba</odpoved>“);
}
}
3.5.5 Zpracování odpovědi objektem XMLHttpRequest
function obsluha(xmlhttp) {
if (xmlhttp.readyState == 4) {
if(xmlhttp.status == 200) {
var odpoved =
xmlhttp.responseXML.getElementsByTagName(‚odpoved’);
…
3.5.6 Aktualizace HTML DOM reprezentace
…
<div id=“co_zmenit_id“> Obsah, který bude přepsán </div>
…
document.getElementById(‚co_zmenit_id‘).innerHTML = odpoved;
2.4 Prostředky pro kontrolu vstupu od uživatele
0Validace – je možno ji definovat pro kteroukoliv vstupní komponentu. Po specifikované akci (typicky odeslání dat z formuláře) jsou zadaná data ověřena, pokud splňují danou podmínku. Pokud ano, pokračuje se ve zpracovávání přijatých dat; pokud ne, je generována případná definovaná chybová hláška a zpracování formuláře je ukončeno.
<ui:textField binding=“#{Page1.textField1}“ id=“textField1″
validator=“#{Page1.longRangeValidator1.validate}“/>
Tab. III: Navázání validátoru na komponentu TextField
Komponenta message je svázána s komponentou, pro niž generuje chybovou hlášku pomocí atributu for.
<ui:message binding=“#{Page1.message1}“ id=“message1″
for=“textField1″/>

<ui:textField binding=“#{Page1.textField1}“
converter=“#{Page1.dateTimeConverter1}“ id=“textField1″/>
3 AJAX
03.1 Historie
3.2 WEB 2.0
Na jednu stranu se může zdát, že Web 2.0 je označením pro souhrn velice progresivních technologií, na stranu druhou již většina technologií, které do tohoto souhrnu spadají existuje delší dobu a weby, které tyto technologie využívají „označovány nálepkou“ Web 2.0 nejsou. Spíše než o revoluci se tedy jedná o pouhou evoluci, z důvodu poptávky po novějších technologiích – zvyšují se kapacity přípojek koncových uživatelů, počty uživatelů internetu rostou, místo obrázků jsou maily posílány videa, roste potřeba sdílení multimediálního obsahu… Jak bylo napsáno výše, jedná se o souhrn moderních technologií, které mohou být (při správném použití) velkým přínosem pro vývojáře a stejně tak dobrým pomocníkem pro uživatele.
- Na AJAXu založené Rich Internet Aplikace
- Rich Internet Aplikace bez použití AJAXu
- Kaskádové styly
- Semanticky správné XHTML značkování
- Informační kanály (RSS a Atom)
- Sociální sítě (Folksonomie, weblogy, wiki…)
- Sdružování služeb nabízených na různých webech na jedno místo (mohou sem spadat i uvedené RSS)
- Representation State Transfer
- Programová rozhraní webových služeb (SOAP)
3.3 Používané technologie
- Definice dokumentu pomocí XHTML – prakticky se jedná o Document Object Model (DOM) reprezentující zobrazení webové stránky zapsaný jako stromová struktura
- Definice stylů stránky pomocí Cascading Style Sheets (CSS)
- Propojení zobrazené stránky za pomocí XML jazyka (je možné použít i jakýkoliv jiný formát, např. HTML, čistý text, či JavaScript Object Notation, XML je ovšem z hlediska rozšířenosti nástrojů pro parsování tohoto typu nejvhodnější)
- Asynchronní metoda pro získávání dat – XMLHttpRequest
- Rutiny v JavaScriptu umožňující spojení se serverem na pozadí a upravující nebo modifikující DOM stránky
3.4 Příklady praktického použití AJAXu
Technologie AJAX je ideální například pro následující činnosti:
- Validace položek formulářů v reálném čase – v praxi se využívá např. pro ověření správnosti seriového čísla, neexistence loginu nově vytvářeného uživatele…
- Autokompletace – v češtině se vžil pojem „našeptávač“ – při psaní do pole uživatel má možnost vybíraz z odpovídajích možností, aby nemusel vypisovat celou frázi
- Načítání na vyžádání – načtení konkrétní části stránky na pozadí a vložení do existujícího DOM
- Sofistikované komponenty – dynamicky generované stromové struktury, menu tabulky…
- Serverem vynucená změna obsahu – aktualizování objektů na stránce bez zásahu uživatele – měnové kurzy, kurzy sázek, hlasování
- Částečné odeslání – odeslání dat bez nutnosti překreslení celé stránky
2.8 Navigace mezi stránkami
0Málokterá webová aplikace je tvořená pouze jedinou stránkou, většinou se jedná spíše o soustavu JSP stránek, které jsou vzájemně propojeny. Toto propojení není tvořeno statickými odkazy, jako v případě HTML dokumentu. Navigace je definována opět v XML struktuře (soubor navigation.xml), jako soustava navigačních pravidel, tzv. navigation-case elementů, ze kterých se vybírá na základě výsledku prováděné akce.
<navigation-rule>
<from-view-id>/Page1.jsp</from-view-id>
<navigation-case>
<from-outcome>prejdi</from-outcome>
<to-view-id>/Page2.jsp</to-view-id>
</navigation-case>
</navigation-rule>
Touto akcí může být například stisknutí tlačítka pro odeslání formuláře, čili přímé aktivování komponenty typu UICommand, nebo se může jednat o návratovou hodnotu některé metody, která mohla být vyvolána na základě nějaké předchozí akce. V praxi se jedná o návratovou hodnotu typu string, která je porovnávána s jednotlivými navigation-case elementy a na jejich základě může zobrazit další stránku (definovanou pomocí emelentu to-view-id).
<ui:button action=“#{Page1.buton1_action}“
binding=“#{Page1.button1}“ id=“button1″ text=“Přejít“/>
public String button1_action() {
return „prejdi“;
}
Tab. XIII: Handler zpracovávající událost stisku tlačítka
2.7 Vytvoření JSP
0private TextField textField1 = new TextField();
public TextField getTextField1() {
return textField1;
}
public void setTextField1(TextField tf) {
this.textField1 = tf;
}