Servleturi - un alt fel de aplicatii Java

Primul lucru la care se gândeste cineva când aude despre limbajul Java sunt apleturile - programe client care ruleaza într-un browser Web. Lucrurile însa nu se limiteaza aici. Calitatile acestui limbaj îl fac o solutie demna de luat în consideratie când este vorba despre dezvoltarea de aplicatii client-server pentru Internet, atât pe partea client, cât si - atentie - pe partea server.

Zöldi Árpád

Înca de la aparitia sa, limbajul Java a avut un impact nemaiîntâlnit în lumea calculatoarelor. Principalul motiv al acestui enorm succes este portabilitatea, careia îi datoram si sloganul „ write-once, run-anywhere“. Pe de alta parte, succesul limbajului se datoreaza si posibilitatii ca aplicatii Java sa poata fi incluse în pagini HTML si rulate într-un browser Web de catre oricine are acces la Internet. În Java însa se pot scrie nu doar apleturi care fac animatii într-o pagina web care plac ochilor, ci si aplicatii server complexe.

Avantajele limbajului din punctul de vedere al dezvoltarii de aplicatii server sunt în esenta aceleasi care îl fac o solutie buna si pe partea client, doar proportia lor fiind diferita. Portabilitatea, principalul atu al limbajului, este importanta si î n cazul aplicatiilor server, dar poate ca într-o masura mai mica decât în cazul aplicatiilor client, de genul apleturilor. Pentru un aplet portabilitatea este de o importanta majora, fiind necesar ca acelasi program sa ruleze pe orice calculator de pe I nternet. În cazul aplicatiilor server, daca un program poate rula fara modificari pe UNIX si pe Windows NT, înseamna o dublare a pietei fara a fi necesara schimbarea nici unei linii de cod. Bineînteles ca oricine va alege o solutie portabila fata de una mai putin portabila, iar Java câstiga clar la acest capitol de fiecare data.

Alte motive convingatoare pentru a alege Java pentru scrierea unor aplicatii server, sunt furnizate de proprietatile intrinseci ale limbajului: gestiunea memoriei, conversia sigura de tip ( type-safety), tratarea exceptiilor si programarea pe fire de executie multiple ( multi-threading).

Aplicatiile server trebuie de obicei sa ruleze mai multe zile, poate chiar luni de zile, fara întrerupere, iar aparitia unor probleme cu memoria, poate cauza probleme serioase. În Java, erori de acest tip nu au cum sa apara, programatorul nu trebuie sa se ocupe de gestiunea memoriei, deci problema pur si simplu dispare.

Conversia sigura de tip ( type-safety) si verificarea limitelor tablourilor (bounds checking) în timpul rularii elimina multe erori de accesare gresita (si neautorizata) a memoriei.

La aplicatiile server mai pot apare mici erori ( bugs), în special erorile care apar odata la câteva zile ori saptamâni sunt greu de depistat. În acest caz, tratarea exceptiilor în Java poate fi foarte folositoare, deoarece prinde si jurnalizeaza ( log) exceptia cu o urma în stiva, cu locul unde a aparut ( stack-trace), astfel încât ulterior se poate analiza ce s-a întâmplat.

În ceea ce priveste viteza de executie, Java mai are mult de recuperat. Compilatoarele JIT, o solutie la acest handicap, aduc însa Java în imediata apropiere a lui C++. De asemenea, putem optimiza viteza de executie a programelor Java prin scrierea de me tode native pentru unele operatii costisitoare de timp, dar acest lucru merge în dauna mult laudatei portabilitati. Cei care ezita sa adopte solutia Java din cauza diferentei mari de performante nu trebuie sa îsi faca griji, urmatoarea generatie de inter pretoare va avea performante mult îmbunatatite, un program Java se va executa cam cu aceeasi viteza ca si aplicatiile C/C++.

Din punct de vedere al programarii, modelul de programare pe fire multiple ( multi-threading) bine structurat este parte integranta a limbajului, ceea ce îl face ideal pentru sisteme intens concurente, care este de fapt esenta unei aplicatii server.

