Přejít k navigační liště

Zdroják » Různé » Java na webovém serveru: AJAX formuláře

Java na webovém serveru: AJAX formuláře

Články Různé

Od minulého dílu umožňuje naše aplikace vkládat komentáře, ovšem ne příliš pohodlným způsobem. Dnes si proto ukážeme, jak uživatelům komentování zpříjemnit pomocí oblíbeného AJAXu. Využijeme k tomu knihovnu jQuery na straně klienta a servlety na straně serveru.

Implementace komentářů z minulého dílu byla sice funkční, ale značně nedokonalá. V případě, že uživatel udělal ve formátování komentáře chybu (zadal nepovolené XHTML značky atd.), dostal po odeslání od serveru chybovou hlášku, ale už neměl šanci chyby napravit – byl odkázán na funkci „zpět“ svého prohlížeče, u které není zaručeno, že se vyplněné údaje z formuláře neztratí. Pokud se mu naopak povedlo naformátovat komentář správně, mohlo snadno dojít k několikanásobnému odeslání (pokud by uživatel obnovil stránku).

Naším dnešním cílem proto bude, umožnit uživatelům zobrazit si náhled formátování komentáře a odeslat ho, aniž by se načítala celá stránka – místo klasického odesílání formuláře vyvoláme asynchronní požadavek javascriptem a odpověď serveru zobrazíme v rámci již načtené stránky.

Jako obvykle si nejprve si aktualizujeme zdrojové kódy aplikace pomocí Mercurialu:

$ hg pull
$ hg up "15. díl"

Případně je můžete stáhnout jako bzip2 archiv přes web.

Na straně klienta

S implementací na straně klienta nám pomůže knihovna jQuery, kterou již ve své aplikaci používáme. Umožňuje snadnou práci s AJAXem a odstiňuje nás od odlišností jednotlivých prohlížečů. Klientský kód je stručný a naleznete ho v souboru komentare.js:

komentare.nahled = function() {
    $("#formularKomentuj .vystup").load("komentare", $("#formularKomentuj form").serialize());
};
komentare.odeslat = function() {
    $("#formularKomentuj .vystup").load("komentare?odeslat=true", $("#formularKomentuj form").serialize());
};

jQuery funkce load() vyvolá HTTP požadavek na dané URL (v našem případě komentare  – první parametr), pomocí nějž předá serveru obsah formuláře (ve standardním URL kódování). Odpověď serveru pak tato funkce vloží do elementu, který jsme si pro tento účel připravili. Javascriptové funkce nahled() a odeslat() navážeme na události formuláře místo klasického (synchronního) odeslání, které je spojeno s načtením celé nové stránky.

Formulář vymažeme až po úspěšném uložení komentáře na serveru – vložené údaje se tak uživateli neztratí, ani při dočasné chybě serveru nebo špatné syntaxi komentáře. Smazáním obsahu formuláře se pak vyhneme případnému opětovnému odeslání (komentář s nulovou délkou nelze vložit). Případně bychom mohli formulář skrýt nebo ho nechat třeba „odletět“ pomocí nějakého pěkného efektu, to už nechám na vás (začít můžete třeba u pluginů do jQuery jako je Flip!).

Na straně serveru

Na straně serveru teď potřebujeme nějak obsloužit požadavky, které přicházejí na URL /komentare. K tomu využijeme technologii servletů, se kterou jsme se seznámili v devátém díle. Implementaci datové vrstvy a kontroly formátování máme hotovou už od minule a zapouzdřenou do EJB, takže jí přepisovat nemusíme  – jediné, co je potřeba upravit, je relativně tenká vrstva, která se stará o překlad z HTTP parametrů na objekty a o vykreslení hlášek informujících uživatele o výsledku (původní implementace této vrstvy byla celá v JSP).

Servlety nám umožní příjemnější zápis dané logiky než JSP – přeci jen programovat v dokumentově orientovaném formátu XML cykly a podmínky není dvakrát zábavné ani pro milovníky XML.

