Sunteți pe pagina 1din 33

Laborator 1

ANT este un instrument pentru compilarea de proiecte Java. In principiu este


asemanator cu utilitarele de tip make (gnumake, nmake, jam) existente in
sistemele Linux. ANT-ul a fost creat in scopul eliminarii neajunsurilor utilitarelor
mentionate in cazul compilarii proiectelor mari pe platforme diverse. In cadrul
utilitarelor de tip make se folosesc utilitare ale sistemului de operare. In cazul in
care vrem sa compilam acelasi proiect pe o platforma diferita, trebuie sa ne
asiguram ca utilitarele folosite exista pe respectiva platforma.

ANT-ul abordeaza problema intr-un mod diferit. In loc sa apeleze direct utilitare
ale sistemului de operare, el apeleaza obiecte Java cu diverse functionalitati.
Descrierea operatiunilor este realizata intr-un fisier XML. Aici este implementat
arborele de sarcini pe care ANT trebuie sa-l execute. Fiecarei sarcini ii corespunde
un obiect Java predefinit. Fisierul XML creat care contine toata logica de compilare
a proiectului poate fi apelat pe orice platforma care suporta o masina virtuala
Java.

Utilizare

Fisierele ANT sunt scrise folosind meta-limbajul XML. Numele standard al fisierului
XML este build.xml. Fiecare fisier descrie un singur proiect si contine cel putin
un target. Un target contine unul sau mai multe task-uri. Task-ul este o
secventa de cod care se executa.

<project>

Cuvantul cheie <project> semnifica inceputul descrierii pasilor de construire a


unui proiect. Acesta apare o singura data in cadrul unui fisier XML.

A1. ATRIBUTELE <project>

<target>

In cadru cuvantului cheie <project> se pot defini unul sau mai multe target-uri.
Un target este o colectie de unul sau mai multe task-uri prin intermediul carora se
construieste proiectul. La apelarea ANT-ului, se poate specifica care din target-
urile definite in build.xml va fi executat. Daca nu este specificat nici un target,
atunci, in mod automat, va fi executat targetul definit de atributele cuvantului
cheie <project> [vezi A1].

Target-urile pot fi organizate astfel incat executia unuia sa depinda de finalizarea


executiei altora. De exemplu putem avea un target pentru compilarea fisierelor
java, unul pentru copierea fisierelor compilate .class intr-un anumit director, altul
pentru crearea unei arhive si in final un target pentru publicarea si inregistrarea
proiectului cu un server specific. Dependenta dintre target-uri este clara: nu pot fi
copiate fisierele .class decat dupa terminarea operatiei de compilare etc.

ANT-ul executa target-urile in functie ce este specificat in cadrul


atributului depends. Evaluarea target-urile se realizeaza de la stanga la dreapta.
Fiecare target este executat o singura data pe parcursul construirii unui proiect,
chiar daca de acesta depinde mai multe target-uri. In cazul dependintelor
multiple, pot apare situatii de forma celei ce urmeaza :
Fie urmatorul exemplu:

<target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="C,B,A"/>

Presupunem ca vrem sa apelam direct target-ul D. Executia acestuia depinde de


finalizarea executiei target-urilor C, B, A in conformitate cu atributul depends.
Daca presupunem ca ordinea de executie a target-urilor este C->B->A->D facem
o eroare. Ordinea de executie este de fapt A->B->C->D din cauza ca target-ul B
depinde de A iar C depinde de B.

B1. ATRIBUTELE <target>

<task>

Cuvantul cheie <task> defineste o secventa de cod care va fi executata. In cadrul


unui task se pot defini unul sau mai multe atribute. In cadrul atributelor pot fi
apelate proprietati definite prin intermediul task-ului property. Sintaxa unui task
este urmatoarea:

<name attr1="value1" attr2="value2" ... />

unde name : numele taskului; attr : numele atributului; value : valoarea


atributului

ANT-ul se instaleaza implicit cu un pachet consistent de astfel de task-uri. ANT-ul


este proiectat de asa maniera incat permite extinderea cu task-uri create de terte
firme, evident existand posibilitatea adaugarii de task-uri create de noi. Scopul
acestui laborator este de familiarizare cu conceptele de baza ale ANT-ului pentru
utilizarea imediata a acestuia, astfel ca doar anumite task-uri vor fi prezentatate.

<property>

Un proiect poate avea una sau mai multe proprietati. O proprietate este o pereche
nume - valoare. De exemplu putem defini directorul sursa pentru fisierele de
imagini ca o proprietate in felul urmator:

<property name="sursa_img" value="images"/>

Proprietatile pot fi folosite in interiorul atributelor task-urilor prin plasarea numelui


(name) proprietatii intre "${" si "}". De exemplu pentru crearea unui director in
care vor fi depuse documentele compilate .class, definim o proprietate si o folosim
in cadrul taskului mkdir:

<property name="dest_class" value="build"/>


....
<mkdir dir="${dest_class}/clase"/>

ANT-ul dispune de un set de proprietati predefinite.

C1. Proprietati predefinite

In urmatorul exemplu este prezentat un proiect care creaza o structura de


directoare, compileaza si impacheteaza fisierele in scopul distribuirii. Este un fisier
text cu numele build.xml si este apelabil de la un terminal astfel: ant . Pentru a
sterge proiectul putem apela: ant clean

Cititi cu atentie exemplul

1:<!-- definim proiectul PrimulProiect avand ca target implicit


dist -->
2:<project name="PrimulProiect" default="dist" basedir=".">
3:
4: <!-- proprietatile globale ale proiectului -->
5: <property name="src" value="."/>
6: <property name="build" value="build"/>
7: <property name="dist" value="dist"/>
8:
9: <!-- targetul initial -->
10: <target name="init">
11: <!-- creaza directorul build folosit in procesul de
compilare -->
12: <mkdir dir="${build}"/>
13: </target>
14:
15: <!-- targetul de compilare : depinde de targetul initial -->
16: <target name="compile" depends="init">
17: <!-- Task de compilare a fisierelor din ${src} in ${build} -
->
18: <javac srcdir="${src}" destdir="${build}"/>
19: </target>
20:
21: <!-- targetul pentru crearea jar-urilor in scopul distributie
proiectului -->
22: <!-- depinde de targetul compile -->
23: <target name="dist" depends="compile">
24: <!-- creaza directorul in care vor fi jar-urile -->
25: <mkdir dir="${dist}/lib"/>
26:
27: <!-- toate fisierele din ${build} sunt impachetate in jar-ul
PrimulProiect.jar -->
28: <jar jarfile="${dist}/lib/PrimulProiect.jar"
basedir="${build}"/>
29: </target>
30:
31: <!-- target apelabil separat pentru stergerea proiectului -->
32: <target name="clean">
33: <!-- Task specializat in stergerea de directoare -->
34: <delete dir="${build}"/>
35: <delete dir="${dist}"/>
36: </target>
37:</project>
Pentru a se putea compila un proiect, de cele mai multe ori avem nevoie de
diferite biblioteci java .jar. ANT-ul pune la dispozitie task-ul specializat
<classpath> pentru a include in procesul de compilare anumite biblioteci
specializate. Sintaxa este urmatoarea:

1: <classpath>
2: <pathelement path="${classpath}"/>
3: <pathelement location="lib/helper.jar"/>
4: </classpath>

Atributul path al cuvantului cheie <pathelement> contine o insiruire de directoare


separate prin ':' sau ';'. Atributul location contine o referinta catre un singur
fisier .jar sau un singur director.

O alta facilitate importanta oferita de ANT este posibilitatea lucrului cu seturi de


fisiere. Setul de fisiere este construit conform definitiei date de cuvantul cheie
<paternset>.

D1. Simboluri utilizate pentru a crea sabloane


D2. <paternset>
D3. <fileset>

Restul facilitatilor oferite de ANT nu sunt importante pentru laborator si sunt


lasate pentru studiu individual.

B TOMCAT este un server de servleturi Java in general si server HTTP in particular.


Versiunea 4 a acestuia implementeaza specificatiile Servlet 2.3 si JavaServer
Pages 1.2 ale Sun, si dispune de o serie intreaga de facilitati care il fac perfect
pentru dezvoltarea de aplicatii web.

O aplicatie web contine atat componente statice cat si componente dinamice.


Componentele statice sunt reprezentate de fisiere HTML, multimedia etc, iar cele
dinamice de servleturi, JSP, EJB etc. Serverul TOMCAT recomanda o modalitate de
organizare a acestui continut, astfel ca atat sursele cat si executabilele sa poata fi
manevrate cu usurinta. Continutul executabil, poate fi servit de TOMCAT direct din
structura de directoare, sau poate fi impachetat intr-o arhiva web, fisier unic cu
extensia .war, ce va contine o imagine a structurii de directoare cu continut
executabil. Prin continut sursa definim structura de directoare care contine sursele
aplicatiei web pe care programatorul le modifica in mod direct, iar prin continut
executabil , structura de directoare, rezultata in urma apelarii utilitarului ANT,
care contine fisierele ce vor fi servite de TOMCAT potentialilor clienti.

Avantajul arhivelor .war este evident: o aplicatie web extrem de complexa poate
fi livrata clientului sub forma unui singur fisier. Acesta, printr-o simpla operatie de
copiere in directorul de aplicatii al TOMCAT, activeaza aplicatia web. Spre
exemplu, serverul EXIST, de baze de date native XML, este livrat ca un fisier Web
Archive, acesta incepand sa functioneze imediat ce este copiat in cadrul TOMCAT.
In figura de mai sus se remarca separarea clara a arhitecturii de directoare a
continutului sursa de arhitectura de directoare a continutului executabil. Practic,
modalitatea de organizare a continutului sursa nu intereseaza, deoarece serverul
nu lucreaza cu acesta. Conform recomadarii TOMCAT, pentru a putea obtine
arhive .war coerente cu specificatia, arhitectura de directoare a continutului
executabil trebuie sa indeplineasca urmatoarele:

 .html, .jpg, .gif, .jsp, etc - Fisierele de acest tip impreuna cu


celelalte fisiere care trebuie sa fie accesibile clientului se regasesc in
directorul parinte al aplicatiei si pot fi organizate in directoare si
subdirectoare in functie de preferinte
 /WEB-INF/web.xml - Fiserul xml reprezinta descriptorul
aplicatiei si trebuie sa fie accesibil conform ierarhiei specificate. In
cadrul acestui fisier sunt specificate componentele care sunt
accesibile de client, parametri de initializare, modelul de securitate
al aplicatiei etc.
 /WEB-INF/classes - Acest director contine atat servleturile cat
si clasele Java normale ale aplicatiei care nu sunt impachetate intr-o
arhiva .jar. De exemplu o clasa defina in cadrul unui pachet sub
forma com.companie.packet.Aplicatietrebuie sa se regaseasca in
urmatoarea structura de directoare:
/WEB-
INF/classes/com/companie/packet/Aplicatie.class
 /WEB-INF/lib - Acest director contine bibliotecile .jar pe care
aplicatia le foloseste.

In momentul instalarii aplicatiei web in cadrul serverului TOMCAT, acesta pune la


dispozitia intregii aplicatii toate fisierele .class sau .jar gasite in directoarele
/WEB_INF/classes si /WEB-INF/lib. Astfel, atunci cand avem nevoie de anumite
clase, nu mai trebuie setati nici un fel de parametri in CLASSPATH.

In continuare este prezentata pas cu pas crearea unei aplicatii web si instalarea
acesteia in TOMCAT. Aplicatia este un convertor valutar simplu.

Pasul 1

Creati urmatoarea structura de directoare: /LTAP/lab1/conv

In directorul /conv creati subdirectoarele /src si /web. In directorul /src creati


subdirectorul /converterApp in care creati fisierul java ConverterBean.java
(continut aici). In directorul /web creati fisierul index.jsp (continut aici) si
directorul /WEB-INF care va contine fisierul web.xml (continut aici).

In final trebuie sa existe urmatoarea structura de directoare si fisiere:


 /conv
o /src
 /converterApp
 ConverterBean.java
o /web
 /WEB-INF
 web.xml
 index.jsp
o build.xml

Se remarca ca despre fisierul build.xml nu am spus nimic. Acesta va fi construit la


pasul 2.

Pasul 2

Creati fisierul build.xml in directorul /conv. In continuare facem urmatoarele


conventii:

 ...!!!cerinta!!!... - atentie la continutul cerintei


 <!-- [x] explicatii --> - zona se inlocuieste cu cea de la sectiunea
respectiva

<project name="Conv" default="build" basedir=".">

<!-- [1] Definim proprietatile proiectului -->

<!-- [2] Configuram task-urile ANT -->

<!-- [3] Definim target-urile de pregatire a contextului -->

<!-- [4] Definim target-urile de executie a proiectului -->

</project>

<!-- [1] Definim proprietatile proiectului -->


<property name="example" value="Conv" />
<property name="path" value="/mst...!!!numele
contului!!!.../${example}"/>
<property name="build" value="/...!!!cale
directa!!!.../deploy" />
<property name="username" value="...!!!nume
utilizator!!!..."/>
<property name="password" value="...!!!parola!!!..."/>
<property name="url"
value="http://atlas.stud.ugal.ro:8080/manager"/>

<!-- [2] Configuram task-urile ANT -->


<!-- Calea catre bibliotecile folosite de ANT in procesul
de compilare-->
<path id="classpath">
<fileset dir="${jwsdp.home}/common/lib">
<include name="*.jar"/>
</fileset>
</path>
<!-- Definim task-urile ANT specializate in lucrul cu
aplicatiile web -->
<taskdef name="install"
classname="org.apache.catalina.ant.InstallTask"/>
<taskdef name="reload"
classname="org.apache.catalina.ant.ReloadTask"/>
<taskdef name="remove"
classname="org.apache.catalina.ant.RemoveTask"/>

<!-- [3] Definim target-urile de pregatire a contextului -->


<!-- Fixam timestamp-ul aplicatiei -->
<target name="init">
<tstamp/>
</target>
<!-- Cream structura de directoare pentru aplicatie -->
<target name="prepare" depends="init" description="Create
build directories.">
<mkdir dir="${build}" />
<mkdir dir="${build}/WEB-INF" />
<mkdir dir="${build}/WEB-INF/classes" />
</target>