Fiind vorba de aplicatii client-server pentru Internet, o prima aplicare a lui Java pe partea server ar putea fi un server HTTP si scrierea aplicatiilor externe care extind functionalitatea unui server Web. În acest caz, problema ar fi modul de realizare a comunicarii dintre serverul HTTP si programele externe Java. Exista deja numeroase servere Web scrise în întregime în Java, pentru acestea comunicarea cu alte programe de extensie scrise în Java nu este o problema.

Scopul acestui articol este de a prezenta Servlet Development Kit (SDK), un chit Java de dezvoltare a aplicatiilor de extensie a serverelor informationale (de exemplu, servere Web), creat de JavaSoft (acum în versiune beta). Chitul include o interfata st andard de programare a servleturilor (Java Servlet API). Pentru început, voi prezenta pe scurt standardele existente de interfatare a aplicatiilor externe cu serverele Web.

Standarde existente

Primul standard de interfata care a aparut a fost CGI (Common Gateway Interface ), dezvoltat de NCSA. Fiind cel mai vechi, este foarte raspândit, astfel ca la ora actuala marea majoritate a prelucrarilor Web sunt facute prin scripturi CGI.

O aplicatie CGI poate fi scrisa în orice limbaj de programare, în general cel mai des sunt folosite limbajele C si Perl. CGI foloseste variabile de mediu ca sa transmita parametrii aplicatiilor externe (de ex. QUERY_STRING, PATH_INFO). Utilizarea CGI are însa câteva dezavantaje. Cea mai importanta dintre ele este performanta scazuta, deoarece pentru fiecare cerere trebuie creat un proces separat, ceea ce duce la întârzieri. Un alt dezavantaj este dependenta de o anumita platforma. Cu toate ca standardul CGI este independent de limbajul de programare, deoarece aplicatiile CGI sunt scrise pentru a rula pe un calculator pe care ruleaza un server HTTP ele vor fi dependente de aceasta platforma, iar ca sa ruleze pe un sistem diferit a plicatiile trebuie modificate. Tot la capitolul deficiente se poate adauga si complexitatea interactiunii dintre doua scripturi CGI care ruleaza pe acelasi server.