Náš servlet se nachází ve třídě Komentare a podstatná je jeho metoda doPost() :

@Override
protected void doPost(HttpServletRequest pozadavek, HttpServletResponse odpoved) throws ServletException, IOException {
    PodnikRemote ejb = hledac.getPodnikEJB();
    /** Načteme HTTP parametry */
    Komentar k = new Komentar();
    k.setPodnik(Integer.decode(pozadavek.getParameter("podnik")));
    k.setNadpis(pozadavek.getParameter("nadpis"));
    k.setKomentar(pozadavek.getParameter("komentar"));
    k.setTyp(Komentar.TYP.valueOf(pozadavek.getParameter("typ")));
    boolean ulozit = Boolean.valueOf(pozadavek.getParameter("odeslat"));
    String jsp;
    try {
        /** Komentář odešleme do nižší vrstvy ke kontrole nebo rovnou k uložení */
        k = ejb.komentuj(k, ulozit);
        pozadavek.setAttribute("komentar", k);
        if (ulozit) {
        jsp = "/WEB-INF/casti/ajaxKomentare/odeslano.jsp";
        } else {
        jsp = "/WEB-INF/casti/ajaxKomentare/nahled.jsp";
        }
    } catch (Exception e) {
        /** Objekty mezi servletem a JSP si můžeme předávat pomocí atributů požadavku */
        pozadavek.setAttribute("chyba", e);
        jsp = "/WEB-INF/casti/ajaxKomentare/chyba.jsp";
    }
    /** O vykreslení XHTML vyýstupu se už zase postará JSP */
    RequestDispatcher rd = getServletContext().getRequestDispatcher(jsp);
    rd.forward(pozadavek, odpoved);
    }

Z HTTP požadavku si nejprve načteme parametry a tím provedeme i jejich základní typovou kontrolu. Nějaké uživatelsky přívětivé chybové hlášky v této fázi nemusíme řešit – pokud by např. v parametru podnik nebyla celočíselná hodnota nebo parametr typ neodpovídala našemu číselníku ( enum), došlo by ke standardní chybě 500 Interní chyba serveru. To se ale stane jen v případě, že by se uživatel v aplikaci „vrtal“ a podstrkával jí ručně svoje parametry – na takového uživatele nemusíme brát zřetel a vyrábět pro něj přívětivé chybové hlášky.

Školení Javy

Java je multiplatformní programovací jazyk, který vytvořila a vyvíjí společnost Sun. Java je silný, objektově orientovaný jazyk se širokou komunitou, nabízející především vysokou produktivitu vývoje. Přijďte na školení Základy programovacího jazyka Java 7. 9. 2010 od 9:00, nebo na Pokročilejší kurz jazyka Java 8. 9. 2010 opět od 9:00.

V Javě se skvěle programuje, ale na druhou stranu se v ní špatně vytvářejí HTML dokumenty  – mohli bychom k tomu sice použít HttpServletResponse.getWriter().print(String
text);
a „lepit“ výsledné HTML z kousků textu, ale nejen že by to bylo nepohodlné, ale také by byla velká pravděpodobnost, že někde uděláme chybu a výsledný kód bude obsahovat např. neuzavřené značky. Naštěstí existuje způsob, jak skloubit programování v Javě a vytváření HTML v JSP dohromady. Pomocí RequestDispatcher u a jeho metody forward() můžeme řetězit za sebe servlety a JSP (což jsou ve výsledku taky servlety) a díky tomu udělat část práce v javovském kódu a část v JSP.

V připojeném JSP máme k dispozici jednak původní GET/POST parametry, které dorazily na servlet a jednak JSPčku můžeme předávat další data (objekty) pomocí atributů požadavku – HttpServletRequest.setAttribute(), které jsou identifikované jednoduše textovým klíčem.

Vytvořený servlet nezapomeneme přidat do souboru web.xml a namapovat na požadované URL:

<servlet>
    <description>Odesílání a náhledy komentářů pomocí AJAXu.</description>
    <servlet-name>komentare</servlet-name>
    <servlet-class>cz.frantovo.nekurak.servlet.Komentare</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>komentare</servlet-name>
    <url-pattern>/komentare</url-pattern>
</servlet-mapping>

JSP, na které se v servletu odkazujeme, je velmi jednoduché a nám známé – nový je jen způsob, kterým přistupujeme k atributům požadavku (objektům). Ty se nacházejí v poli requestScope[] pod námi zvoleným klíčem. Dále s těmito objekty pracujeme, jak jsme zvyklí (pomocí .komentar přistupujeme k vlastnosti objektu – ve výsledku se volá metoda getKomentar() třídy Komentar).

<?xml version="1.0" encoding="UTF-8"?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
      xmlns:fn="http://java.sun.com/jsp/jstl/functions"
      xmlns:nk="urn:jsptagdir:/WEB-INF/tags/nekurak"
      version="2.0">
    <div>
    <p class="informacniHlaska"><fmt:message key="komentare.nahledNadpis"/>:</p>
    <!-- XHTML je už zkontrolované: → vypíšeme ho rovnou -->
    ${requestScope['komentar'].komentar}
    </div>
</jsp:root>

Závěr

Dnes jsme vylepšili naši aplikaci tak, aby se formulář pro komentování odesílal AJAXem, což uživatelům zpříjemní práci s webem – tedy alespoň těm se zapnutým Javascriptem (pro ostatní je tu původní implementace s klasickým odesíláním HTML formuláře). Při tom jsme si prakticky ukázali, jak skloubit servlety a JSP a mít z obou to lepší – ze servletů programování a z JSP tvorbu HTML/XML dokumentů.

Odkazy

Komentáře

Odebírat
Upozornit na
guest
18 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
Zobrazit všechny komentáře
pajamu

Je to už onlajn na nekurak.net? :) Nějak to tam nevidím.

pajamu

Tak to se omlouvám, zřejmě jsem to přehlédl. :)

smilelover

Neda mi to a musim zminit JSF 2.0, se kterymi je ajaxove odesilani formularu o mnoho jednodussi ;)
Ale je mi jasne, ze nebudes do projektu tahat Faces jen kvuli tomu ;)

peter

Myslis nieco taketo?
http://zdrojak.root.cz/clanky/java-na-webovem-serveru-ajax-formulare/
http://www.developer.com/java/web/article.php/10935_3870686_2/Inside-JSF-20s-Ajax-and-HTTP-GET-Support.htm
A myslis to vazne?
Kde je tam nejaka RESTovskost?
Ako tam volam POST, alebo DELETE metodu?
Myslim ze JSF maju malo spolocneho s principmi Webu. :(

smilelover

Nejak se nam to v hlavince pomichalo, ze? :)
Fanaticke cpani RESTu vzdycky a vsude je zcela kontraproduktivni a k nicemu. Delas z toho svatou valku a podstata veci ti unika. Necpu JSF vsude a vubec netvrdim, ze se na vsechno hodi. A stejne tak nema smysl to delat s klasickymi request-response RESTful rameworky.
Mene ideologie, vice pragmatismu.

peter

Nejak se nam to v hlavince pomichalo, ze? :)
Ze sa Vam to v hlavicke pomiesalo som si vsimol a preto som sa pokusil Vam v tej hlvicke svojim prispevkom spravit poriadocek. :)
Fanaticke cpani RESTu vzdycky a vsude je zcela kontraproduktivni a k nicemu.
REST predstavuje fundamentalne principy na ktorych funguje Web, prosim dostudujte si to. Cim sa Vase riesenie vzdaluje viac od RESTu, vzdaluje sa od Webu.
REST == Web
Delas z toho svatou valku a podstata veci ti unika. Necpu JSF vsude a vubec netvrdim, ze se na vsechno hodi. A stejne tak nema smysl to delat s klasickymi request-response RESTful rameworky.
Mene ideologie, vice pragmatismu.