<!-- [4] Definim target-urile de executie a proiectului -->


<!-- Target de instalare : apeleaza Managerul TOMCAT -->
<target name="install" description="Install web
application" depends="build">
<install url="${url}" username="${username}"
password="${password}"
path="${path}" war="file:${build}"/>
</target>

<!-- Target de reincarcare : apeleaza Managerul TOMCAT -->


<target name="reload" description="Reload web application"
depends="build">
<reload url="${url}" username="${username}"
password="${password}"
path="${path}"/>
</target>

<!-- Target de stergere : apeleaza Managerul TOMCAT -->


<target name="remove" description="Remove web application">
<remove url="${url}" username="${username}"
password="${password}" path="${path}"/>
</target>

<!-- Compileaza fisierele java si copiaza restul in


directorul ${build} -->
<target name="build" depends="prepare"
description="Compile app Java files and copy HTML and
JSP pages" >
<javac srcdir="src" destdir="${build}/WEB-INF/classes">
<include name="**/*.java" />
<classpath refid="classpath"/>
</javac>
<copy todir="${build}/WEB-INF">
<fileset dir="web/WEB-INF" >
<include name="web.xml" />
</fileset>
</copy>
<copy todir="${build}">
<fileset dir="web">
<include name="*.html" />
<include name="*.jsp" />
<include name="*.gif" />
</fileset>
</copy>
</target>

Pasul 3

In acest moment aplicatia noastra este gata. Urmeaza apelarea utilitarului ANT
pentru construirea efectiva a proiectului si testarea intr-un browser web a
functionalitatii acesteia.

Intr-un terminal schimbati directorul curent in /conv si dati comanda : ant install

Pentru a verifica daca aplicatia a fost instalata cu succes in TOMCAT, vom apela la
un utilitar al acestuia, numit MANAGER. In browserul Mozzila introducem
urmatoarea adresa URL : http://atlas.stud.ugal.ro:8080/manager/list. In lista
afisata trebuie sa regasim si aplicatia noastra cu specificatia running .

Laborator 2
Tehnologia Java ofera posibilitatea realizarii a trei categorii mari de aplicatii:
A o aplicatii stand-alone - ruleaza independent
o appleturi - ruleaza in browser-ul clientului
o servleturi - ruleaza pe server

Tehnologia servlet-urilor permite dezvoltarea de aplicatii care ruleaza pe servere


cu capabilitati Java. Un exemplu de astfel de aplicatie : un servlet, sau mai multe,
care permite prelucrarea formularelor completate de clienti. Avantajul major al
servlet-urilor este faptul ca acestea au acces la intregul API Java, oferind
posibilitatea de a dezvolta aplicatii oricat de complexe.

Pachetul javax.servlet ofera interfetele si clasele necesare dezvoltarii de servlet-


uri. Atentie : pachetul vjavax.serlet nu se regaseste in documentatia standard
Java. Acesta poate fi obtinut de la http://java.sun.comfacand download la
pachetul Java Web Services.

A1. API-ul javax.servlet

Prezentare generala

Abstractia centrala a pachetului javax.servlet este interfata Sevlet. Orice servlet


creat de programator implementeaza direct sau indirect aceasta interfata. In mod
obisnuit, servleturile extind clasa HttpServlet. Ierarhia este prezentata in figura
urmatoare:

Atunci cand un servlet accepta o cerere de la un client, acesta creeaza doua


obiecte:

o ServletRequest - contine datele transmise de client serverului


o ServletResponse - contine datele transmise de server clientului

Exercitiu

In continuare va fi construita o aplicatie care afiseaza un mesaj clientului. Se vor


folosi utilitarele ANT de instalare.

Se creaza structura de directoare a continutului sursa. Recomandarea este ca


structura sa fie urmatoarea:

 /ex1
o /src
 /java
 PrimulServlet.java
o build.xml
o web.xml

Continutul servletului PrimulServlet este prezentat in continuare:

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import java.net.*;

public class PrimulServlet extends HttpServlet


{
// --- primul servlet : afiseaza un mesaj simplu

public void doGet (HttpServletRequest


request,HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter out;
String title = "Primul Exemplu de Servlet";

// seteaza continutul raspunsului folosind obiectul


response
response.setContentType("text/html");

// seteaza out ca iesire pentru client


out = response.getWriter();

out.println("<HTML><HEAD><TITLE>");
out.println(title);
out.println("</TITLE></HEAD><BODY>");
out.println("<H1>" + title + "</H1>");
out.println("<P>Acesta este primul servlet");
out.println("</BODY></HTML>");
out.close();
}
}

Fisierul web.xml realizeaza o mapare a servletului in contextul serverului


TOMCAT. Continutul acestuia este prezentat in continuare:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

<!-- Definirea numelui de acces si a clasei servletului -->


<servlet>
<servlet-name>PrimulServlet</servlet-name>
<servlet-class>PrimulServlet</servlet-class>
</servlet>
<!-- Maparea adresei URL -->
<servlet-mapping>
<servlet-name>PrimulServlet</servlet-name>
<url-pattern>/PrimulServlet</url-pattern>
</servlet-mapping>

</web-app>

Fisierul build.xml va fi construit in mod similar celui din laboratorul 1. Se vor


consulta din manualul ANT task-urile <copy> si <fileset>. In cazul in care nu se
reuseste construirea unui fisier de build.xml, o posibila solutie poate fi aceasta.

Interactiunea cu clientii

Scopul principal al servleturilor este facilitarea interactiunii cu clientul. Prin


intermediul metodei service , servlet-ul primeste cererile clientilor si le
redirectioneaza catre metodele specializate:

o doGet - pentru protocolul HTTP GET


o doPost - pentru protocolul HTTP POST

Programatorul trebuie sa supradefinesca metodele necesare, acestea returnand


implicit BAD_REQUEST (404) . Metoda supradefinita primeste ca argumente doua
obiecte:

o HttpServletRequest - contine datele de la client


o HttpServletResponse - contine datele catre client

Obiectul HttpServletRequest ofera acces catre header-ul HTTP al mesajului si


catre argumentele pe care clientul le-a trimis in cerere. Pentru a accesa
argumentele trimise de client serverului, se foloseste
methodagetParameter(<nume_argument>).

Obiectul HttpServletResponse contine raspunsul trimis de server clientului. Una


din metodele posibile de a apela obiectul este metoda getWriter() care intoarce
un obiect de tip Writer, in care se pot scrie datele trimise clientului.

import javax.servlet.http.*;
import javax.servlet.*;
import java.io.*;
import java.net.*;

public class PrimulServlet extends HttpServlet


{
// --- primul servlet : afiseaza un mesaj simplu

public void doGet (HttpServletRequest


request,HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter out;
String title = "Primul Exemplu de Servlet";

// seteaza continutul raspunsului folosind obiectul


response
response.setContentType("text/html");

// seteaza out ca iesire pentru client


out = response.getWriter();
String om = request.getParameter("nume");

out.println("<HTML><HEAD><TITLE>");
out.println(title);
out.println("</TITLE></HEAD><BODY>");
out.println("<H1>" + title + "</H1>");
out.println("<P>Aceasta este cererea clientului servlet"
+ om);
out.println("</BODY></HTML>");
out.close();
}
}