Un alt standard, dezvoltat ca o extensie pentru CGI este FastCGI (vezi articolul lui Radu Greab din numarul din ianuarie '97), dezvoltat de OpenMarket. FastCGI foloseste procese persistente pentru a rula aplicatii externe, deci în acest caz nu mai este nevoie sa se creeze un proces separat pentru fiecare cerere receptionata. Dar si în acest caz, comunicatia între serverul Web si aplicatia externa poate cauza scaderea performantelor, din moment ce ele ruleaza ca procese diferite.

Pentru a rezolva problemele de performanta, unii producatori de servere Web au dezvoltat interfete de programare în limbajul C/C++ (de exemplu, Netscape cu NSAPI, Microsoft cu ISAPI). Aceste interfete extind direct serverul Web la un nivel inferior, modulele C rulând în acelasi proces ca si serverul. Dezavantajele acestei abordari sunt dependenta de interfata respectiva si de limbajul de programare, precum si complexitatea si lipsa de securitate. Modulele de extensie rulând în acelasi spatiu de adresare cu serverul, daca apare o eroare în extensia C, atunci e posibil ca tot serverul sa cada. O alternativa la aceste solutii este Java, cu programe servlet.

Ce este un servlet?

Servleturile sunt componente independente de platforma ale aplicatiilor server, care extind dinamic serverele care au suport Java integrat. Ele sunt independente si de protocol, asigurând un cadru general pentru servicii pe baza modelului cerere-raspuns . Acest binecunoscut model este des folosit la programarea sistemelor distribuite, începând cu apeluri de proceduri la distanta si terminând cu protocolul HTTP pentru cereri catre servere Web. Cu ajutorul servleturilor extindem deci functionalitatea unei aplicatii de tip server informational (nu neaparat server HTTP), un prim domeniu de aplicare fiind, bineînteles, extinderea serverelor Web.

Servleturile pot fi considerate echivalentul apleturilor pe partea server, ele fiind asemanatoare din multe puncte de vedere. Însa principala caracteristica a apleturilor, interfata grafica utilizator, lipseste din servleturi, ele neavând nevoie de asa ceva din moment ce ruleaza în interiorul serverelor. În rest, ele se aseamana mult, un servlet fiind si el o componenta de aplicatie, scrisa în Java, care poate fi transferata la un sistem care are nevoie de ea.

Servleturile sunt un hibrid dintre CGI si interfete de programare de nivel inferior ca NSAPI ori ISAPI. Un servlet se comporta ca o aplicatie CGI, dar are o durata de viata lunga si se încarca dinamic (ca si modulele NSAPI/ ISAPI), eliminându-se astfel întârzierile de la pornire specifice CGI-ului. Dupa încarcare, la o noua cerere nu mai este necesar sa fie creat un nou servlet: serverul doar apeleaza o metoda care deserveste cererea, astfel încât e nevoie doar de o schimbare de context usoara ( light-weight) pentru un alt fir de executie.

Deci, în cazul în care avem o aplicatie server HTTP, servleturile sunt o alternativa completa si mai eficienta pentru CGI.

Ce poate face un servlet?

Aceste programe sunt folosite în primul rând pentru a asigura acces prin Web la informatii prezentate ca pagini HTML. Cu ajutorul servleturilor putem vizualiza si modifica interactiv aceste date, folosind tehnici de generare dinamica a paginilor Web. Une le servleturi pot, de exemplu, sa genereze direct text formatat HTML cu ajutorul unor ierarhii de clase create chiar în acest scop. De asemenea, cu aceste programe se pot pre-procesa pagini web înainte de a fi trimise catre clienti, folosind functionalit atea Server Side Include a serverelor Web, utilizata în cazul fisierelor shtml. Un servlet poate însa face mai mult decât sa genereze documente. Dupa ce o conexiune a fost stabilita între client si servlet, clientul – care poate fi un aplet – si servlet ul pot „vorbi“ un protocol oarecare, folosind o noua conexiune. O alta posibilitate ar fi ca serverul sa conecteze mai multe servleturi într-un lant de filtre, fiecare servlet din lant facând o transformare asupra datelor de intrare.

Plecând de la ideea ca servleturile sunt folosite pentru extindere dinamica, le putem folosi si ca niste componente auxiliare de tip plug-in, de exemplu în cazul unui motor de căutare. De asemenea, servleturile pot fi o componenta intermediara a unei aplicatii distribuite, putând fi la rândul lor clienti ai unor alte servicii scrise în orice alt limbaj. Putem construi deci cu ajutorul servleturilor aplicatii client/server baza te pe modelul pe trei nivele (three-tier architecture). Primul nivel poate fi un applet, servletul fiind componenta de la mijloc ( middle-tier), iar componenta a treia o baza de date. În acest caz servletul, folosind interfata JDBC ( Java DataBase Connectivity), acceseaza o baza de date relationala.

Disponibilitate

Interfata de programare Java Servlet API dezvoltata de JavaSoft nu face parte din nucleul de programare Java, fiind un API standard de extensie Java. Este deci disponibila ca un pachet aditional pentru nucleul Java.

Pentru ca un servlet sa poata rula pe un server Web e nevoie ca serverul sa aiba integrata o masina virtuala Java (JVM – Java Virtual Machine), sa dispuna de o interfata de comunicare cu servleturi si sa gestioneze servleturile aflate în executie. Multe companii producatoare de servere Web au anuntat ca vor include curând un JVM în serverele lor. De asemenea, JavaSoft a furnizat un pachet pe ntru a îngloba suport pentru servleturi în alte servere Web, inclusiv Apache si IIS de la Microsoft. Serverele Web de la Netscape dispun deja de suport pentru servleturi.

Merita mentionat ca servleturile au fost initial suportate de Java Web Server (fostul Jeeves) de la JavaSoft si de atunci multe servere bazate pe Java au integrat API-ul servlet. Anumite componente de baza din Java Web Server sunt chiar servleturi. Compo nenta serverului care se ocupa cu invocarea servleturilor este si ea un servlet ( Invoker Servlet). La fel, componenta care se ocupa cu deservirea cererilor HTTP si returnarea documentelor este tot un servlet, care implementeaza si un cache pentru paginile mai des accesate ( File Servlet). Documentele .shtml sunt prelucrate de servletul SSInclude Servlet . De lucrul cu programe externe bazate pe interfata CGI se ocupa un alt servlet (CGI Servlet). În fine, chiar administrarea serverului web este sarcina unui servlet (Admin Servlet).

API-ul java.servlet

Servleturile sunt bazate pe modelul de programare cerere-raspuns (acceptare de cereri si generare de raspunsuri). Ca sa poata receptiona cereri si sa raspunda la ele, orice servlet este un obiect Java care se conformeaza unei interfete speciale. Adica, î n termenii programarii Java, implementeaza interfata Servlet. Acest lucru se poate face direct, prin implementarea tuturor metodelor interfetei, sau indirect, prin mostenire, fie de la o clasa servlet generica ( GenericServlet), fie de la clasa specifica servleturilor bazate pe protocolul HTTP ( HttpServlet, care de fapt si ea extinde clasa generica). A doua solutie este mai des utilizata de proiectanti, deoarece în cele doua clase sunt deja implementate metodele interfetei, programatorul suprascrie ( override) doar metodele de care are nevoie.

În interfata Servlet, cea mai importanta metoda este service (ServletRequest req, ServletResponse res). Aceasta metoda este apelata la fiecare cerere receptionata. Cel mai simplu servlet posibil defineste doar aceasta metoda service, care are ca parametrii doua obiecte, instante a claselor ServletRequest si respectiv ServletResponse. Primul parametru încapsuleaza datele trimise de client, fiind astfel posibil accesul servletului la parametrii cererii. Unui servlet îi putem trimite parametrii în multe feluri:

Toti acesti parametrii pot fi preluati prin intermediul unui obiect ServletRequest.

Al doilea parametru ne permite trimiterea raspunsului înapoi la client printr-un OutputStream. Prin acest stream e posibil transferul datelor în formatul dorit: servletul poate specifica ce tip de date ( MIME-type) trimite apelând res.setContentType (mimeContentType).

Servleturile fiind obiecte Java, care sunt de fapt aplicatii independente rulând în interiorul serverelor, au date specifice instantelor. La initializare ele au acces la date de configurare specifice servletului respectiv.

Un alt aspect al servleturilor care le aseamana cu apleturile este modul de comunicare cu mediul în care ruleaza. Un aplet realizeaza acest lucru prin intermediul metodei getAppletContext, care returneaza un obiect ApletContext prin care apletul poate interactiona cu mediul în care ruleaza, adica cu browserul. La rândul lui, un servlet foloseste (ati ghicit!) getServletContext care îi returneaza o instanta a clasei ServletContext , prin intermediul careia servletul poate afla informatii despre mediul lui de rulare, care de data aceasta este serverul.

Un servlet este de obicei încarcat dinamic în memorie la prima cerere care-i este destinata, dar serverul poate fi configurat astfel încât sa încarce anumite servleturi la pornire. Încarcarea se face prin tehnici normale de încarcare a claselor Java, pri n intermediul unui ClassLoader, acest lucru având avantajul ca servleturile pot fi încarcate la fel de usor dintr-un director securizat ( trusted) aflat undeva pe retea – de exemplu http://server-departament/servlets – ca si din sistemul de fisiere local. Acest lucru asigura o flexibilitate sporita în arhitectura sistemului si o distribuire mai usoara a serviciilor în retea. Bineînteles, aici ap ar anumite probleme de securitate care vor fi discutate ceva mai încolo.

Dupa ce un servlet a fost încarcat în memorie, în timpul existentei sale trece prin anumite faze. În primul rând trebuie activat de catre server ca sa fie capabil sa raspunda la cereri. Acest lucru se realizeaza printr-un apel la metoda init. Proiectant ii de servleturi suprascriu (overriding) aceasta metoda pentru ca anumite calcule, initializari sau configurari costisitoare ca timp de executie (de exemplu, operatii de I/O) sa se faca doar o singura data si nu la fiecare cerere. Asemenea initializari ar putea fi de pilda, accesul la datel e persistente proprii prin conectare la o baza de date sau prin citire dintr-un fisier. Dupa initializari, servletul odata activat poate prelucra multe cereri. Fiecare cerere client genereaza un apel al metodei service a servletului. Desigur, aceste apel uri pot fi concurente, ceea ce permite servleturilor sa coordoneze anumite activitati între clienti diferiti si sa partajeze date între mai multi clienti. Cererile sunt acceptate si prelucrate pâna când servletul este explicit oprit de catre server, prin tr-un apel la metoda destroy. Urmatoarea faza este curatenia: într-un moment când procesorul este liber apare „gunoierul“ ( Garbage Collector) care elibereaza memoria ocupata de servlet.

Securitate

Asa cum am amintit mai devreme, deoarece încarcarea în memorie a servleturilor se face prin mecanismul standard Java (folosit în orice alta masina virtuala Java), care permite si încarcarea claselor Java din retea, apar anumite probleme de securitate. Ac este probleme se refera în primul rând la servleturile aduse din retea, de pe alte servere. În API-ul servlet exista suport integrat pentru securitate. Acest lucru se datoreaza de fapt mediului Java standard care are un SecurityManager care poate cont rola accesul la toate resursele, cum ar fi fisiere locale, alte fire care ruleaza pe acelasi server, informatii administrative a serverului (utilizatori, grupuri) sau accesul la alte servere din retea. Prin acest mecanism se poate asigura un mediu de e xecutie controlat (SandBox) pentru servleturi, similar celui folosit de navigatoarele Web pentru a controla apleturile. Administratorul serverului poate specifica deci, prin intermediul SecurityManager-ului, carui servlet sa i se acorde drepturi de accesare a retelei sau a fis ierelor locale. Daca luam în considerare recent aparuta posibilitate de a semna digital fisiere Java ARchive (JAR), care contin clase Java arhivate, am putea considera urmatoarea politica de securitate:

  1. Din moment ce sunt instalate local de catre administratorii serverului, servleturile locale au acces deplin la toate resursele.
  2. Toate servleturile din retea se executa în interiorul sandbox-ului. Servleturile care sunt semnate digital si se afla pe o lista de semnaturi în care administratorul are încredere, au acces deplin la toate resursele. Servleturile semnate, dar care nu sunt pe lista, sunt considerate ca servleturi fara semnatura.
  3. Servleturile care nu sunt semnate digital se executa în sandbox si nu au acces la nici o resursa.

Bineînteles, aceasta solutie poate fi extinsa, putând fi adoptata o politica mai flexibila. De exemplu, pentru servleturi cu o anumita semnatura putem permite accesul doar la retea sau doar la anumite fisiere.

Un alt aspect al securitatii se refera la informatiile disponibile despre clientul care a creat cererea. Servleturile au acces la informatii despre clientii lor prin intermediul cererii receptionate: pot afla adresa IP si numele computerului gazda ( host) de unde a venit cererea, precum si tipul protocolului cererii respective. Daca se foloseste un protocol de comunicatie sigur – de exemplu SSL ( Secure Sockets Layer) – se poate face o identificare sigura a clientului. De asemenea, servleturile care se bazeaza pe protocolul HTTP au acces la date de autentificare specifice protocolului.

Moduri de invocare a servleturilor

Vom vedea în continuare cum putem trimite o cerere catre un servlet. Servleturile, ca si apleturile de altfel, pot fi identificate printr -un URL. Servleturile locale le putem identifica doar prin numele clasei respective. Un fapt important este ca se pot specifica nume virtuale si date specifice pentru un servlet la încarcare. Acest lucru este folositor atunci când dorim ca instante multip le ale aceluiasi servlet sa ruleze pe acelasi server, fiind posibila si o comunicare între aceste servleturi.

Dupa încarcare si initializare putem invoca direct servletul, printr-un URL, în stil CGI:

http://server_host/servlets/<nume_servlet>?argumente

De asemenea, clientii pot invoca indirect un servlet, cerând un document html generat dinamic de catre servlet, serverul facând maparile pentru servletul respectiv. Aceste mapari se pot face în multe feluri, dintre care voi prezenta doar câteva:

O solutie ar fi ca administratorul serverului sa specifice într-un fel (de exemplu printr -un fisier mapping.rules) ca un anumit tip de cerere se mapeaza de fiecare data la un servlet particular. Un exemplu ar putea fi un servlet care acceseaza o baza de date.

O alta solutie ar putea fi ca o parte a cererii client sa fie numele servletului, aflat într-un director servlets. În plus, acest director ar putea fi partajat între mai multe servere între care este distribuita procesarea cererilor venite de la clienti i site-ului respectiv.

Serverele ar putea fi configurate în asa fel încât sa apeleze automat anumite servleturi pentru a filtra informatiile de iesire ale altor servleturi. De exemplu, daca apare un anumit tip de date de iesire, se apeleaza automat un servlet care face post-pr ocesarea datelor, de pilda o conversie de format.

Anumiti clienti care au trecut de o faza de autentificare pot specifica exact numele servletului care urmeaza a fi apelat.

Unele servere Web, care au suport complet pentru servleturi, pot asigura si functionalitatea SSI ( Server Side Include). Aceste servere pot apela servleturi pentru a pre-procesa pagini Web înainte ca acestea sa fie trimise clientilor. Acest lucru se realizeaza printr-o sintaxa HTML speciala, si anume cu ajutorul tag-ului SERVLET. Fisierele care contin acest tag sunt fi siere cu extensia .shtml, iar sintaxa tag-ului este urmatoarea:

<SERVLET NAME=NumeServlet CODE=NumeClasaServlet.class
CODEBASE=LocatieServleturi
initparam1=initvalue1 initparam2=initvalue2 ...>
<PARAM NAME=param1 VALUE=valoare1>
<PARAM NAME=param2 VALUE=valoare2>
.
.
.

Text care este afisat daca serverul nu cunoaste servleturi

</SERVLET> 

Serverul încearca prima data sa apeleze servletul prin câmpul NAME. Daca acesta nu este prezent, încearca sa încarce servletul pe baza urmatoarelor doua câmpuri, iar câmpurile ramase din tag sunt parametrii de initializare. Tag-urile PARAM contin parame trii cererii. Servletul apelat va genera o parte a unei pagini web, rezultatele servletului vor fi puse în locul unde a fost situat în document tag-ul SERVLET.

Un exemplu

În listingul alaturat este sursa unui servlet care acceseaza o baza de date relationala. Servletul este un contor care numara de câte ori este accesata o pagina Web. Se foloseste interfata JDBC pentru a accesa o baza de date MiniSQL în care sunt stocate datele. În baza de date avem un tabel tabel_contor care contine doua câmpuri: pagina_WWW si nr_accesari. Servletul este accesat prin intermediul tag-ului SERVLET din fisere shtml si are un singur parametru: URL-ul paginii respective.

Servletul are trei metode mai importante. La prima cerere, când servletul este încarcat, serverul apeleaza metoda init. Aceasta metoda acceseaza resursele necesare prelucrarii cererilor, adica se creeaza o conexiune la baza de date. Ca sa poata sa faca a cest lucru, se impune crearea unei referinte la un driver de baze de date folosit la comunicatia cu baza de date mSQL.

Metoda care este apelata la fiecare cerere, service, se foloseste de conexiunea la baza de date pentru a accesa datele prin intermediul cererilor SQL. Aceasta metoda preia un singur parametru, numele paginii Web, din obiectul ServletRequest, cu ajutorul metodei getParameter. În continuare, se trimite o cerere SELECT catre baza de date, pentru a se cauta linia din tabelul tabel_contor care contine datele pentru pagina respectiva. Daca nu s-a gasit linia respectiva înseamna ca pagina este accesata prima data, si inseram în t abel noul URL si valoarea 1. Daca o linie a fost gasita, se face o incrementare si apoi un UPDATE în baza de date. La sfârsit se scrie rezultatul în stream-ul de iesire, pe care îl accesam prin intermediul obiectului ServletResponse.

Metoda destroy închide conexiunea la baza de date. În toate cele trei metode se foloseste metoda log, care scrie în fisierul jurnal modul cum s-au terminat operatiile, pentru o eventuala analiza ulterioara. Metoda getServletInfo este echivalentul metodei getAppletInfo din apleturi si returneaza informatii despre servlet.

Exemplul prezentat demonstreaza usurinta cu care putem accesa o baza de date. Bineînteles, se pot crea aplicatii care acceseaza o baza de date ce contine structuri de date mai complexe, care pot fi prezentate utilizatorului în pagini web având o forma in tuitiva. Este posibil chiar ca utilizatorul sa poata crea cereri catre o baza de date.

Concluzie

Chiar daca versiunea finala a chitului Java SDK înca nu a aparut, schimbari majore în API-ul servlet nu sunt de asteptat. Cum limbajul Java primeste tot mai mult suport din partea tuturor producatorilor de soft, este o solutie demna de luat în considerar e. Ramâne însa de vazut în ce masura se va impune si va reusi sa mai contrabalanseze dominatia CGI -ului.

Zöldi Árpád este student la Universitatea „Petru Maior“ din Tg.Mures si poate fi contactat la adresa: azoldi@uttgm.ro

Aplicatie servlet

import java.servlet.*;
public class CounterServlet extends GenericServlet {
static java.sql.Connection conexiunea;
public void init() throws ServletException {
String driver, dataBase, user, pass;
log("init");
if( (driver = getInitParameter("driver")) == null ) 
driver = "imaginary.sql.iMsqlDriver";
if( (dataBase = getInitParameter("db")) == null ) 
dataBase = "jdbc:msql://felix.uttgm.ro:4333/test_db";
if( (user = getInitParameter("user"))== null )
user = "azoldi";
if( (pass = getInitParameter("password"))== null )
pass = "";
try {
Class.forName(driver);
conexiunea = java.sql.DriverManager.getConnection( dataBase,user,pass);
log(" Connection to "+dataBase+" created.");
}
catch( java.sql.SQLException e ) {
e.printStackTrace();
log("Failed to connect to "+dataBase+".");
throw new ServletException("Can't open database");
}
catch( ClassNotFoundException e ) {
e.printStackTrace();
log("Unable to load database driver: "+driver+".");
}
}

 

public void destroy() {
log("destroy");
try {
conexiunea.close();
log("Connection to database closed.");
} catch( java.sql.SQLException e ) {
e.printStackTrace();
log("Failed to close database.");
}
}

 

public String getServletInfo() {
return "Page Counter Servlet";
} 

Aplicatie serviciu

public void service( ServletRequest req, ServletResponse res ) 
throws ServletException, java.io.IOException {
int contor = 0;
String page;
if( (page = req.getParameter("page")) == null ) {
log("Wrong servlet call, parameter \"page\" not present.");
throw new ServletException("Wrong servlet call");
}
try {
java.sql.Statement statement = conexiunea.createStatement();
java.sql.ResultSet result_set;
String sqlQuery = null; 
result_set = statement.executeQuery("SELECT nr_accesari FROM tabel_contor " +
"WHERE pagina_WWW = '" + page + "'");
if( result_set.next() ) 
contor = result_set.getInt(1);
else contor = 0;
statement.close();
statement = conexiunea.createStatement();
if( ++contor == 1 ) {
sqlQuery = "INSERT INTO tabel_contor " +
"(pagina_WWW, nr_accesari) " +
"VALUES ('" + page + "', " +contor+ ")";
}
else {
sqlQuery = "UPDATE tabel_contor " +
"SET nr_accesari = " + contor + " " +
"WHERE pagina_WWW= '" + page + "'";
}
statement.executeUpdate(sqlQuery);
statement.close();
}
catch( java.sql.SQLException e ) {
e.printStackTrace();
}
java.io.PrintStream out = new java.io.PrintStream( res.getOutputStream() );
out.println(contor);
out.close();
}
}

(C) Copyright Computer Press Agora