Capitolul precedent v-a aratat cum sa instalati software-ul necesar si cum
sa va configurati mediul de dezvoltare. Acum doriti sa scrieti cu adevarat
cateva servlet-uri. Acest capitol va arata cum, evidentiind structura pe care o
urmeaza aproape toate servlet-urile, conducandu-va prin pasii necesari
compilarii si executarii unui servlet, si dand detalii despre cum sunt
initializate servlet-urile si cand sunt apelate diferitele metode. Totodata prezinta cateva instrumente generale care va
vor fi de ajutor in dezvoltarea servlet-urilor.
2.1 Structura de baza a servlet-urilor
Listarea
2.1 evidentiaza un servlet simplu care utilizeaza cereri GET. Cererile GET,
pentru cei nefamiliarizati cu HTTP, reprezinta tipurile obisnuite de
cereri pentru pagini Web. Un browser genereaza aceasta cerere cand utilizatorul
tasteaza un URL in linia de adresa, urmeaza un link dintr-o pagina Web, sau
trimite un formular HTML care nu specifica un METHOD. Servlet-urile de asemenea pot utiliza
foarte usor cereri POST, care sunt generate cand cineva trimite un formular HTML care specifica METHOD=”POST”. Pentru detalii despre utilizarea
formularelor HTML, vezi Capitolul 16.
Pentru a fi un servlet, o clasa trebuie sa extinda HttpServlet si si as suprascrie doGet sau doPost, depinzand daca datele sunt transmise prin GET sau prin POST. Daca vreti ca acelasi servlet sa utiilzeze
si GET si POST si sa actioneze la fel pentru amandoua, puteti pur si simplu
sa-i comandati lui doGet sa apeleze doPost, sau viceversa.
Listarea 2.1 ServletTemplate.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public
class ServletTemplate extends HttpServlet {
public
void doGet(HttpServletRequest request,
HttpServletResponse
response)
throws
ServletException, IOException {
// Foloseste
"request" pentru a citi anteturile HTTP de intrare
//
(e.g. cookies) si date din formulare HTML (e.g. date introduse
// si
trimise de utilizator).
//
Foloseste "response" pentru a specifica codul si anteturile
// starii
raspunsului HTTP (e.g. tipul continutului, cookies).
PrintWriter
out = response.getWriter();
// Foloseste
"out" pentru a trimite continutul catre browser
}
}
Ambele metode iau doua argumente: un HttpServletRequest si un
HttpServletResponse. HttpServletRequest detine
metode prin care puteti afla despre informatia de intrare cum ar fi datele din
formular, anteturile cererii HTTP si hostname-ul clientului. HttpServletResponse
permite specificarea informatiei de iesire cum ar fi coduri de stare HTTP (200,
404, ets.), anteturile raspunsurilor (Content-Type, Set-Cookie, etc.) si, cel mai important, permite obtinerea unui PrintWriter utilizat la
trimiterea continutului documentului inapoi la client. Pentru servlet-uri
simple, cea mai mare parte a efortului este depus in declaratii println care genereaza
pagina dorita. Datele din formulare, anteturile cererilor HTTP, raspunsurile
HTTP si cookie-urile se vor discuta detaliat in capitolele urmatoare. Din
moment ce doGet si doPost arunca doua exceptii, vi se cere sa le
includeti in declaratie. La final, trebuie sa importati clase in java.io (pentru PrintWriter, etc.), javax.servlet (pentru HttpServlet, etc.), si javax.servlet.http (pentru HttpServletRequest si HttpServlet-Response).
Strict vorbind, HttpServlet nu este singurul punct de
pornire pentru servlet-uri, deoarece esrvlet-urile pot, in principiu, sa
extinda mail, FTP sau alte tipuri de servere. Servlet-urile pentru aceste medii
ar extinde o clasa obisnuita derivata din Generic-Servlet, clasa parinte a lui HttpServlet. In practica, insa,
servlet-urile sunt utilizate aproape exclusiv pentru servere care comunica prin
HTTP (de ex: servere Web si de aplicatii), si discutia din aceasta carte se va
limita la aceasta utilizare.
2.2 Un servlet simplu care genereaza text
Listarea
2.2 afiseaza un servlet simplu care doar genereaza text, avand iesirea afisata
in Figura 2-1. Sectiunea 2.3 (Un servlet care geneeraza
HTML) prezinta cazul mai uzual in care este generat HTML. Cu toate acestea, inainte de a merge mai departe, merita sa petreceti putin
timp trecand prin procesul de instalare, compilare si rulare a acestui servlet
simplu. La prima incercare acest lucru vi se va parea putin cam anost. Aveti
rabdare, procesul fiind acelasi de fiecare data, va veti obisnui repede cu el,
in special daca automatizati partial procesul prin intermediul unui fisier
script cum ar fi cel prezentat in sectiunea urmatoare.
Listarea 2.2 HelloWorld.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
public
void doGet(HttpServletRequest request,
HttpServletResponse
response)
throws
ServletException, IOException {
PrintWriter
out = response.getWriter();
out.println("Hello
World");
}
}
Figura 2–1 Rezultatul Listarii 2.2 (HelloWorld.java).
Compilarea si instalarea servlet-ului
Primul
lucru de care aveti nevoie este sa va asigurati ca serverul dumneavoastra este
configurat corespunzator si ca clasa dumneavoastra CLASSPATH se refera la fisierele JAR care contin clasele de
servlet standard. Consultati Sectiunea 1.5 (Instalare si configurare) pentru o
explicare a acestui proces.
Urmatorul
pas este sa decideti unde sa stocati clasele de servlet. Aceasta locatie difera
de la server la server, asa incat consultati documentatia Web server-ului
dumneavoastra pentru instructiuni definitorii. Cu
toate acestea, exista unele conventii intrucatva comune. Majoritatea serverelor
detin trei locatii diferite pentru clasele de servlet, dupa cum urmeaza:
1.
Un director pentru clase de servlet
modificate frecvent.
Servlet-urile
din acest director sunt automat reincarcate cand fisierul lor de clasa se
modifica, astfel ca ar trebui sa folositi acest director in timpul dezvoltarii.
Spre exemplu, acesta este de obicei install_dir/servlets in Java Web Server de la Sun si WebSphere
de la IBM si install_dir/myserver/servletclasses pentru BEA WebLogic, desi marea parte a
serverelor ii permit administratorului sa specifice o locatie diferita. Nici
Tomcat si nici JSWDK nu suporta reincarcarea automata a servlet-ului. Cu toate
acestea, detin totusi un director similar pentru plasarea servlet-urilor,
trebuie doar sa opriti si sa reporniti mini-serverul de fiecare data cand
modificati un servlet existent. Cu
Tomcat 3.0, plasati servlet-urile in install_dir/webpages/WEB-INF/classes. Cu JSWDK 1.0.1, folositi install_dir/webpages/WEB-INF/servlets.
2. Un director pentru clase de servlet modificate rar.
Servlet-urile plasate in aceasta locatie sunt usor mai eficiente deoarece
serverul nu trebuie sa verifice permanent data modificarii lor. Totusi,
modificarile fisierelor de clasa din acest director necesita repornirea
serverului. Aceasta optiune (sau Optiunea 3 de mai jos) este potrivita pentru
servlet-uri de “productie” lansate pe un site de mare volum. Acest director de
regula este de genul install_dir/classes, acesta fiind denumirea implicita pentru
Tomcat, JSWDK si Java Web Server. Deoarece Tomcat si JSWDK nu suporta
reincarcarea automata a servlet-urilor, acest director lucreaza in acelasi mod
cu cel descris la Optiunea 1, asa ca majoritatea dezvoltatorilor raman fideli optiunii
precedente.
3. Un director pentru servlet-uri modificate rar, in fisiere JAR.
In cadrul optiunii secundare precedente, fisierele de clasa sunt plasate
direct in directorul classes sau in subdirectorii care corespund denumirii
pachetelor. Aici, fisierele de clasa sunt impachetate intr-un fisier JAR, si
acel fisier este apoi plasat in directorul destinat. In Tomcat, JSWDK, Java Web
Server si majoritatea celorlalte servere, directorul este install_dir/lib. Trebuie sa reporniti serverul de fiecare data cand
modificati fisiere in acest director.
Dupa ce ati configurat serverul, setati-va CLASSPATH-ul, iar dupa ce ati plasat servlet-ul in
directorul corespunzator, doar folositi comanda “javac HelloWorld.java” pentru a compila servlet-ul. In medii de productie, totusi, servlet-urile
sunt frecvent plasate in pachete pentru evitarea conflictelor de nume cu
servlet-uri scrise de alti dezvoltatori. Utilizarea
pachetelor implica 2 pasi in plus, acoperiti in Sectiunea 2.4 (Impachetarea
servlet-urilor). De asemenea, se
folosesc in mod obisnuit formulare HTML pe post de fatade pentru servlet-uri
(vezi Capitolul 16). Pentru a le utiliza, va trebui sa stiti unde sa plasati
fisiere HTML obisnuite pentru a le face accesibile serverului. Aceasta locatie
difera de la server la server, dar in JSWDK si Tomcat, plasatin un fisier HTML
in install_dir/webpages/path/file.html si apoi il accesati prin http://localhost/path/file.html (inlocuiti localhost cu hostmane-ul real in cazul rularii la distanta). O pagina JSP poate fi instalata oriunde ar
putea fi si o pagina normala HTML.
Invocarea servlet-ului
Pentru
diferite servere, clasele de servlet pot fi plasate intr-o multitudine de
locatii diferite, si nu exista decat o minima standardizare pentru servere. Pentru
invocarea servlet-urilor, cu toate acestea, exista o conventie comuna: folositi
un URL de forma http://host/servlet/ServletName. Observati ca URL-ul se refera la servlet, singular, chiar daca directorul real
care contine codul servlet-ului se numeste servlets, plural, sau are un nume neinrudit cum ar
fi classes sau lib.
Figura 2-1, afisata anterior in aceasta sectiune, ofera un exemplu cu
serverul Web ruland direct pe PC-ul meu (“localhost” inseamna “masina
curenta”). Marea parte a serverelor de asemenea va permit sa inregistrati nume
pentru servlet-uri, astfel incat unservlet poate fi invocat prin http://host/any-path/any-file. Procesul pentru a
realiza acesta depinde de server, consultati documentatia serverului pentru
detalii.
2.3 Un servlet care genereaza HTML
Majoritatea
servlet-urilor genereaza HTML, nu text ca in exemplul precedent. Pentru a
construi HTML sunt necesari 2 pasi aditionali:
Primul pas
se realizeaza prin setarea antetului de raspuns HTTP Content-Type. In general, anteturile se seteaza prin
metoda setHeader a lui HttpServletResponse, dar setarea tipului continutului este o
sarcina atat de comuna incat exista si o metoda speciala setContentType doar pentru acest scop. Modul HTML este
desemnat cu tipul text/html, astfel incat codul ar arata dupa cum urmeaza:
response.setContentType("text/html");
Desi
servlet-urile creeaza cel mai adesea document de tip HTML, nu este exclus sa
creeze si alte tipuri de document. De exemplu, Capitolul 7.5 (Utilizarea
servlet-urilor pentru a genera imagini GIF) arata cum servlet-urile pot
construi si returna imagini la cerere, specificand tipul de continut image/gif. Alt exemplu, Capitolul 11.2 (Atributul contentType)
arata cum se genereaza si returneaza spreadsheet-uri Excel, folosind tipul de
continut application/vnd.ms-excel. De remarcat faptul ca
anteturile de raspuns trebuie setate inainte de returnarea vreunei parti din
continut prin Print-Writer. Aceasta din cauza ca
un raspuns HTTP este format din linia de stare, unul sau mai multe anteturi, o
linie libera si documentul propriu-zis, in
aceasta ordine. Anteturile pot aparea in orice ordine, iar servlet-urile
pastreaza anteturile in memoriile tampon si le trimit pe toate odata, astfel ca
se poate seta codul de stare (parte a primei linii returnate) chiar si dupa
setarea anteturilor. Dar servlet-urile nu memoreaza neaparat documentul
propriu-zis, din moment ce utilizatorii ar putea dori sa vada rezultate
partiale pentru paginile lungi. In versiunea 2.1 a specificatiilor
servlet-urilor, iesirea PrintWriter nu este pastrata deloc
in memoria tampon, asa ca la prima folosire a lui PrintWriter, este prea tarziu pentru a merge inapoi si a seta
anteturile. In versiunea 2.2, motoarelor de servlet-uri le este permis sa
memoreze partial iesirea, dar dimensiunea memoriei tampon nu este specificata. Se
poate folosi metoda getBufferSize a lui HttpServletResponse pentru a determina dimensiunea, sau setBufferSize pentru a o specifica. In versiunea 2.2 cu permiterea
memoriei tampon, anteturile pot fi setate pana cand memoria tampon se umple si
continutul este trimis catre client. Pentru a verifica
daca a fost trimis sau nu continutul memoriei tampon se poate folosi metoda isCommitted.
Important
Intotdeauna
trebuie setat tipul continutului inainte
de transmiterea documentului propriu-zis.
Al doilea pas in scrierea unui servlet care construieste
un document HTML este modificarea instructiunii println pentru a genera HTML si nu text. Structura unui document HTML este discutata mai detaliat in Capitolul
2.5 (Utilitare simple pentru construirea documentelor HTML). Listarea 2.3 ofera un exemplu de servlet ce are ca
rezultat imaginea din Figura 2-2.
Listarea 2.3 HelloWWW.java
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWWW extends HttpServlet {
public
void doGet (HttpServletRequest request,
HttpServletResponse
response)
throws
ServletException, IOException {
response.setContentType("text/html");
PrintWriter
out = response.getWriter();
String
docType =
"<!DOCTYPE
HTML PUBLIC \"-//W3C//DTD HTML 4.0 " +
"Transitional//EN\">\n";
out.println(docType
+
"<HTML>\n"
+
"<HEAD><TITLE>Hello
WWW</TITLE></HEAD>\n" +
"<BODY>\n"
+
"<H1>Hello
WWW</H1>\n" +
"</BODY></HTML>");
}
}
Figura 2–2 Rezultatul Listarii 2.3 (HelloWWW.java).