Exercitiu

Sa se creeze o aplicatie care preia de la utilizator un formular pentru introducerea


de articole intr-un magazin virtual, analizeaza datele si semnaleaza eventualele
neconcordante aparute in campurile formularului. Daca formularul a fost
completat corect va fi semnalat si acest fapt.

Se creaza structura de directoare a continutului sursa. Recomandarea este ca


structura sa fie urmatoarea:

 /ex1
o /src
 /java
 Analiza.java
 /jsp
 index.jsp
 formular.jsp
o build.xml
o web.xml

Fisierul index.jsp contine un mesaj de introducere si un link catre


fisierul formular.jsp care trimite datele catre servletul Analiza.java.
Laborator 3

In exemplul urmator se vor citi toate datele trimise de client servletului.


A Acestea vor fi afisate clientului sub forma unui tabel.

Codul pentru servletul ShowParameters este aici.


Codul pentru formular este aici.

Continutul sursa, fisierele build.xml si web.xml vor fi implementate in


conformitate cu aplicatia.

Ciclul de viata al servlet-urilor


B
La initializarea servleturilor, serverul creaza o singura instanta a
acestora. Pentru fiecare client care invoca servletul, este creat un thread
separat care se va ocupa de prelucrarea datelor trimise de client
via doGet sau doPost.

Atunci cand un servlet este initializat de server, methoda init a acestuia


este invocata. Din cauza ca serverul creaza o singura instanta pentru
servlet, metoda init va fi apelata o singura data. Din acest motiv este
recomandabil sa scriem codul de initializare pentru aplicatia noastra in
aceasta metoda. Dupa initializarea servletului, invocarea de catre clienti
duce la crearea unui thread (pentru fiecare in parte) care apeleaza
metoda service a acestuia. Metoda serviceapeleaza la randul ei una din
metodele doGet, doPost etc. in functie de cererea HTTP a clientului.
Atunci cand serverul decide sa elibereze servletul din memorie, apeleaza
metoda destroy a acestuia.

Metoda init este apelata doar atunci cand servletul este creat. Servletul
poate fi creat in mod dinamic, atunci cand clientul il invoca sau in mod
static, atunci cand serverul este pornit. Modalitatea de initializare a
servletului este setata in configurarile serverului. Metoda init poate fi
scrisa in doua moduri: in prima varianta, metoda nu primeste nici un
argument - este folosita in cazul in care servletul nu citeste configurarile
serverului pe care se afla; a doua varianta primeste ca argument
obiectul ServletConfig prin intermediul caruia are acces la diferiti
parametri ai serverului.

Exemplu pentru prima modalitate:

public void init() throws ServletException {


// Cod de initializare ...
}

Exemplu pentru a doua modalitate:


public void init(ServletConfig config)
throws ServletException {
super.init(config);
// Cod de initializare ...
}

De fiecare data cand un servlet este invocat, serverul creaza un nou fir
de executie si transfera apelul metodei service. Aceasta verifica tipul
cererii HTTP si apeleaza una din metodele doGet, doPost etc.
Supradefinirea metodei service se face astfel:

public void service(HttpServletRequest request,HttpServletResponse


response)
throws ServletException, IOException {
// Cod ....
}

Supradefinirea metodei service nu este intotdeauna recomandata. Chiar


daca vor apare dublari ale codului, este bine sa supradefinim fiecare
metoda de tipul doXxx in parte:

public void doGet(HttpServletRequest request,HttpServletResponse


response)
throws ServletException, IOException {
// cod ...
}
public void doPost(HttpServletRequest request,HttpServletResponse
response)
throws ServletException, IOException {
// cererile provenite via POST sunt redirectate catre
// doGet in scopul evitarii dublarii codului
doGet(request, response);
}

Asa cum spuneam mai sus, serverul creaza o singura instanta pentru un
servlet si cate un nou thread pentru fiecare acces la servlet. Atunci cand
servletul contine campuri sau date partajate, modelul multi-threading nu
este cel mai indicat. Pentru a preveni crearea de thread-uri multiple,
servletul trebuie sa implementeze interfata SingleThreadModel :

public class PrimulServlet extends HttpServlet


implements SingleThreadModel {
// cod ...
}

Prin implementarea interfetei, sistemul garanteaza ca nu va exista mai


mult de un singur fir de executie care acceseaza instanta servletului.
Acest lucru poate fi realizat prin plasarea cererilor intr-un buffer si
tratarea acestora una cate una sau prin crearea unor instante multiple ale
servletului. Totusi, pentru accesul la resurse externe, servleturile trebuie
sa implementeze metode specifice sincronizate. Implementarea
interfetei SingleThreadModel duce la scaderea semnificativa a
performantelor serverului deci numai in situatii absolut necesare se
apeleaza la aceasta.

Serverul poate lua decizia eliminarii servletului din memorie ca urmare


a unei cereri explicite sau a neaccesarii indelungate a servletului. Inainte
de a-l elimina, este invocata metoda destroya servletului. Aceasta
metoda ofera servletului sansa de a efectua operatii absolut necesare de
finalizare cum ar fi: inchiderea conexiunilor la baza de date, terminarea
thread-urilor create, salvarea datelor etc.

In continuare este prezentat un exemplu de folosire a parametrilor de


initializare in cazul unui servlet. Parametrii de initializare vor fi:

o message - reprezinta mesajul care va fi


trimis clientului
o repeats - specifica de cate ori va fi
afisat mesajul clientului

Codul pentru servletul ShowMessage este aici. In cazul serverului


TOMCAT, parametrii de initializare sunt definiti in
fisierul web.xml. Portiunea din acesta care ne intereseaza este
prezentata in continuare:

<web-app>
<servlet>
<servlet-name>ShowMessage</servlet-name>
<servlet-class>ShowMessage</servlet-class>
<init-param>
<param-name>message</param-name>
<param-value>un exemplu de mesaj</param-value>
</init-param>
<init-param>
<param-name>repeats</param-name>
<param-value>5</param-value>
</init-param>
</servlet>
<!-- Se completeaza in conformitate -->
</web-app>
D Continutul mesajelor HTTP

In afara de datele trimise de client servlet-ului, protocolul HTTP


incapsuleaza in mesaj si alte informatii. In cadrul mesajului, acestea
sunt separate de cele trimise de client. In continuare este prezentat
un astfel de mesaj HTTP care este rezultatul apelului unui servlet de
cautare,search, pentru cuvintele "documentatie java".

GET /search?keywords=documentatie+java HTTP/1.1