Tento Vas nazor je typickym pre tych, ktori neovladaju tie zakladne principy webu a myslia si, ze ked sa naucia nieco klikat v nejakom frameworku, tak vlastne rozumeju Webu. :(
Myslim ze o RESTe a Webe sa napisalo uz dost. Je cas aby ste si to precitali, pokusili sa to pochopit a zacali tie principy respektovat.
Vy si myslite, ze rozumiete Webu lepsie ako ti, ktori ho narhli? :)
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

martin

No on je mozna trochu problem v tom, ze kdyz Web (resp. HTTP) vznikal, tak se nepocitalo s tim, ze se v tech samych technologiich budou psat tak „komplikovane“ aplikace, ktere na dnesnim Webu bezi, nemluve o ruznych intranetovych aplikacich a IS. Souhlasim s Danielem – je rada situaci, kdy stavovost (rozumej stateful aplikace) je nanejvys vhodna.
A jeste jedna poznamka: framework neznamena klikani.

peter

Ak hovorime o Webovej aplikacii, je to aplikacia ktora je v zhode s principmi Webu, teda RESTu.
Ak pouzijete prehliadac a HTTP inym sposobom, je to na vas, ale potom to uz nie je Webova aplikacia. Je to taky „Webovy paskvil“. To su asi presne tie intranetove aplikacie a IS, o ktorych hovorite. Tie paskvily vacsinov robia „odbornici“ s nazormi ake ma Daniel Kvasnička ml., vacsinou bezia iba v IE6 a su napisane v JSF. :)
Poznamka: Nie som si isty, ci Daniel Kvasnička ml. si pod FW nepredstavuje prave nieco klikacie. :)
Nikomu, kto rozumie Webu nemoze vyhovovat JSF.

martin

To je trochu definice kruhem :) IE6 je vsak podle me stejny nepritel jak pro tvurce „paskvilu“, tak pro tvurce „pravovernych“ webovych aplikaci, jako jste Vy.

Martin Malý

Pánové, žádám vás: držte se tématu a nenechte rozhořčení cloumat svými majestáty. Děkuji.

peter
jehovista

„This video is private“

peter

Mozno maju nieco proti jehovistom :)

Přístupnost není jen o splnění norem: nový pohled na inkluzivní design

Přístupnost a inkluze možná nepatří mezi nejžhavější témata digitálního světa – dokud o nich nezačne mluvit Vitaly Friedman. Na WebExpo 2024 předvedl, že inkluzivní design není jen o splněných checkboxech, ale hlavně o lidech. S energií sobě vlastní obrátil zažité přístupy naruby a ukázal, že skutečně přístupný web je nejen možný, ale i nezbytný.

Efektivnější vývoj UI nebo API: Co si odnést z WebExpo 2025?

Různé
Komentáře: 0
Jak snadno implementovat moderní uživatelské rozhraní? Které funkce brzdí rychlost vašeho webu? A kdy raději sami přibrzdit, abychom využitím AI nepřekročili etické principy? Debatu aktuálních dev témat rozdmýchá sedmnáctý ročník technologické konference WebExpo, která proběhne v Praze od 28. do 30. května. Který talk či workshop si rozhodně nenechat ujít? Toto je náš redakční výběr z vývojářských hroznů.

Zapřáhněte AI jako nikdy předtím. Květnová konference WebExpo přivítá hvězdy technologického světa

Od 28. do 30. května 2025 promění pražský Palác Lucerna na tři dny technologická konference WebExpo. Na programu je více než 80 přednášek a workshopů od expertů z celého světa. WebExpo tradičně propojuje vývojáře, designéry, marketéry i byznysové lídry a nabízí praktické dovednosti, strategické myšlení a přináší nejnovější trendy nejen v oblasti AI.