Minule jsme dokonΦili povφdßnφ o servletech. V tomto - ji₧ zßv∞reΦnΘm - dφlu naÜeho malΘho pr∙vodce programovßnφm pro web se jeÜt∞ podφvßme na strßnky JSP a alespo≥ krßtce si povφme o zvlßÜtnostech lad∞nφ tohoto druhu program∙.
Strßnky JSP
Jak jste se snad p°esv∞dΦili minule, servlety jsou skv∞lß v∞c - ale takΘ majφ svΘ problΘmy. ╚asto je obsah HTML strßnky z v∞tÜφ Φßsti "statick²", pevn∞ dan², a pouze malΘ ·seky se vytvß°ejφ dynamicky, na zßklad∞ po₧adavk∙. Pak tvo°φ p°evß₧nou Φßst servletu p°φkazy println(), kterΘ vypisujφ stßle stejn² zdrojov² k≤d HTML. Jist∞ si dovedete p°edstavit, ₧e napsat takov² servlet je ·mornß prßce.
A prßv∞ tady ocenφme tzv. strßnky JSP. Zkratka pochßzφ z anglickΘho JavaServer Pages, a znamenß tedy n∞co jako "javskΘ serverovΘ strßnky".
Seznamte se...
Jako nejjednoduÜÜφ p°φklad strßnky JSP si vezmeme obyΦejn² HTML soubor, nap°. tento:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- Soubor JSP1.jsp -->
<HTML> <HEAD>
<TITLE>Prvnφ JSP strßnka</TITLE>
</HEAD> <BODY>
<CENTER>
<H1>ZaΦφnßme s JSP</H1>
a tohle je naÜe prvnφ strßnka.
</BODY> </HTML>
Soubor ulo₧φme pod nßzvem JSP1.jsp do adresß°e, kam se na serveru uklßdajφ obyΦejnΘ strßnky HTML (na serveru Tomcat 3.2 to je podadresß° Webapps\Root v domovskΘm adresß°i serveru), a vy₧ßdßme si jej stejn²m zp∙sobem jako jakoukoli b∞₧nou strßnku HTML.
Typickß strßnka JSP obsahuje sm∞s HTML textu a tzv. skriptovacφch prvk∙. VeÜker² text jazyka HTML p°ejde beze zm∞n do v²slednΘ HTML strßnky. (Proto se o HTML textu ve strßnkßch JSP takΘ hovo°φ jako o "Üablon∞ textu".) Pokud tedy strßnka JSP obsahuje pouze HTML text, bude v²sledkem HTML strßnka naprosto identickß se strßnkou p∙vodnφ, jen odezva serveru bude pomalejÜφ.
Skriptovacφ prvky, zvanΘ tΘ₧ skriptlety, p°edstavujφ ·seky javskΘho programu "propaÜovanΘ" do HTML textu. P°ijde-li po₧adavek na strßnku JSP, server tuto strßnku nejprve p°elo₧φ do Javy - vytvo°φ servlet, kter² generuje odpovφdajφcφ strßnku HTML - a tento servlet spustφ. Vytvo°en² servlet bude mimo jinΘ obsahovat metodu _jspService(), kterou bude volat nßm u₧ znßmß metoda service().
Skriptlety
Pod tφmto podivn²m oznaΦenφm (v originßle scriptlets; ₧e by "skriptφky"?) se skr²vajφ ·seky javskΘho textu uzav°enΘ mezi znakovΘ posloupnosti <% a %>. D°φve ne₧ p°ejdeme k jejich druh∙m, zastavφme se u komentß°∙ v JSP.
Vlo₧φme-li do strßnky JSP komentß° podle pravidel HTML, nap°.
<!-- Soubor JSP1.jsp -->
p°ejde tento komentß° do vytvo°enΘ HTML strßnky. U₧ivatel ho sice na obrazovce neuvidφ, ale znaky, jimi₧ je tvo°en, se budou po sφti p°enßÜet. Pokud chceme, aby se komentß° do textu vytvo°enΘ HTML strßnky nep°evzal (tzv. skryt² komentß°, hidden comment), pou₧ijeme zßpis
<%-- Soubor JSP1.jsp --%>
Jak plyne z definice, prßv∞ jsme pou₧ili skriptlet. Podobn∞ jako zde znaky -- znamenaly, ₧e jde o skryt² komentß°, jsou jednotlivΘ druhy skriptlet∙ (o nich₧ si povφme v nßsledujφcφch odstavcφch) rozliÜeny konkrΘtnφm znakem za ·vodnφ dvojicφ <%.
V²razy
V²raz v JSP strßnce je vlastn∞ libovoln² v²raz vyhovujφcφ pravidl∙m Javy, zapsan² mezi znakovΘ posloupnosti <%= a %>. V²raz se vyhodnotφ a jeho hodnota se zapφÜe na odpovφdajφcφ mφsto do v²slednΘ HTML strßnky.
V takov²ch v²razech m∙₧eme pou₧φvat p°eddefinovanΘ prom∞nnΘ s t∞mito v²znamy:
* request je prom∞nnß typu HttpServletRequest p°edstavujφcφ po₧adavek;
* response je prom∞nnß typu HttpServletResponse p°edstavujφcφ odezvu na po₧adavek;
* out je v²stupnφ proud typu PrintWriter;
* session je instance typu HttpSession odpovφdajφcφ aktußlnφmu sezenφ;
* application obsahuje instanci typu ServletContext; k dispozici je vÜak jeÜt∞ n∞kolik dalÜφch prom∞nn²ch.
Prvnφ dv∞ p°eddefinovanΘ prom∞nnΘ, request a response, majφ t²₧ v²znam jako stejnojmennΘ parametry metod pro obsluhu po₧adavku v servletu.
Jako p°φklad pou₧itφ v²razu napφÜeme strßnku JSP, kterß u₧ivateli °ekne, kdy jeho po₧adavek dorazil na server (podobn²m sloganem zaΦφnal v Üedesßt²ch letech jeden populßrnφ rozhlasov² po°ad). K tomu postaΦφ vytvo°it nov² objekt t°φdy java.util.Date a pou₧φt ho jako v²raz. Celß strßnka m∙₧e vypadat takto:
<%-- Soubor Cas.jsp --%>
<HTML> <HEAD>
<TITLE> Nep°esn² Φas </TITLE>
</HEAD> <BODY>
<H1>Je prßv∞ tolik hodin, kolik prßv∞ je.</H1>
<P>VßÜ po₧adavek dorazil na server
<%= new java.util.Date() %> <P>
Mßte-li na sv²ch hodinkßch vφce nebo mΘn∞, nenφ to naÜe vina.
</BODY> </HTML>
V²sledek ukazuje obrßzek 1.
Stiskneme-li v prohlφ₧eΦi tlaΦφtko Obnovit, dostaneme nov² (aktußln∞jÜφ) Φasov² ·daj. (DalÜφ ·pravy - nap°. formßtu data - si m∙₧ete zkusit sami.)
Javsk² k≤d
Vlo₧en² ·sek javskΘho k≤du signalizuje "samotnß" ·vodnφ dvojice <%, tj. bezprost°edn∞ za nφ nßsleduje n∞kter² z "bφl²ch znak∙" (mezera, nov² °ßdek atd.); ·sek, jak u₧ vφme, konΦφ °et∞zcem %>. Tento k≤d bude vlo₧en do metody _jspService(). I v javskΘm k≤du samoz°ejm∞ m∙₧eme pou₧φvat p°eddefinovanΘ prom∞nnΘ, m∙₧eme volat jejich metody apod.
Jako p°φklad napφÜeme strßnku JSP, kterß nßm ukß₧e typ po₧adavku a vÜechna jeho zßhlavφ.
Zavolßme-li tuto strßnku z prohlφ₧eΦe pomocφ URL http://localhost:8080/Pozadavek.jsp, objevφ se obrßzek 2.
Direktivy
Direktivy majφ tvar
<%@ jmΘno_direktivy atribut="hodnota" %>
Atribut∙ m∙₧e b²t i vφce; pak se zßpisy atribut="hodnota" zapisujφ za sebe (nebo spφÜe pod sebe) a odd∞lujφ se jen bφl²mi znaky; hodnota musφ b²t v₧dy uzav°ena v uvozovkßch. JSP pou₧φvß direktivy page, include a taglib. Prvnφ z nich umo₧≥uje pracovat se strukturou strßnky JSP, druhß slou₧φ ke vklßdßnφ soubor∙ do JSP strßnek a t°etφ umo₧≥uje pou₧φvat u₧ivatelem definovanΘ znaΦky ve strßnkßch JSP. Podrobn² rozbor by p°esßhl mo₧nosti naÜeho serißlu, a proto mi nezb²vß ne₧ odkßzat na dokumentaci [6] nebo na knihu M. Halla [1]. (V dob∞, kdy budete tento Φlßnek Φφst, u₧ by m∞l b²t na trhu Φesk² p°eklad.)
Zde si alespo≥ °ekneme, ₧e atribut import direktivy page umo₧≥uje zp°φstupnit ve strßnce JSP (tj. v jejφch v²razech, javsk²ch k≤dech nebo deklaracφch) t°φdu nebo cel² balφk, podobn∞ jako p°φkaz import ve zdrojovΘm souboru v Jav∞.
V p°edchozφm p°φkladu jsme pou₧ili rozhranφ java.util.Enumeration. Vlo₧φme-li jako prvnφ °ßdek direktivu
<%@ page import="java.util.*" %>
m∙₧eme v deklaraci prom∞nnΘ hn vynechat kvalifikaci jmΘnem balφku:
<%
Enumeration hn = request.getHeaderNames();
...
Deklarace
Deklarace v JSP zaΦφnß <%! a m∙₧e obsahovat libovolnou deklaraci vyhovujφcφ syntaktick²m pravidl∙m Javy. Tato deklarace se ulo₧φ do t∞la t°φdy servletu, kter² vznikne p°ekladem JSP strßnky. (Jde tedy o deklaraci datovΘ slo₧ky nebo metody servletu. Jak jsme vid∞li v p°edchozφm p°φkladu, m∙₧e i javsk² k≤d obsahovat deklaraci prom∞nnΘ, p∙jde ovÜem o prom∞nnou lokßlnφ v metod∞ _jspService().)
Poznamenejme, ₧e v deklaracφch nelze pou₧φvat p°eddefinovanΘ prom∞nnΘ.
Jako p°φklad napφÜeme strßnku JSP, kterß bude poΦφtat faktorißly nezßporn²ch cel²ch Φφsel. (Jist∞ si pamatujete, ₧e faktorißl Φφsla n se znaΦφ n! a je to souΦin 1.2. ... . n. Nenφ definovßn pro zßpornß Φφsla, navφc platφ 0! = 1.) Nejprve vytvo°φme formulß° HTML, kter² bude obsahovat jedno vstupnφ pole pro zadßnφ Φφsla a tlaΦφtko pro jeho odeslßnφ. I kdy₧ jde o tΘm∞° doslovnou analogii formulß°e z minulΘho dφlu, pro pohodlφ si ho zde zopakujeme:
Jeho faktorißl je: <%= f(request.getParameter("cislo"))%>
<%!
// Funkce pro v²poΦet faktorißlu
private String f (String co)
{
try {
// P°eve∩ znakov² °et∞zec na Φφslo
int n = Integer.parseInt(co);
if(n < 0) return "╚φslo musφ b²t nezßpornΘ";
long s = 1; // s obsahuje v²sledek
while(n > 1) s *= n--; // Vlastnφ v²poΦet
return String.valueOf(s);
}
catch(Exception e)
{
return "èpatn∞ zadanΘ Φφslo.";
}
}
%>
</BODY> </HTML>
V²stup tΘto strßnky JSP ukazuje obrßzek 3.
JSP a ΦeÜtina
V minulΘm dφlu jsme si °ekli, ₧e p°i p°enosu ΦeskΘho textu z formulß°e do servletu narazφme na problΘmy, a ukazovali jsme si, jak je lze °eÜit. Je to s podivem, ale strßnky JSP podobn²mi neduhy netrpφ. O tom se snadno p°esv∞dΦφme, jestli₧e v p°edchozφm p°φkladu zadßme mφsto Φφsla op∞t onu znßmou v∞tu o ₧lu¥ouΦkΘm koni. V²sledek ukazuje obrßzek 4.
Podmφn∞n² text
N∞kdy pot°ebujeme, aby se do v²slednΘ strßnky vlo₧il r∙zn² text v zßvislosti na tom, zda je spln∞na n∞jakß podmφnka. Trik, kter² to umo₧≥uje, je zalo₧en na tom, ₧e:
* jednotlivΘ °ßdky HTML textu ("Üablony textu") se p°evßd∞jφ na p°φkazy v²stupu a uklßdajφ se do t∞la metody _jspService() v po°adφ, v jakΘm jsou zapsßny ve zdrojovΘm souboru;
* skriptlety se beze zm∞ny vklßdajφ do zdrojovΘho k≤du metody _jspService() op∞t v po°adφ, v jakΘm jsou zapsßny v textu strßnky JSP;
* po°adφ skriptlet∙ a Üablon textu se zachovßvß.
Z toho plyne, ₧e m∙₧eme napsat nap°. takovouto konstrukci:
<% if(podm) { %>
<H1> Slßva! Podmφnka je spln∞na.</H1>
<% } else { %>
<SMALL>Bohu₧el, vÜechno je jinak.</SMALL>
<% } %>
Podle toho, zda je spln∞na podmφnka podm, se vlo₧φ do v²stupu jeden nebo druh² nßpis.
DalÜφ prvky
Na strßnkßch JSP m∙₧eme vedle dosud uveden²ch prvk∙ pou₧φt jeÜt∞ dalÜφ, kterΘ umo₧≥ujφ vlo₧it aplet, pou₧φt komponentu JavaBeans atd. V∞tÜina t∞chto prvk∙ pou₧φvß syntaxi zalo₧enou na jazyce XML. To znamenß, ₧e zaΦφnß ·vodnφ znaΦkou <jsp:xxx>, pak nßsleduje t∞lo prvku a koncovß znaΦka tvaru </jsp:xxx>. ZnaΦky, kterΘ nemajφ t∞lo, majφ tvar <jsp:xxx/> (a neexistuje k nim koncovß znaΦka). Ve znaΦce mohou b²t uvedeny parametry, nap°φklad
</jsp:xxx width="25" height="100">; hodnota parametru musφ b²t v uvozovkßch.
Chceme-li t°eba, aby vytvo°enß strßnka JSP obsahovala aplet zalo₧en² na JDK 1.2, kter² pou₧φvajφ odpovφdajφcφ plug-in, pou₧ijeme prvek <jsp:plugin>. V prvnφm dφlu naÜeho serißlu jsme napsali aplet Aplet1, kter² vypisoval jak²si mravouΦn² nßpis. Budeme-li chtφt vlo₧it tento aplet do strßnky JSP a pou₧φt p°itom JDK 1.2, napφÜeme
<jsp:plugin type="applet"
code="Aplet1.class"
width="300" height="150">
</jsp:plugin>
Do prvku <jsp:plugin> m∙₧e b²t vno°en prvek <jsp:fallback> uvßd∞jφcφ alternativnφ text, kter² zobrazφ prohlφ₧eΦe, je₧ nepodporujφ Javu (nebo kdy₧ se nepoda°φ nainstalovat plug-in).
Dßle m∙₧e b²t do prvku <jsp:plugin> vno°en prvek <jsp:params>, kter² uvßdφ specifikaci parametr∙ apletu. P°edchozφ text bychom tedy mohli upravit nap°. takto:
P°i lad∞nφ aplikacφ zalo₧en²ch na servletech jde o n∞kolik r∙zn²ch problΘm∙. Prvnφm z nich je odlad∞nφ vlastnφho algoritmu pro zpracovßnφ po₧adavku, druh²m pak je odlad∞nφ vytvß°enΘ HTML strßnky. DalÜφ problΘmy se mohou t²kat sφ¥ovΘho spojenφ, jeho rychlosti atd.
Poznamenejme, ₧e profesionßlnφ v²vojovΘ nßstroje obvykle nabφzejφ mo₧nost spustit servlet p°φmo ve v²vojovΘm prost°edφ, zobrazit si jeho v²stup bez pou₧itφ prohlφ₧eΦe atd. V dalÜφm textu ale nep°edpoklßdßm ₧ßdn² konkrΘtnφ nßstroj.
Webov² server
P°i v²voji servlet∙ je prakticky nezbytnΘ mφt na poΦφtaΦi instalovan² n∞kter² z webov²ch server∙ nebo jejich nßhra₧ek umo₧≥ujφcφch spouÜt∞t servlety a JSP. SpouÜtφme-li servlety na takovΘmto lokßlnφm serveru, mßme k dispozici javskou konzolu, na kterou si m∙₧eme vypisovat ladicφ informace.
O serveru Apache Tomcat (apaΦsk² kocour) od Apache Software Foundation jsme ji₧ hovo°ili ve druhΘm dφlu tohoto serißlu; dopl≥me jeÜt∞, ₧e ho lze pou₧φvat jako samostatn² server pro lad∞nφ nebo jako dopln∞k do webovΘho serveru Apache, kter² mu umo₧≥uje spouÜt∞t servlety a JSP.
Vedle toho lze pro lad∞nφ pou₧φt JavaServer Web Development Kit (JSWDK) od firmy Sun. O n∞m lze zφskat podrobn∞jÜφ informace na adrese [8]. Jde o stroj pro spouÜt∞nφ servlet∙ podle specifikace 2.1 a JSP podle specifikace 1.0. JSWDK vÜak ji₧ nenφ dßle vyvφjen a firma Sun nabφzφ na sv²ch strßnkßch ke sta₧enφ Tomcat.
DalÜφ mo₧nost p°edstavuje LiteWebServer od Gefion Software, kter² si lze stßhnout z [9]. V souΦasnΘ dob∞ aktußlnφ verze 2.2.2 implementuje servlety verze 2.2 a JSP verze 1.1.
Adresß° pro lad∞nΘ servlety
N∞kterΘ servery majφ zvlßÜtnφ adresß° pro servlety, jejich₧ t°φdy se Φasto m∞nφ (jin²mi slovy pro lad∞nΘ servlety). Zm∞nφ-li se soubor .class hlavnφ t°φdy servletu v tomto adresß°i, server ji automaticky znovu zavede do pam∞ti.
Server Apache Tomcat tuto vlastnost bohu₧el nemß. To znamenß, ₧e p°i ka₧dΘ zm∞n∞ t°φdy servletu musφme server zastavit a znovu spustit. Pokud na to zapomeneme, opravenß t°φda servletu se do pam∞ti nezavede a pob∞₧φ stßle neopravenß verze. (TotΘ₧ platφ i o zm∞n∞ strßnky JSP.)
Prohlφ₧eΦ
DalÜφ problΘm m∙₧e p°edstavovat webov² prohlφ₧eΦ, p°esn∞ji Internet Explorer nejnov∞jÜφch verzφ. V p°φpad∞, ₧e se nepoda°φ vyhov∞t po₧adavku - nap°. proto, ₧e po₧adovanß strßnka nebyla nalezena, ₧e byla zruÜena, p°esunuta atd. -, obsahuje odezva serveru HTML strßnku s informacemi o vzniklΘm problΘmu. MS IE ovÜem tuto strßnku nahradφ svou vlastnφ (viz obr. 5), kterß je sice p°φjemn∞jÜφ pro nezasv∞cenΘho u₧ivatele, ale pro programßtora, kter² ladφ webovou aplikaci, je naprosto nevhodnß, nebo¥ ne°φkß, co se vlastn∞ stalo.
NaÜt∞stφ lze u IE nastavit standardnφ chovßnφ. V jeho nabφdce Nßstroje vybereme mo₧nost Mo₧nosti sφt∞ Internet..., p°ejdeme na kartu Up°esnit a vyhledßme skupinu Prochßzenφ (je pom∞rn∞ rozsßhlß). Zde zruÜφme zaÜkrtnutφ polo₧ky Zobrazovat jednoduchΘ chybovΘ zprßvy protokolu HTTP (obr. 6). (P°esn² nßzev tΘto polo₧ky se v n∞kter²ch verzφch IE liÜφ.) PotΘ ji₧ bude prohlφ₧eΦ zobrazovat chybovß hlßÜenφ serveru, a to vΦetn∞ hlßÜenφ o neoÜet°en²ch v²jimkßch v servletu nebo JSP.
P°ipome≥me si, ₧e po ·prav∞ HTML strßnky nebo servletu je t°eba zadat p°φkaz Obnovit (p°φp. Aktualizovat - m∙₧e se jmenovat i jinak), kter² zp∙sobφ znovuzavedenφ HTML strßnky do pam∞ti nebo novΘ volßnφ servletu.
HTML
Jin²m problΘmem je sprßvnost vytvo°enΘho HTML dokumentu. Abychom si mohli prohlΘdnout zdrojov² k≤d vytvo°enΘho HTML dokumentu, staΦφ v IE v nabφdce Zobrazit pou₧φt p°φkaz Zdrojov² k≤d. (Podobnou mo₧nost nabφzφ v∞tÜina prohlφ₧eΦ∙.) Vedle toho lze pou₧φt i specißlnφ programy pro ov∞°enφ sprßvnosti HTML dokument∙, tzv. validßtory.
O Φem jsme nehovo°ili
Do Φty°dφlnΘho serißlu se pochopiteln∞ nevejde vÜe, co bychom mohli o programovßnφ pro internet napsat. S v²jimkou aplet∙ jsme zcela pominuli programovßnφ na stran∞ klienta (nap°. skriptovßnφ v HTML strßnkßch pomocφ jazyk∙, jako je JavaScript nebo VBScript); totΘ₧ platφ o pou₧φvßnφ databßzφ v servletech a JSP. (Zßkladnφ informace o JDBC najdete nap°. v dodatku k [1].)
V∙bec jsme se nezmφnili o vytvß°enφ distribuovan²ch aplikacφ zalo₧en²ch na standardu CORBA nebo na RMI. (Zßkladnφ pouΦenφ lze najφt v knize [2].) Nedostalo se ani na p°esm∞rovßnφ po₧adavk∙ na jinΘ servlety nebo JSP strßnky nebo na p°φmou komunikaci servletu a apletu ("tunelovßnφ" HTTP).
Nehovo°ili jsme o vytvß°enφ knihoven u₧ivatelsk²ch znaΦek JSP, o pou₧φvßnφ komponent JavaBeans v JSP strßnkßch a o mnoha dalÜφch tΘmatech.
V p°φpad∞ aplet∙ jsem si dovolil p°edpoklßdat, ₧e je znßte a umφte s nimi zachßzet. Zßkladnφ informace o nich najdete prakticky v ka₧dΘ uΦebnici Javy, dokonce i v mΘ uΦebnici [3] urΦenΘ naprost²m zaΦßteΦnφk∙m. Podrobn∞jÜφ informace na toto tΘma zφskßte nap°. v [2] nebo ve [4].
O CGI skriptech zalo₧en²ch na jazyku C lze najφt informace nap°. v knize [5]. DalÜφ informace o servletech a JSP najdete v on-line dokumentaci [6]. TakΘ v²klad o protokolu HTTP byl velice povrchnφ. Podrobn∞jÜφ informace lze najφt v [7].
Miroslav Virius
Odkazy
[1] M. Hall: Core Servlets and JavaServer Pages. Prentice Hall 2000
[2] B. Eckel: Myslφme v jazyku Java (1. a 2. dφl). Grada Publishing, Praha 2001
[3] M. Virius: Java pro zelenßΦe. Neokortex, Praha 2001
[4] P. Herout: Java - grafickΘ u₧ivatelskΘ prost°edφ a ΦeÜtina. Kopp, ╚eskΘ Bud∞jovice 2001
[5] R. Stones, N. Matthew: Linux - zaΦφnßme programovat. Computer Press 2000