Accept: image/gif, image/jpg, */*
Accept-Encoding: gzip
Connection: Keep-Alive
Cookie: userID=id456578
Host: www.cauta.com
Referer: http://www.cauta.com/carti.html
User-Agent: Mozilla/4.7 [en] (Win98; U)

Cererea include parametrii ( headers ) Accept, Accept-Encoding,


Connection, Cookie etc. care pot fi extrem de folositori servletului.
Citirea acestora de catre servlet este extrem de simpla: se invoca
metoda getHeader() a obiectului HttpServletRequest, care intoarce
un obiect Stringdaca respectivul parametru ( header ) exista in
mesaj sau null daca acesta nu exista. Parametrii nu sunt case-
sensitive. Datorita faptului ca unii parametrii sunt invocati extrem de
des, in clasa HttpServletRequest au fost prevazute metode pentru
accesul direct la acestia:

o getCookies - intoarce continutul header-ului Cookie


intr-un Array de obiecte
o getAuthType, getRemoteUser - interpreteaza
header-ul Authorization
o getContentLength - intoarce ca
valoare int continutul header-ului Content-Length
o getContentType - intoarce valoarea header-ului
Content-Type
o getDateHeader - intoarce un obiect de tip Date
o getHeaderNames - intoarce un obiect de
tip Enumeration care contine toate header-urile
mesajului
o getHeaders - intoarce un obiect de
tip Enumeration care contine toate aparitiile header-
ului specificat de metoda

In continuare este prezentat un servlet care afiseaza o parte din


continutul mesajului HTTP. Recomandarea este sa adaptati servletul
la unul din exercitiile anterioare:
1:import java.io.*;
2:import javax.servlet.*;
3:import javax.servlet.http.*;
4:import java.util.*;
5:
6:public class ShowRequestHeaders extends HttpServlet {
7:
8:public void doGet(HttpServletRequest
request,HttpServletResponse response)
9: throws ServletException, IOException {
10:
11: response.setContentType("text/html");
12: PrintWriter out = response.getWriter();
13: String title = "Exemplu de header HTTP";
14:
15: out.println(title +
16: "<BODY BGCOLOR=\"#FDF5E6\">\n" +
17: "<H1 ALIGN=CENTER>" + title + "</H1>\n" +
18: "<B>Request Method: </B>" +
19: request.getMethod() + "<BR>\n" +
20: "<B>Request URI: </B>" +
21: request.getRequestURI() + "<BR>\n" +
22: "<B>Request Protocol: </B>" +
23: request.getProtocol() + "<BR><BR>\n" +
24: "<TABLE BORDER=1 ALIGN=CENTER>\n" +
25: "<TR BGCOLOR=\"#FFAD00\">\n" +
26: "<TH>Header Name<TH>Header Value");
27:
28: Enumeration headerNames = request.getHeaderNames();
29: while(headerNames.hasMoreElements()) {
30: String headerName =
(String)headerNames.nextElement();
31: out.println("<TR><TD>" + headerName);
32: out.println(" <TD>" + request.getHeader(headerName));
33: }//while
34:
35: out.println("</TABLE>\n</BODY></HTML>");
36:}//doGet
37:
38:
39:public void doPost(HttpServletRequest
request,HttpServletResponse response)
40: throws ServletException, IOException {
41: doGet(request, response);
42:}//doPost
43:}//class

Un exemplu in care sunt expuse mai multi din parametrii HTTP este
prezentat in continuare:

1:import java.io.*;
2:import javax.servlet.*;
3:import javax.servlet.http.*;
4:import java.util.*;
5:
6:public class ShowHTTPVariables extends HttpServlet {
7:
8:public void doGet(HttpServletRequest
request,HttpServletResponse response)
9: throws ServletException, IOException {
10: response.setContentType("text/html");
11: PrintWriter out = response.getWriter();
12: String[][] variables ={
13: { "AUTH_TYPE", request.getAuthType() },
14: { "CONTENT_LENGTH",
String.valueOf(request.getContentLength()) },
15: { "CONTENT_TYPE", request.getContentType() },
16: {
"DOCUMENT_ROOT",getServletContext().getRealPath("/") },
17: { "PATH_INFO", request.getPathInfo() },
18: { "PATH_TRANSLATED", request.getPathTranslated() },
19: { "QUERY_STRING", request.getQueryString() },
20: { "REMOTE_ADDR", request.getRemoteAddr() },
21: { "REMOTE_HOST", request.getRemoteHost() },
22: { "REMOTE_USER", request.getRemoteUser() },
23: { "REQUEST_METHOD", request.getMethod() },
24: { "SCRIPT_NAME", request.getServletPath() },
25: { "SERVER_NAME", request.getServerName() },
26: { "SERVER_PORT",String.valueOf(request.getServerPort())
},
27: { "SERVER_PROTOCOL", request.getProtocol() },
28: {
"SERVER_SOFTWARE",getServletContext().getServerInfo() }
29: };
30:
31: String title = "Exemplu complex";
32:
33: out.println(title +
34: "<BODY BGCOLOR=\"#FDF5E6\">\n" +
35: "<H1 ALIGN=CENTER>" + title + "</H1>\n" +
36: "<TABLE BORDER=1 ALIGN=CENTER>\n" +
37: "<TR BGCOLOR=\"#FFAD00\">\n" +
38: "<TH>Numele variabilei<TH>Value");
39:
40: for(int i=0; i<variables.length; i++) {
41: String varName = variables[i][0];
42: String varValue = variables[i][1];
43: if (varValue == null) varValue = "<I>Nespecificata</I>";
44: out.println("<TR><TD>" + varName + "<TD>" +
varValue);
45: }//for
46:
47: out.println("</TABLE></BODY></HTML>");
48:}//doGet
49:
50:
51:public void doPost(HttpServletRequest
request,HttpServletResponse response)
52: throws ServletException, IOException {
53: doGet(request, response);
54:}//doPost
55:}//class
O mai buna detailiere a parametrilor continuti intr-un mesaj HTTP
poate fi gasita in specificatia RFC 2616.

Laborator 4

Cookies

Cookie-urile sunt secvente de date text, de mici dimensiuni,


trimise de server clientului. Atunci cand clientul viziteaza din nou
acelasi server sau domeniu, cokkie-ul este trimis fara modificari
catre acesta. Cookie-urile ofera serverului posibilitatea de a stoca
anumite informatii specifice clientului si de a le folosi ulterior
pentru:

o identificarea clientului in timpul unei sesiuni de


comert electronic
o stocarea numelui si a parolei pentru un anumit
site
o navigare personalizata
o reclama preferentiala

Majoritatea browserelor limiteaza cookie-urile la 20 per site si la


300 in total. Dimensiunea maxima a unui cookie este limitata la
4KB. In plus, cookie-urile sunt folosite doar pentru stocare de
date si niciodata nu sunt executate. Din aceste motive, cookie-
urile nu prezinta nici un fel de risc pentru computer-ul clientului.

Pentru a trimite un cookie clientului, un servlet trebuie sa creeze


o instanta a acestuia folosind constructorul new Cookie(name,
value) , sa seteze optiuni ale acestuia si sa-l insereze in
mesajul de raspuns folosindresponse.addCookie(cookie).
Pentru a citi un cookie, servletul apeleaza
metodarequest.getCookies(), care intoarce un tablou de
cookie-uri asociate de browser cu server-ul respectiv.

Inainte de a trimite cookie-ul clientului, acestuia ii pot fi setate


una din urmatoarele proprietati:

o public String getComment()


public void setComment(String str) -
comentarii referitoare la cookie
o public String getDomain()
public void setDomain(String
domainPattern) - domeniul catre care browser-ul
clientului va trimite cookie-ul. In mod normal
cookie-ul este trimis catre domeniu de unde a fost
trimis, insa pot apare situatii in care acesta trebuie
trimis si catre altele
o public int getMaxAge()
public void setMaxAge(int lifetime) - specifica
cat timp (in secunde) browserul va folosi cookie-ul.
Daca valoarea este negativa, cookie-ul va fi utilizat
doar pentru sesiunea curenta
o public String getName()
public void setName(String cookieName) -
metoda getName este folosita aproape mereu
pentru a extrage din request cookie-ul dorit
o public String getPath()
public void setPath(String path) - specifica
URL pentru care browserul trimite cookie-ul
o public boolean getSecure()
public void setSecure(boolean flag) - specifica
daca cookie-ul va fi trimis in cadrul unui protocol
securizat (https)
o public String getValue()
public void setValue(String value) - permit
setarea sau citirea de valori
o public int getVersion()
public void setVersion(int version) -
protoculul la care cookie-ul se conformeaza.

Exemplul urmator implementeaza un servlet care creeza 6


cookie-uri cu date diferite de expirare si un servlet care le
afiseaza.

Codul pentru SetCookie.java este prezentat in continuare:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SetCookies extends HttpServlet {

public void doGet(HttpServletRequest


request,HttpServletResponse response)
throws ServletException, IOException {
for(int i=0; i<3; i++) {
// durata de expirare este setata initial la -1
deci cookie-ul va fi
// folosit doar in cadrul sesiunii curente
Cookie cookie = new Cookie("Session-Cookie " +
i,"Cookie-Value-S" + i);
response.addCookie(cookie);
cookie = new Cookie("Persistent-Cookie " +
i,"Cookie-Value-P" + i);
// durata de expirare este setata la trei minute
cookie.setMaxAge(180);
response.addCookie(cookie);
}//for

response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Setare cookie-uri";

out.println(title +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" +
"Pentru a vizualiza cookie-urile > " +
"<A HREF=\"ShowCookies\">\n" +
"aici </A>.\n" +
"</BODY></HTML>");
}//doGet
}

Codul pentru ShowCookies.java este prezentat in continuare:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class ShowCookies extends HttpServlet {

public void doGet(HttpServletRequest


request,HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Cookie-uri trimise de browser";

out.println(title +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=\"CENTER\">\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
" <TH>Nume\n" +
" <TH>Valoare");

Cookie[] cookies = request.getCookies();


Cookie cookie;

for(int i=0; i<cookies.length; i++) {


cookie = cookies[i];
out.println("<TR>\n" +
" <TD>" + cookie.getName() + "\n" +
" <TD>" + cookie.getValue());
}

out.println("</TABLE></BODY></HTML>");
}
}
Sesiuni

Protocolul HTTP este un protocol fara mentinerea starii. Chiar


daca serverul poate mentine o conexiune deschisa mai mult timp
(keep-alive) , acesta tot nu permite stocarea de informatie
contextuala despre client. In cazul unei aplicatii de comert
electronic, serverul trebuie sa dispuna de o modalitate de
identificare a clientului pentru a putea manipula coerent
produsele aflate in cos.

Problema are trei solutii: folosirea cookie-urilor, rescrierea URL-


ului sau campuri de formular ascunse. In cadrul cookie-urilor
poate fi stocat un numar unic care identifica sesiunea curenta.
Prin rescrierea URL-ului se ataseaza la acesta un numar unic care
este transmis impreuna cu datele clientului de fiecare data. A
treia modalitate consta in crearea unor campuri ascunse in
formular care transmit numarul unic de identificare. Ultimile doua
metode sunt folosite in cazul in care browser-ul clientului nu
suporta cookie-uri.

In cazul aplicatiilor de mari dimensiuni, folosirea directa a


cookie-urilor sau celorlalte metode este dificila. API-ul
javax.servlet pune la dispozitia programatorul clasa HttpSession,
care ii permite acestuia sa se concentreze asupra functionalitatii
aplicatiilor si nu asupra detaliilor tehnice.

O sesiune in cadrul servletului este creata prin apelarea


metodei getSession a obiectului HttpServletRequest.

HttpSession session = request.getSession(true);

Servletul extrage din cookie sau URL numarul unic de identificare


a clientului, apoi il foloseste pentru a identifica
obiectul HttpSession asociat clientului in care sunt stocate date
despre acesta. Daca metoda getSession intoarce valoarea null,
inseamna ca utilizatorul acceseaza prima data servletul
respectiv. In consecinta, acesta va crea o noua sesiune pentru
clientul respectiv.

Metodele disponibile in clasa HttpSession sunt:

o public Object getValue(String name)


public Object getAttribute(String name) -
aceste metode intorc valoarea atributului name din
sesiune.
o public void putValue(String name, Object
obj)
public void setAttribute(String name, Object
obj) - stocheaza in sesiune un obiect cu
numele name
o public void removeValue(String name)
public void removeAttribute(String name) -
sterge din sesiune obiectul asociat cu numele
respectiv
o public String[] getValueNames()
public Enumeration getAttributeNames() -
intoarce numele tuturor obiectelor din sesiune
o public String getId() - intoarce numarul unic
generat pentru sesiunea curenta
o public boolean isNew() - intoarce true daca
clientul apeleaza prima data servlet-ul respectiv
o public long getCreationTime() - intoarce
timpul in milisecunde de la 1 ianuarie 1970, ora
12.00 PM (GMT) pana la crearea sesiunii
o public long getLastAccessedTime() - intoarce
timpul in milisecunde de la 1 ianuarie 1970, ora
12.00 PM (GMT) pana la ultima accesare a acesteia
o public int getMaxInactiveInterval()
public void setMaxInactiveInterval(int
seconds) - seteaza intervalul de timp, in secunde,
pentru care sesiunea ramane activa in conditiile
neaccesarii acesteia de client. O valoare negativa
inseamna ca sesiunea nu va fi distrusa.
o public void invalidate() - distruge sesiunea

In exemplul urmator este prezentat un servlet care afiseaza


informatii despre sesiune si numarul de accesari a paginii
respective. Codul pentru ShowSession.javaeste prezentat in
continuare:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.net.*;
import java.util.*;

public class ShowSession extends HttpServlet {

public void doGet(HttpServletRequest


request,HttpServletResponse response)
throws ServletException, IOException {

response.setContentType("text/html");
PrintWriter out = response.getWriter();
String title = "Exemplu de Sesiune";

// crearea unei noi sesiuni sau apelarea celei


existente
HttpSession session = request.getSession(true);

String heading;
Integer accessCount
=(Integer)session.getAttribute("accessCount");
if (accessCount == null) {
accessCount = new Integer(0);
heading = "Prima data ! Bine ati venit !";
} else {
heading = "Ati mai fost ! Bine ati revenit !";
accessCount = new
Integer(accessCount.intValue() + 1);
}//if

session.setAttribute("accessCount", accessCount);

out.println(title +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=\"CENTER\">" + heading + "</H1>\n" +
"<H2>Informatii despre sesiune:</H2>\n" +
"<TABLE BORDER=1 ALIGN=\"CENTER\">\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
" <TH>Tip info.<TH>Valoare\n" +
"<TR>\n" +
" <TD>ID sesiune\n" +
" <TD>" + session.getId() + "\n" +
"<TR>\n" +
" <TD>Data crearii\n" +
" <TD>" + new Date(session.getCreationTime()) +
"\n" +
"<TR>\n" +
" <TD>Ultima accesare\n" +
" <TD>" + new
Date(session.getLastAccessedTime()) + "\n" +
"<TR>\n" +
" <TD>Numar de accesari\n" +
" <TD>" + accessCount + "\n" +
"</TABLE>\n" +
"</BODY></HTML>");
}//doGet

public void doPost(HttpServletRequest


request,HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}//doPost
}//class
Laborator 5
Tehnologia JavaServer Pages (JSP) permite combinarea
continutului static HTML cu continut dinamic. Procesul de crearea
unei pagini JSP este extrem de simplu: se creaza un fisier text cu
extensia .jsp. Acesta poate contine orice informatie de tip text,
de la texte simple pana la HTML. In momentul in care serverul
TOMCAT intalneste un fisier cu extensia .jsp, indiferent de
continutul acestuia, il interpreteaza si il transforma, in mod
transparent pentru utilizator, intr-un servlet - vezi schema
urmatoare:

In afara de continut HTML, JSP permite utilizarea a trei tipuri de


elemente:

o elemente script - cod Java care va fi


inclus in servletul final
o directive - permit controlul structurii
generale a servletului
o actiuni - specifica ce componente se
utilizeaza

A1. Referinta simpla JSP v1.2


A2. Referinta completa JSP v1.2

Elemente script

Exista trei modalitati de a introduce cod Java in JSP:

o <%= expresie %> - evalueaza expresia


respectiva
o <% cod java %> - interpreteaza codul Java
o <%! declaratie %> - permite introducerea de
declaratii

Pentru a simplifica expresiile, sunt definite cateva obiecte care se


numesc si obiecte implicite:

o request - reprezinta obiectul


HttpServletRequest si se utilizeaza exact ca
in cazul servleturilor
o response - reprezinta obiectul
HttpServletResponse si se utilizeaza exact
ca in cazul servleturilor
o out - reprezinta obiectul JspWriter
echivalentul lui PrintWriter folosit in cazul
servleturilor
o session - reprezinta obiectul HttpSession
si permite accesul la sesiunea care este
creata automat
o application - reprezinta obiectul
ServletContext care se obtine prin
getServletConfig().getContext() .
Servleturile si JSP-urile pot stoca date
persistente atat in sesiune cat si in context.
Stocarea datelor in context se realizeaza
prin intermediul metodei setAttribute.
Diferenta dintre sesiune si context este ca
datele stocate in context sunt accesibile
tuturor servleturilor si jsp-urilor din cadrul
aplicatiei web.
o config - reprezinta obiectul ServletConfig
o pageContext - reprezinta obiectul
PageContext si permite accesul la datele
comune din pagina respectiva

Sa se creeze un formular - cu numele formular.html - care sa


contina campul numesi campul varsta. Formularul va fi trimis
catre fisierul motor.jsp prezentat in continuare

<HTML>
<HEAD>
<TITLE>Expresii JSP</TITLE>
</HEAD>
<BODY>
<H2>Expresii</H2>
<UL>
<LI>Timp: <%= new java.util.Date() %>
<LI>Nume computer: <%= request.getRemoteHost() %>
<LI>ID Sesiune: <%= session.getId() %>
<LI>Nume:<%= request.getParameter("nume") %>
<LI>Varsta:<%= request.getParameter("varsta") %>
</UL>
</BODY>
</HTML>

In cazul in care se doreste introducerea de cod Java mai


complicat in cadrul paginii JSP, se foloseste constructia <% cod
java %>. In cadrul codului java se pot folosi oricare din
obiectele implicite definite mai sus.

In formularul de la exercitiul anterior, se adauga si


campul culoareFundal. Fisierulmotor.jsp se modifica astfel:

<HTML>
<HEAD>
<TITLE>JSP</TITLE>
</HEAD>

<%
String bgColor =
request.getParameter("culoareFundal");
boolean culoareSpecificata; // daca culoarea de
fundal
// a fost trimisa

if (bgColor != null) {
culoareSpecificata = true;
} else {
culoareSpecificata = false;
bgColor = "#ff0000"; // in caz ca alta culoare
nu a fost specificata
}
%>

<BODY BGCOLOR="<%= bgColor %>">

<H2>Expresii si Cod</H2>
<UL>
<LI>Timp: <%= new java.util.Date() %>
<LI>Nume computer: <%= request.getRemoteHost() %>
<LI>ID Sesiune: <%= session.getId() %>
<LI>Nume:<%= request.getParameter("nume") %>
<LI>Varsta:<%= request.getParameter("varsta") %>
</UL>

<%
if (culoareSpecificata) {
out.println("Culoarea de fundal specificata
este " +
bgColor + ".");
} else {
%>

<H1>Culoarea de fundal nu a fost specificata in


formular !!!</H1>
<%
}
%>

</BODY>
</HTML>
Declaratiile se introduc prin intermediul constructiei <%!
declaratie %>. In cadrul declaratiilor se definesc metodele sau
campurile folosite.

In exemplul urmator, in variabila accessCount se regaseste


numarul de accesari a site-ului.

<HTML>
<HEAD>
<TITLE>Declaratii</TITLE>
</HEAD>

<BODY>
<H1>Declaratii</H1>
<%! private int accessCount = 0; %>

<H2>Pagina a fost accesata de <u> <%= ++accessCount %>


</u> ori</H2>

</BODY>
</HTML>

Directive

In cadrul paginilor JSP exista trei tipuri mari de


directive: page, include si taglib. Directiva include permite
inserarea unui fisier extern pagina JSP la momentului compilarii
acesteia intr-un servlet. Directiva taglib permite crearea de
taguri personale.

Directiva page poate fi introdusa oriunde in pagina JSP si contine


urmatoarele
atribute: import, contentType, isThreadSafe, session, buffe
r, autoflush,extends, info, errorPage, isErrorPage si langua
ge.

Atributul import al directivei page permite specificarea


pachetelor si claselor care vor fi incluse. De exemplu, pentru
includerea claselor din pachetul java.util, in pagina JSP se va
folosi urmatoarea constructie:

<%@ page import="java.util.*" %>

Directiva page cu atributul import poate apare de mai multe ori


in cadrul aceleiasi pagini JSP. Sintaxa atributului este
urmatoarea:

<%@ page import="package.class" %>


<%@ page import="package.class1,...,package.classN" %>

Atributul contentType permite setarea tipului continutului care


este trimis clientului. Sintaxa este urmatoarea:
<%@ page contentType="MIME-Type" %>
<%@ page contentType="MIME-Type;
charset=Character-Set" %>

In aplicatia urmatoare se genereaza un tabel in format HTML sau


Office Excel in functie de parametrul format. Se creeaza un
formular care contine campul format, si fisierul tabel.jsp cu
urmatorul continut:

<HTML>
<HEAD>
<TITLE>Tabele</TITLE>
</HEAD>
<BODY>
<CENTER>
<H2>Preturi la mere si portocale</H2>
<%
String format = request.getParameter("format");
if ((format != null) && (format.equals("excel"))) {
response.setContentType("application/vnd.ms-
excel");
}
%>

<TABLE BORDER=1>
<TR><TH></TH><TH>Mere<TH>Portocale
<TR><TH>Primul semestru<TD>2307<TD>4706
<TR><TH>Al doilea semestru<TD>2982<TD>5104
<TR><TH>Al treilea semestru<TD>3011<TD>5220
<TR><TH>Al patrulea semestru <TD>3055<TD>5287
</TABLE>
</CENTER>
</BODY>
</HTML>

In laborator testarea aplicatiei se va realiza folosind sistemul


Windows2 pentru a putea rula aplicatia Office Excel.

Atributul isThreadSafe specifica daca servletul generat din


pagina JSP implementeaza interfata SingleThreadModel.
Daca isThreadSafe este false atunci servletul implementeaza
interfata SingleThreadModel.Sintaxa este urmatoarea:

<%@ page isThreadSafe="true" %><%!-- Default --%>


<%@ page isThreadSafe="false" %>

Atributul session specifica daca pagina respectiva participa intr-


o sesiune HTTP. Sintaxa este urmatoarea:

<%@ page session="true" %> <%-- Default --%>


<%@ page session="false" %>

Atributul buffer specifica marimea bufferului de date care este


trimis clientului. Marimea bufferului trebuie sa fie mai mare de
8kb, de exemplu 32kb ( <%@ page buffer="32kb" %> ).
Serverul astepta pana cand bufferul se umple si dupa aceea el
este trimis clientului. Sintaxa este urmatoarea:

<%@ page buffer="sizekb" %>


<%@ page buffer="none" %>

Atributul extends specifica superclasa pe care servletul generat


o va implementa. Acest atribut trebuie utilizat cu atentie
deoarece este posibil ca servletul sa extinda deja o superclasa.
Sintaxa este urmatoarea:

<%@ page extends="package.class" %>

Atributul errorPage specifica pagina JSP care va afisa si procesa erorile


din pagina curenta. Sintaxa este urmatoarea:

<%@ page errorPage="Relative URL" %>

Atributul isErrorPage specifica daca pagina curenta este o pagina care


prelucreaza erorile provenite din alta pagina JSP. Sintaxa este
urmatoarea:

<%@ page isErrorPage="true" %>


<%@ page isErrorPage="false" %> <%!-- Default --%>

Aplicatia urmatoare calculeaza viteza in functie de spatiu si timp. Se va


creea un formular care contine campurile spatiu si timp.
Pagina CalculeazaViteza.jsp va calcula viteza in functie de cei doi
parametri. Codul este prezentat in continuare:

<HTML>
<HEAD>
<TITLE>Calculul vitezei</TITLE>
</HEAD>

<BODY>

<%@ page errorPage="EroareViteza.jsp" %>

<TABLE BORDER=5 ALIGN="CENTER">


<TR><TH CLASS="TITLE">Calcul viteza</TABLE>

<%!
private double toDouble(String value) {
return(Double.valueOf(value).doubleValue());
}
%>

<%
double spatiu =
toDouble(request.getParameter("spatiu"));
double timp = toDouble(request.getParameter("timp"));
double viteza = spatiu/timp;
%>

<UL>
<LI>Spatiu: <%= spatiu %>
<LI>Timp: <%= timp %>
<LI>Viteza: <%= viteza %>
</UL>
</BODY>
</HTML>

Pagina EroareViteza.jsp va afisa erorile generate de


pagina CalculeazaViteza.jsp .

<HTML>
<HEAD>
<TITLE>Pagina erori</TITLE>
</HEAD>
<BODY>

<%@ page isErrorPage="true" %>

<TABLE BORDER=5 ALIGN="CENTER">


<TR><TH CLASS="TITLE">Pagina erori viteza</TABLE>
<P>
Pagina CalculeazaViteza.jsp a generat urmatoarele
erori:
<I><%= exception %></I>.
<p>Problema este la:
<PRE>
<% exception.printStackTrace(new PrintWriter(out)); %>
</PRE>
</BODY>
</HTML>

Redirectionarea datelor

In cazul aplicatiilor complexe, existenta unui singur servlet sau JSP


pentru intreaga aplicatie este total nepractica. In astfel de cazuri
aplicatia este alcatuita dintr-un numar mare de JSP-uri si servleturi,
fiecare cu rolul lui. Unele componente pot fi specializate pe comunicarea
cu clientul si rutarea cererilor catre componentele specializate, altele
sunt specializate pe anumite domenii, baze de date, email, calcule
matematice, prelucrari de date etc.

Pentru a permite unui servlet sa trimita altui servlet specializat cererea


respectiva, se foloseste obiectul RequestDispacher. Pentru a obtine un
obiect RequestDispacher se apeleaza metodagetRequestDispacher a
obiectului ServletContext. Dupa ce obiectul RequestDispacher este
obtinut, se foloseste metoda forward a acestuia pentru a transfera
controlul complet componentei specificate.

In continuare este prezentat codul care trebuie inclus intr-un servlet


pentru ca acesta sa poata transfera controlul unui alt servlet sau JSP.

public void doGet(HttpServletRequest


request,HttpServletResponse response)
throws ServletException, IOException {
String operation =
request.getParameter("catre");
if (catre == null) {
catre = "nimic";
}
if (catre.equals("adresa1")) {
gotoPage("/carti/carte1.jsp",request,
response);
} else if (catre.equals("adresa2")) {

gotoPage("/magazin/formular2.jsp?client=2",request,
response);
} else {

gotoPage("/erori/eroareHandler?er=5",request,
response);
}
}//doGet

private void gotoPage(String address,


HttpServletRequest
request,HttpServletResponse response)
throws ServletException, IOException {

RequestDispatcher dispatcher
=getServletContext().getRequestDispatcher(address);
dispatcher.forward(request, response);
}//gotoPage

Pentru ca datele sa poata fi vizibile de catre servletul sau JSP destinatie,


acestea trebuiesc salvate intr-o sesiune HTTP sau in ServletContext.
Incepand cu versiunea 2.2 a specificatiei SUN pentru servleturi, datele
pot fi transmise catre client direct in adresa URL, exact ca in cazul
metodei GET clasice ( vezi exemplul anterior ).

In unele cazuri, prelucrarea datelor se realizeaza partial in componenta


curenta si partial in componenta specializata. Pentru a rezolva acest caz,
in loc de metoda forward se foloseste metoda include conform
exemplului urmator:

PrintWriter out = response.getWriter();


out.println("...");

RequestDispatcher dispatcher
=getServletContext().getRequestDispatcher("adresa");
dispatcher.include(request, response);

out.println("...");

In cazul in care componenta care ruteaza cererile este o pagina JSP


atunci se va folosi elementul jsp:forward.
De exemplu:

<%
String destinatie;
if (Math.random() > 0.5) {
destinatie = "/pagina1.jsp";
} else {
destinatie = "/pagina2.jsp";
}
%>

<jsp:forward page="<%= destination %>" />

S-ar putea să vă placă și