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:

  1. Sa i se spuna browser-ului ca raspunsul va fi HTML si
  2. Sa se modifice instructiunile println astfel incat sa construiasca o pagina Web.

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).