Sunteți pe pagina 1din 53

8.

JAVA SERVER PAGES (JSP)

8.1. Introducere
8.1.1. Privire general i cteva exemple simple
Java Servlet Pages (JSP) [87, 2, 9, 51] este o tehnologie care permite descrierea unei aplicaii Web distribuite, specificnd ntr-un singur document att partea client ct i partea server. Sintaxa scrierii permite separarea prii dinamice de partea static a unei astfel de pagini Web. Partea static se scrie ca i un fiier normal HTML [85] sau XML [84, 24, 38] care urmeaz a fi invocat de browser. Secvenele dinamice sunt distribuite n acelai fiier, intercalate cu elementele din partea static. Separarea secvenelor dinamice se face cu nite tag-uri speciale care conin construcii de forma <%...%> sau <jsp:...>, cunoscute i sub numele de elemente scripting. Din punct de vedere al tehnologiilor Java, JSP este o extensie a tehnologiei servlet prin care se permite elaborarea de aplicaii n stil HTML sau XML. Evident, nu este unica tehnologie care permite acest lucru. Specificaiile HTML [85] permit specificarea n documente HTML, prin SSI (Server Side Included), a unor elemente, relativ simple, de comportare a server-ului. ns cele mai apropiate "rude" ale JSP sunt tehnologiile ASP (Application Server Pages) [82, 24] i PHP (Programmable/Professional Hypertext Processor dup ce iniial a fost Personal Home Page) [96, 24]. Att ASP ct i PHP utilizeaz specificarea intercalat: dinamic - static prin elemente de scripting. Iat, spre exemplu, un fiier cu numele Salut.jsp, care are coninutul din programul 8.1
Va saluta <I><%= request.getParameter("nume") %></I> Programul 8.1. Salut.jsp

n stilul servlet, acest fiier va fi depus n zona aplicaiilor distribuite ale Tomcat, n acelai loc cu documentele HTML (vezi 7.1.3.5). De exemplu, poate fi depus n directorul $WEBAPP_NAME al aplicaiei pdpj din capitolul precedent:
%CATALINA_HOME%\webapps\pdpj\

407

Toate exemplele pe care le vom prezenta n acest capitol, cu excepia celor la care vom specifica altfel, vor fi depuse n acelai director de mai sus! Invocnd:
http://florin.cs.ubbcluj.ro:8080/Salut.jsp?nume=Boian+Florian

browser-ul va afia imaginea din fig. 8.1.

Figura 8.1. Efectul lui Salut.jsp

8.1.1.1. Cum funcioneaz JSP? Tehnologia JSP este intim legat de tehnologia servlet prezentat n capitolul precedent. Containerul de servlet asigur toate funciile necesare lucrului cu JSP. O pagin JSP este creat ntr-un fiier de tip .jsp i este plasat n zona $WEBAPP_NAME - contextul aplicaiei n containerul de servlet. Pe post de container poate fi Tomcat, JRun sau orice alt container servlet. La rndul lui, containerul poate fi legat de server-ul Web sau poate aciona singur (cu un server Web ncorporat), aa dup cum am vzut n 7.1.2. n faza de dezvoltare a aplicaiilor servlet i JSP se poate utiliza cu succes server-ul Web ncorporat n container. n faza de exploatare se recomand folosirea unor servere Web consacrate: Apache, IIS etc. La prima invocare a unei pagini JSP, componenta JSP-Engine preia fiierul .jsp i construiete din el un text surs Java al unui servlet. De exemplu, pentru fiierul Salut.jsp:
Va saluta <I><%= request.getParameter("nume") %></I>

Servlet-ul generat de ctre JSP-Engine este prezentat n programul 8.2.


package org.apache.jsp; import import import import javax.servlet.*; javax.servlet.http.*; javax.servlet.jsp.*; org.apache.jasper.runtime.*;

408

public class Salut$jsp extends HttpJspBase { static { } public Salut$jsp( ) { } private static boolean _jspx_inited = false; public final void _jspx_init() throws org.apache.jasper.runtime.JspException { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { JspFactory _jspxFactory = null; PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; String _value = null; try { if (_jspx_inited == false) { synchronized (this) { if (_jspx_inited == false) { _jspx_init(); _jspx_inited = true; } } } _jspxFactory = JspFactory.getDefaultFactory(); response.setContentType( "text/html;charset=ISO-8859-1"); pageContext = _jspxFactory.getPageContext(this, request, response, "", true, 8192, true); application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); // HTML // begin [file="/Salut.jsp";from=(0,0);to=(0,13)] out.write("Va saluta <I>"); // end // begin [file="/Salut.jsp";from=(0,16);to=(0,46)] out.print( request.getParameter("nume") ); // end // HTML // begin [file="/Salut.jsp";from=(0,48);to=(1,0)] out.write("</I>\r\n"); // end } catch (Throwable t) {

409

if (out != null && out.getBufferSize() != 0) out.clearBuffer(); if (pageContext != null) pageContext.handlePageException(t); } finally { if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext); } } } Programul 8.2. Salut$jsp.java (generat din Salut.jsp)

Partea specific a generrii este indicat prin comentarii //HTML. Dup generarea acestei surse se depune fiierul .class ntr-un subdirector rezervat. De exemplu, n cazul Tomcat fiierele servlet *.java i *.class sunt plasate n $CATALINA_HOME/work/localhost. La urmtoarele invocri, dac pagina JSP nu a fost modificat, se apeleaz servlet-ul, exact aa cum se desfoar aciunea la lucrul cu servlet-uri. n cazul n care pagina JSP a fost modificat de la ultima creare a servlet-ului, atunci servlet-ul este creat din nou. Indiferent dac servlet-ul a fost recreat sau nu, invocarea se ncheie cu executarea servlet-ului. Cele dou exemple care urmeaz sunt efectul unor aciuni efectuate la server, n plus fa de simpla livrare a unui document HTML. Pentru moment este suficient s se observe, n aceste exemple, caracterul de mixtur ntre HTML i Java (un fel de struo-cmil). Dup aceste prime exemple vor urma toate explicaiile necesare. 8.1.1.2. Alfabet afiat circular Iat n fig. 8.2, un alt exemplu simplu de pagin generat prin JSP. Ea afieaz 26 de linii, fiecare linie cu 26 caractere literele mari ale alfabetului ncepnd cu alt liter de start. Documentul JSP care produce acest efect este fiierul Alfabet.jsp descris n programul 8.3.

410

Figura 8.2. Alfabet generat circular <html> <head> <title>Alfabetul cu JSP</title> </head> <body> <!-- Fixarea informaiilor globale din pagina --> <%@ page language = "java" %> <!-- Declara o variabila caracter --> <%! char c = 0; %> <!Scriptulet cu cod Java --> <% for (int i = 0; i < 26; i++) { for (int j = 0; j < 26; j++) { // Expune o litera mare a alfabetului c = (char) (0x41+(26-i+j)%26);

411

%> <% } %>

<!Scoate c.toString() in pagina HTML --> <%= c %>

<br> <% } %> </body> </html> Programul 8.3. Alfabet.jsp

8.1.1.3. Cinci numere aleatoare Exemplul care urmeaz este implementat n fiierul 5Numere.jsp, al crui coninut este dat n programul 8.4.
<html><head><title>Cinci numere aleatoare</title></head> <body><h3>Cinci numere aleatoare, mereu altele:</h3> <ol> <% java.util.Random r = new java.util.Random(); for (int i=0; i<5; i++) { %> <li><%=r.nextInt()%> <% } %> </ol> </body></html> Programul 8.4. 5Numere.jsp

Efectul, n browser este cel din fig. 8.3.

8.1.2. Obiecte predefinite JSP


Pentru a simplifica scrierea expresiilor i a poriunilor de cod (din partea dinamic) JSP ntreine nou obiecte predefinite. Acestea sunt:
request, response, out, session, application, config, pageContext, page, exception.

Aceste obiecte pot fi folosite fr ca s fie definite n prealabil. S le lum pe rnd.

412

Figura 8.3. Generarea a cinci numere aleatoare

8.1.2.1. request Este un obiect de tip HttpServletRequest i el nglobeaz parametrii cererii. Acetia sunt obinui prin intermediul metodei getParameter i depind de tipul cererii (GET, POST, HEAD etc.) i de header-ul HTTP primit (cookies, Referer etc.). n situaii speciale, request poate fi privit ca provenind dintr-o subclas a lui ServletRequest, alta dect HttpServletRequest, atunci cnd protocolul este altul dect HTTP. Din fericire, aceste situaii nu apar niciodat n practic. Exact ca i la servlet, utilizatorul poate solicita acestui obiect obinerea de cookies prin request.getCookies(). De asemenea poate obine de la el prin request.getSession(true) obiectul session. Att cookies, ct i session se utilizeaz exact aa cum am artat la servlet-uri. 8.1.2.2. response Acesta este obiectul HttpServletResponse asociat cu rspunsul ctre client. Prima lui sarcin, nainte de orice emisie ctre client este s seteze status code i header-ul rspunsului ctre client. Aceste setri nu mai sunt permise dup ce s-a trimis output spre client. n acest context, prin response.addCookie(...) se pot transmite spre browser cookies, aa cum am artat la servlet-uri.

413

8.1.2.3. out Este un obiect derivat din JSPWriter, o versiune buffer-izat a lui PrintWriter, prin care se trimit octei spre client. Fiind buffer-izat, ofer mecanisme de ajustare a dimensiunii buffer-ului i de golire a lui. Expresiile JSP depun automat rezultatele n el. Necesitatea de a folosi out n mod explicit n cadrul paginilor JSP apare destul de rar. 8.1.2.4. session Este un obiect de tip HttpSession obinut prin request.getSession(true)aa cum am artat mai sus. Deoarece sesiunea este creat automat, ea poate fi folosit explicit, cu excepia situaiei cnd n directiva page se folosete atributul session=false. n esen, acest obiect coincide cu obiectul de tip sesiune folosit la servlet-uri. n capitolul precedent am artat cum se folosete sessoin, motiv pentru care nu mai prezentm aici exemple. 8.1.2.5. application Este obiectul de tip ServletContext obinut prin getServletConfig().getContext(). Acest obiect se comport ca i un depozitar de obiecte. Metoda setAttribute(String nume, Object obiect) permite pstrarea unui obiect oarecare i asocierea unui nume obiectului pstrat. Metoda getAttribute(String nume) ntoarce obiectul care are asociat numele respectiv, iar metoda removeAttribute (String nume) terge din depozit obiectul i elibereaz numele asociat lui. Aciunile posibile asupra acestui obiect sunt cele precizate la servlet-uri (7.1.4.5). Depozitarul application este valabil pe toat durata aplicaiei, motorul JSP avnd grij s asigure persistena obiectelor coninute n el prin salvarea lor n contextul aplicaiei. Natural, obiectele introduse trebuie s fie serializabile. 8.1.2.6. page Este sinonim instanierii curente a paginii JSP (this). A fost creat mai ales pentru situaiile n care vor apare i alte limbaje script dect Java. Este, evident, valabil numai pentru documentul curent. 414

8.1.2.7. config Este obiectul de tip ServletConfig pentru pagina curent (this). Este folosit n faza de iniializare a servlet-ului (asociat JSP n cazul nostru) i exist doar pe durata paginii. 8.1.2.8. pageContext JSP introduce o nou clas numit PageContext. Ea ncapsuleaz o serie de faciliti ce caracterizeaz pagina la un moment dat. Obiectul exist doar pe durata existenei paginii. Printre metodele disponibile amintim:
setAttribute(), getAttribute(), findAttribute(), removeAttribute(), getAttributesScope(), getOut(), getException(), getPage() getRequest(), getResponse(), getSession(), getServletConfig(), getServletContext().

8.1.2.9. exception Acest obiect este excepia java.lang.Throwable care apare la un apel eronat al paginii.

8.1.3. Sumar al sintaxei construciilor JSP


Tabelul urmtor prezint un sumar al sintaxelor construciilor specifice JSP. Pentru utilizatorul cunosctor, acest tabel este practic suficient pentru a dezvolta aplicaii JSP.

8.2. Text static HTML i comentarii


Partea static a paginii, numit i text template, se scrie n JSP exact ca i n HTML clasic. Acest text poate fi creat cu orice instrument de dezvoltare, ncepnd de la editoarele de texte simple: vi, notepad i terminnd cu mediile evoluate de dezvoltare, cum ar fi Allaire HomeSite. Exist doar cteva excepii pe care le vom preciza n continuare:

415

Element JSP

Sintaxa

Echivalent XML

Interpretare Observaii Se evalueaz expresia i rezultatul este plasat n out. Se pot folosi obiecte predefinite Codul este inserat n metoda service

Expresie

Fragment de cod

Declaraie

<%= expresie %> <% cod %> <%! cod %>

<jsp:expression> expresie </jsp:expression> <jsp:scriptlet> cod </jsp:scriptlet> <jsp:declaration> cod </jsp:declaration>

Codul este inserat n corpul servlet-ului, dar nafara metodei service

Directiva page <jsp:directive.page atrib=val/>

<%@ page atrib=val %>

Directiva include <%@ include file=url %>

Aciunea jsp:include

<jsp:directive.inclu de file=url /> <jsp:include page=urlrelativ flush=true />

Setri generale pentru servlet engine. Conine maximum 11 perechi atribut-valoare: import={package.class | package.* }, ... contentType=mimeType [ ; charset=characterSet ] | text/html;charset=ISO8859-1 isThreadSafe=true|false session=true|false buffer=none|8kb|sizekb autoflush=true|false extends=package.class info=mesaj errorPage=url isErrorPage=true|false language=java n momentul translatrii n servlet se include de pe sistemul local fiierul citat, ncepnd cu linia n care apare directiva. Include un fiier ncepnd cu linia n cara apare aciunea, la momentul n care este cerut pagina

416

Element JSP <jsp:forward page=urlrelativ />

Sintaxa

Echivalent XML

Aciunea jsp:forward

Interpretare Observaii Trimite forward cererea la alt pagin.

Aciunea jsp:useBean

<jsp:useBean atrib=val/> sau <jsp:useBean atrib=val> - - </jsp:useBean>

Aciunea jsp:setProperty <jsp:setProperty atrib=val />

Aciunea jsp:getProperty

Gsete sau fabric un JavaBean. Atributele posibile sunt: id=nume scope=page|request| session|application class=package.class type=package.class beanName=package.class Seteaz proprieti ale unui bean, fie explicit, fie prin desemnarea de valori luate din parametrii cererii. Atributele sunt: name=beanName property=propertyname param=parameterName value=val Caut i pune n out valoarea parametrului din bean.

Definire taglib

<jsp:getProperty name=beanName property=propertyName /> <%@ taglib uri=numeTag prefix=prefixTag %> <%-- ... --%>

Comentarii JSP

Declar folosirea unui tag utilizator ce va fi folosit n pagin sub forma: <prefixTag:numeTag ...> Comentariul JSP <%-- ...--%> nu apare la client. Comentariul html <!-- ...--> apare la client.

417

Dac textul template trebuie s conin <%, atunci acesta trebuie specificat prin <\%. Dac textul template trebuie s conin %>, atunci acesta trebuie specificat prin %\>. Dac se cere ca n valoarea unui atribut s apar apostrof sau ghilimea, atunci specificarea se poate face prin \ respectiv \. n interiorul unui comentariu <%-- NU trebuie s apar caracterul : (dou puncte). n caz contrar JSP Engine va da eroare.

Aceste excepii generate de caracterele speciale < > pot fi evitate dac n locul lor se folosesc prescurtrile cunoscute din HTML: ;lt: ;gt: i celelalte. Comentariile JSP sunt de dou tipuri: comentarii JSP propriu-zise, folosite doar pentru documentarea paginii i care nu sunt trimise spre client i comentarii HTML care ajung i la client. n programul 8.5 prezentm un exemplu simplu de text static comments.jsp, n care am introdus dou comentarii.
<%@ page language="java" %> <html><head><title>Test comentarii</title></head><body> <h2>Urmeaza comentariu JSP: nu este emis la client</h2> <%-- Un comentariu ce nu este trimis la client --%> <h2>Urmeaza comentariu HTML: este emis la client, dar browserul il ignora</h2> <!-- Un comentariu ce este trimis emis la client, dar e ignorat de browser --> </body></html> Programul 8.5. comments.jsp

Efectul este prezentat n fig. 8.4. Utilizatorul poate s vad acest efect vizualiznd sursa din browser, ca n fig. 8.4.

Figura 8.4. Sursa n browser pentru comments.jsp

418

8.3. Tag-urile JSP


8.3.1. Elementele de scripting JSP
Elementele de scripting inserabile n pagini JSP sunt: tate. 8.3.1.1. Expresii Expresia dintre delimitatori poate fi orice expresie valid Java. n ea pot s apar inclusiv obiectele predefinite descrise mai sus. La sfritul expresiei NU se pune ; (punct-virgul). Ea este evaluat n faza de execuie, n momentul cererii paginii. Dup evaluare rezultatul este convertit la String i depus n ieire. Iat dou exemple de expresii:
Timpul curent la server este: <%= new java.util.Date() %> Clientul este: <%= request.getRemoteHost() %>

expresii, descrise sub forma: <%= . . . %> fragmente de cod, descrise sub forma: <% . . . %> declaraii, descrise sub forma: <%! . . . %>

Sintaxele complete, inclusiv formele pentru XML au fost deja prezen-

8.3.1.2. Fragmente de cod Aceste construcii sunt folosite atunci cnd se dorete introducerea n servlet a unor construcii mai sofisticate. Bucile de cod sunt introduse n servlet exact aa cum sunt scrise. Aceste fragmente se asambleaz cu textele template dintre ele sau cu expresiile i trebuie s conduc la instruciuni (construcii) Java corecte n servlet. Iat un exemplu de construcie JSP n care apar fragmente de cod combinate cu text static HTML:
<% if (Math.random() < 0.5) { %> Ai dat un zar <b>slab!</b> <% } else { %> Ai dat un zar <b>bun</b>(sau destul de bun). <% } %>

n servlet aceast secven este convertit n:


if (Math.random() < 0.5) { out.println("Ai dat un zar <b>slab!</b>");

419

} else { out.println("Ai dat un zar <b>bun</b>(sau"+ " destul de bun)); }

n interiorul unui fragment de cod se mai pot declara variabile sau metode care vor fi folosite mai trziu n fiier. De asemenea, se pot folosi obiectele implicite i obiectele bean declarate prin <jsp:useBean> aa dup cum vom vedea ceva mai ncolo. De exemplu:
<% String nume = request.getParameter(nume); %>

definete un string nume, care primete ca i valoare valoarea parametrului nume din cererea de la client. Textele statice, precum i alte tag-uri JSP trebuie scrise n afara fragmentului de cod. Execuia fragmentului (inclus n servlet) se face n momentul procesrii cererii clientului. Dac fragmentul produce o ieire, atunci ea este depus n obiectul out. De exemplu, iat cum se poate ntoarce n pagina rezultat spre client string-ul trimis de client ca i cerere prin metoda GET:
<% String cerere = request.getQueryString(); out.println(Ati cerut prin metoda GET:+cerere); %>

8.3.1.3. Declaraii JSP O declaraie JSP definete cmpuri i metode care vor fi inserate n corpul servlet-ului dar n afara metodei service (sau a celei care trateaz cererile). ntr-un tag declaraie trebuie s apar declaraii Java complete, cel puin una, i fiecare dintre ele s se termine cu ;. Iat cteva declaraii:
<%! int contor=0; %> <%! int a,b,c; Circle a = new Circle(2,0); %> <%! private int contor = 0; %>

Deoarece declaraiile nu genereaz nici o ieire, acestea trebuie s fie fcute corelat cu fragmentele de cod i cu expresiile care urmeaz a fi folosite n pagin. De exemplu, n cod poate s apar:
<%= ++contor %>

420

Declaraiile trebuie fcute nainte de utilizarea lor n pagina JSP. Variabilele i metodele care sunt declarate n pachetele importate prin directiva page nu mai trebuie declarate. Domeniul de valabilitate al declaraiilor depinde de prezena sau absena unor include, astfel: Dac nu se solicit nici un include, atunci declaraiile sunt valabile n tot textul paginii JSP. Dac se include un fiier dinamic prin <jsp:include>, atunci n acest fiier inclus declaraiile nu sunt valabile. Dac se include un fiier static prin <jsp:include> sau prin directiva <%@include, dar fr nici un fiier dinamic, atunci declaraiile sunt valabile n toate fiierele statice incluse.

8.3.1.4. Exemple cu tabele Am preluat de pe Internet un articol al lui Stephanie Kaminaris i Jose Annunziato n care ei prezint un exemplu simplu i frumos de codificare i configurare a tabelelor dinamice. De fapt, este vorba de abilitatea de a controla dinamic tag-urile <TD> i <TR> din cadrul tag-ului <TABLE>. Mai nti un exemplu n care sunt generate cinci linii fr cod n ele. Sursa JSP este dat n programul 8.6.
<TABLE BORDER=3> <% for(int lin=1; lin <= 5; lin++) { %> <TR> </TR> <% } %> </TABLE> Programul 8.6. tabel1.jsp

Printr-un ciclu for interior vom aduga cte nou coloane n fiecare linie. n fiecare celul vom pune indicii celulei respective. Se obine programul 8.7.
<TABLE BORDER=3> <% for(int lin=1; lin <= 5; row++) { %> <TR> <% for(int col=1; col<=9; col++) { %> <TD> (<%=col%>,<%=lin%>) </TD> <% } %> </TR>

421

<% } %> </TABLE> Programul 8.7. tabel2.jsp

n urma execuiei apare imaginea din fig. 8.5.

Figura 8.5. Un tabel simplu

Pagina JSP din fiierul tabelDinamicColorat.jsp (programul 8.8) arat cum se poate genera dinamic un tabel. Prin dou tag-uri INPUT se obin mai nti dimensiunile tabelului. Dup submit, este generat tabelul n forma dorit. Fiecare celul este colorat altfel i are alt coninut. Pentru a ne referi mai uor la ele, am numerotat liniile fiierului JSP.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: <HTML><HEAD><TITLE>Tabel dinamic colorat</TITLE></HEAD> <BODY> <CENTER> <H1>Tabel dinamic colorat</H1> <FORM METHOD=POST ACTION=tabelDinamicColorat.jsp> Latime tabel (<16) = <INPUT TYPE=TEXT NAME=WIDTH VALUE=5 SIZE=2>, Inaltime tabel (<16) = <INPUT TYPE=TEXT NAME=HEIGHT VALUE=15 SIZE=2>, <INPUT TYPE=SUBMIT VALUE="Afiseaza tabelul!"> </FORM> <HR> <% String w = request.getParameter("WIDTH"); String h = request.getParameter("HEIGHT"); if(w == null) w = "5"; if(h == null) h = "15"; int width = Integer.parseInt(w); int height = Integer.parseInt(h);

422

17: if(width>15) width = 15; 18: if(width<0) width = 0; 19: if(height>15) height = 15; 20: if(height<0) height = 0; 21: String[] colorArray = { "00", "11", "22", "33", 22: "44", "55", "66", "77", 23: "88", "99", "AA", "BB", 24: "CC", "DD", "EE", "FF" }; 25: <TABLE BORDER=5 CELLPADDING=0 CELLSPACING=0> 26: <% for(int y=0; y<=height; y++){ %> 27: <TR> 28: <% for(int x=0; x<=width; x++){ 29: String bgColor = "AA" + colorArray[y] + colorArray[x]; %> 30: <TD BGCOLOR=<%=bgColor%>> 31: (<%=x%>, <%=y%>) 32: </TD> 33: <% } %> 34: </TR> 35: <% } %> 36: </TABLE> 37: <HR> 38: </CENTER> 39: </BODY></HTML> Programul 8.8. tabelDinamicColorat.jsp

%>

Liniile 5-9 declar un formular n care se precizeaz lungimea i limea tabelului. Acestea au fost limitate la mai puin de 16. n liniile 11 i 12 se obin dimensiunile tabelului. Liniile 13-20 convertesc dimensiunile la ntregi, iar dac este cazul se fixeaz la dimensiunile implicite, 5 linii i 15 coloane. Linia 21 declar un tablou (de culori) cu valori de la 00 la FF. Linia 25 declar tabelul. Ciclul for din linia 26 d nlimea, adic numrul de linii. Ciclul din linia 28 d numrul de coloane din cadrul liniei. Linia 29 creeaz codul culorii celulei curente, iar linia 30 fixeaz culoarea celulei. Un astfel de tabel afiat de browser este cel din fig. 8.6.

423

Figura 8.6. Tabel dinamic colorat

Ceea ce mai trebuie remarcat la acest exemplu este faptul c n acelai document este specificat att formularul de cerere, ct i partea dinamic a JSP. 8.3.1.5. Exemplu: determinarea maximului a dou numere n capitolul despre servlet-uri am prezentat un exemplu de determinare a maximului dintre dou numere. n continuare vom prezenta dou variante JSP de rezolvare. Prima variant reproducere servlet-ul i este prezentat n fiierul max.jsp, descris n programul 8.9
<html><head><title>Maximul a doua numere</title></head><body> <% int n1 = Integer.parseInt(request.getParameter("unu")); int n2 = Integer.parseInt(request.getParameter("doi")); %>

424

<CENTER><H1>Maxim(<%=n1%>,<%=n2%>)= <%=(n1>n2)?n1:n2%></H1></CENTER> </body></html> Programul 8.9. max.jsp

Apelul acestuia se face n maniera obinuit:


http://masina:8080/pdpj/max.jsp?unu=1&doi=2

De asemenea, apelul poate fi fcut dintr-un formular ca cel din programul 8.10.
<html><head><title>Maximul a doua numere</title></head><body> <form method="post" action="max.jsp"> <p>Primul numar:<input type="text" name="unu"> <p>Al doilea:<input type="text" name="doi"> <p><input type=submit value= "Maxim"> </form></body></html> Programul 8.10. max.html

n a doua variant vom avea doar un singur document n care va aprea att formularul de cerere a numerelor, ct i rspunsul. Textul acestui fiier (maxim.jsp) este:
<html><head><title>Maximul a doua numere</title></head><body> <form method="post" action="maxim.jsp"> <p>Primul numar:<input type="text" name="unu"> <p>Al doilea:<input type="text" name="doi"> <p><input type=submit value= "Maxim"> </form> <% String s1 = request.getParameter("unu"); String s2 = request.getParameter("doi"); if ((s1!=null)&&(s2!=null)) { int n1 = Integer.parseInt(s1); int n2 = Integer.parseInt(s2); %> <CENTER><H1>Maxim(<%=n1%>,<%=n2%>)= <%=(n1>n2)?n1:n2%></H1></CENTER> <%}%> </body></html> Programul 8.11. maxim.jsp

Execuia este "interesant": mai nti afieaz formularul, apoi afieaz din nou formularul cu afiarea maximului numerelor date la completarea precedent! Din aceast cauz am preluat cererea n dou stringuri i am testat non-nulitatea lor pentru a determina maximul. Determinarea maximului i 425

afiarea lui se face doar n cazul cnd sunt nenule. Iat, n fig. 8.7, cum arat rezultatul (numerele 1 i 2 n cerere le-am completat iari dup afiarea maximului!):

Figura 8.7. Maximul a dou numere

8.3.2. Directive, includeri, forward


O directiv JSP afecteaz structura global a clasei servlet. Exist dou tipuri principale de directive: page i include. Includerea poate fi realizat i printr-o aciune include. Pentru invocarea unei alte pagini se folosete aciunea forward. 8.3.2.1. Directiva page Definete o serie de atribute care vor fi aplicate asupra ntregii pagini JSP. n prezent sunt definite 11 astfel de atribute, pe care le vom prezenta n continuare. 1. import="package.class" sau import="package.class1,...,package.classn" Se specific pachetele care vor fi importate pentru expresiile, declaraiile i fragmentele de cod ce vor apare n pagina JSP. n absena acestor specificri, clasele trebuie s fie vizibile de ctre container prin 426

CLASSPATH sau trebuie s fie plasate n acelai director cu fiierul class n care este plasat servlet-ul (vezi 7.1.3.5). De exemplu:
<%@ page import="java.util.*,java.sql.*" %>

2.

contentType="mimeType" sau contentType="mimeType; charset=characterSet" Valorile implicite n absena specificaiei sunt:


<%@ page contentType="text/html; charset=ISO-8859-1" %>

Se indic spre client tipul MIME (prin response.setContentType()) i eventual setul de caractere ce vor fi folosite pentru rspuns. De exemplu:
<%@ page contentType="text/plain" %>

Efectul este acelai cu al specificrii:


<% response.setContentType("text/plain"); %>

3.

isThreadSafe="true|false" Valoarea implicit, true indic situaia normal n care se proceseaz simultan mai multe cereri. Sincronizrile cad n seama proiectantului paginii. Valoarea false permite un singur thread la un moment dat. Eventualele cereri multiple vor avea consecin mai multe instanieri ale servlet-ului (identic cu funcionarea CGI).

4.

session="true|false" Valoarea true indic dreptul de a se folosi obiectul implicit session. Valoarea false nu permite aceast utilizare i va genera eroare n momentul folosirii.

5.

buffer="sizekb|none" Stabilete lungimea buffer-ului pentru obiectul out de tip JspWriter. Valoarea implicit este:
<%@ page buffer="8kb" %>

6.

autoFlush="true|false" Valoarea implicit, true, nseamn c la fiecare umplere a buffer-ului lui out acesta este automat golit. Valoarea false, rar folosit, arunc o excepie la umplerea buffer-ului. 427

7.

extends="package.class" Indic superclasa pe care o va extinde servlet-ul. Trebuie s fie o clas care extinde HTTPServlet. Se va folosi cu extrem pruden, deoarece servlet-ul poate folosi deja o superclas.

8.

info="mesaj" Se definete mesajul getServletInfo(). ce va fi returnat prin intermediul

9.

errorPage="urlFisier" Indic fiierul JSP care va fi trimis spre client n momentul aruncrii unei excepii.

10.

isErrorPage="true|false" Valoarea implicit, false, indic faptul c nu se poate folosi obiectul exception. Valoarea true permite folosirea errorPage.

11.

language="java" Indic limbajul n care se scriu declaraiile, expresiile i fragmentele de cod. n prezent se permite doar Java.

8.3.2.2. Directiva include Insereaz un fiier text, HTML sau cod JSP n timpul translatrii, atunci cnd este compilat fiierul JSP. De exemplu, fie fiierele din programele 8.12 i 8.13. principal.jsp :
<html><head><title>Test include</title></head> <body bgcolor="white"><font color="blue"> Data si ora curenta este: <%@ include file="data.jsp" %> </font></body></html> Programul 8.12. principal.jsp

428

data.jsp :
<%@ page import="java.util.*" %> <%= (new Date()).toLocaleString() %> Programul 8.13. data.jsp

n momentul invocrii paginii principal.jsp, se va afia data i ora curent a server-ului, ca n fig. 8.8.

Figura 8.8. Afiarea datei i a orei

Procesul de includere este static. Dac fiierul este un cod JSP, tag-urile acestuia sunt parsate i incluse n fiierul JSP. De aici rezult necesitatea unei atenii sporite la posibilele conflicte ce pot aprea dup includere: resurse dublu definite sau dublu deschise, tag-uri (<html>, <body> etc.) dublate .a.m.d. La modificarea unuia dintre fiierele incluse, servlet-ul se va recompila la prima invocare. 8.3.2.3. Aciunea jsp:include Include un fiier static sau dinamic ntr-un fiier JSP. Includerea poate fi static dac fiierul inclus este parsat i inclus n servlet, sau dinamic dac fiierul inclus acioneaz ca o nou cerere la care urmeaz s primeasc rspuns. Caracterul static sau dinamic NU se poate deduce din url-ul sau calea ce invoc fiierul de inclus ci doar din context. JSP engine decide aceasta i ori de cte ori are dubii, face includere dinamic. Sintaxa aciunii este:
<jsp:include page="url" flush="true" /> sau <jsp:include page=<%= expresie %> flush="true" />

De exemplu, un fiier cu mari anse de a fi static este:


<jsp:include page="copyright.html" />

429

n secvena de mai jos este vorba de includere dinamic - invocarea unei cereri:
--<ol> <li><jsp:include page="URL1" flush="true" /> <li><jsp:include page="URL1" flush="true" /> <li><jsp:include page="URL1" flush="true" /> </ol>

8.3.2.4. Aciunea forward Aceast aciune permite trimiterea mai departe a cererii spre o alt pagin. Aceasta poate fi, la rndul ei, un fiier HTML, un fiier JSP sau un servlet. Sintaxa este:
<jsp:forward page="urlRelativ|<%= expresie %>" />

De exemplu,
<jsp:forward page="/servlet/login" />

Aceast aciune trimite mai departe obiectul request de la fiierul JSP spre locul specificat, iar JSP-Engine nu mai proceseaz restul paginii JSP. nainte de forward, este golit buffer-ul obiectului out. Pentru a exemplifica utilizarea forward, s relum exemplul de la directiva include (8.3.2.2). n locul directivei include, vom specifica aciunea forward. Noul fiier va fi cel din programul:
<html><head><title>Test include</title></head> <body bgcolor="white"><font color="blue"> Data si ora curenta este: <jsp:forward page="data.jsp" /> </font></body></html> Programul 8.14. principalf.jsp

n urma apelului, pe navigator va aprea doar data i ora, linia care precede apelul aciunii forward va disprea, aa cum se vede n figura de mai jos.

430

Figura 8.9. Data i ora prin forward

8.4. Utilizarea bean-urilor n pagini JSP


API JavaBeans permite scrierea de componente n Java. O component este o unitate software self contained reutilizabil, care poate fi manevrat vizual cu ajutorul unor instrumente specializate. Aceste componente (Java) se numesc bean-uri. Astfel de tratri de componente se ntlnesc la Delphi i Visual Basic. Bean-urile Java sunt, n prezent, utilizate n trei contexte: 1. Componente vizuale Sunt utilizate pentru simplificarea elaborrii de GUI n special pentru partea de client. Ele sunt manevrate mai ales prin intermediul unor pachete, de tip BeanBuilder, care asist utilizatorul n crearea, testarea i utilizarea acestor componente. 2. Componente de tip EJB (Enterprise Java Beans) Sunt proiectate pentru partea de bussines a aplicaiilor distribuite. Pe durata vieii lor sunt gestionate de ctre containerele (serverele) EJB. 3. Componente utilizate n pagini JSP Sunt destinate n principal simplificrii codificrii unor aplicaii bazate pe JSP. Despre acestea din urm vom vorbi n cele ce urmeaz. Simplu vorbind, un bean utilizat n pagini JSP trebuie s aib un constructor fr parametri, iar metodele lui, pe ct posibil - dar nu obligatoriu, s se refere la valori private accesate prin metodele getter i setter:
private tip nume; - - - - - - - - public tip getNume() {} public void setNume(tip st) {}

431

public boolean isNume() {...}

// numai pentru boolean

Utilizarea componentelor este extrem de benefic, deoarece permite exploatarea de clase reutilizabile fr a se pierde nimic din utilizarea convenional. n plus permite reutilizarea codului (el fiind inut n metodele clasei). Paginile JSP devin mai simple, deoarece nu se mai scrie codul unei operaii, ci doar apelul unei metode.

8.4.1. Aciunea useBean


8.4.1.1. Sintaxe i semnificaii useBean Aceast aciune permite ncrcarea unei componente JavaBean care urmeaz a fi utilizat n interiorul paginii JSP. Nu intenionm s prezentm dect cea mai simpl, i n acelai timp cea mai frecvent modalitate de utilizare a unei componente JavaBean. n forma cea mai simpl, specificarea aciunii useBean se face:
<jsp:useBean id="numeInstanta" scope="page|request|session|application" class="package.class" />

nelesul specificrii este: "instaniaz un obiect al clasei package.class leag-l de numeInstanta i utilizeaz-l ca un obiect obinuit". Persistena (durata de via a) obiectului este una dintre cele specificate prin scope, iar n absena acestuia obiectul triete ct pagina (page). Sau, n maniera Java, fr atributul scope, urmtoarele declaraii sunt echivalente:
<jsp:useBean id="numeInstanta" class="package.class" /> <% package.class numeInstanta = new package.class(); %>

Prin id="numeInstanta" se definete numele unei variabile care identific bean-ul. Acest nume reprezint bean-ul n expresiile i fragmentele de cod JSP. Referina la bean se poate face fie prin numeInstanta.metoda(), fie prin aciuni setProperty sau getProperty. Despre ultimele dou aciuni vom discuta n seciunile urmtoare. Durata de via a bean-ului se specific prin scope="page|request|session|application". Vizibilitatea implicit coincide cu pagina curent. Valoarea request permite ca vizibilitatea s fie prelungit i la pagina ctre care se face forward. Valoarea session permite utilizarea bean-ului de ctre toate paginile active n cadrul 432

sesiunii curente. Valoarea application permite comunicarea ntre pagini la nivel de container (Tomcat), cu asigurarea persistenei ntre apeluri. Prin class="package.class" se instaniaz un bean din pachetul package i clasa class. n mod obligatoriu bean-ul trebuie s fac parte dintr-un pachet explicit al crui nume este dat de package. Nu este admis apartenena bean-ului la pachetul implicit. Locul pachetului este subdirectorul cu numele indicat prin package din $WEBAPP_HOME/WEBINF/classes, iar numele clasei s fie cel indicat prin class. Clasa trebuie s satisfac condiiile de bean, adic (cerin minim) s aib un constructor fr parametri. Evident, de cele mai multe ori se dorete ca referina la un bean s fie de acelai tip cu bean-ul creat. Totui, uneori se dorete ca referina s aib ca i tip ori o superclas a bean-ului, ori o interfa pe care acesta o implementeaz. A doua form a lui useBean (i ultima pe care o prezentm) este:
<jsp:useBean id="numeInstanta" scope="page|request|session|application" class="package1.class1" type="package2.class2" />

Sau, cu alte cuvinte, n maniera Java, fr atributul scope, urmtoarele declaraii sunt echivalente:
<jsp:useBean id="numeInstanta" class="package1.class1" type="package2.class2"/> <% package2.class2 numeInstanta = new package1.class1(); %>

Crearea condiionat a unui bean n anumite situaii, utilizatorul trebuie s aib n vedere o tratare difereniat a lui useBean dac acesta a fost sau nu deja creat. Dac useBean constat c bean-ul cu acelai id i cu acelai scope este deja creat, se face controlul de tip asupra clasei. n mod normal, referina id va repera bean-ul deja creat. n caz de ilegalitate (clasa nu coincide cu cea veche sau s-a folosit type ntr-un mod ilegal), se arunc ClassCastException. n aceste condiii, este posibil s se doreasc executarea unor anumite aciuni numai n cazul crerii bean-ului nu i n cazul de useBean pe un bean deja creat. Pentru aceast situaie, n loc de:
<jsp:useBean - - - />

se va folosi construcia:
<jsp:useBean - - - >

433

instructiuni de executat doar la crearea bean-ului </jsp:useBean>

8.4.1.2. Un exemplu de bean Vom construi un bean care ntreine informaii despre un student i le actualizeaz de cte ori este nevoie. Pentru a acoperi cele dou forme ale lui useBean prezentate mai sus, am definit i o interfa pe care acest bean s o implementeze. Sursa bean-ului Student este prezentat n programul 8.15.
package stud; public class Student implements Identitate { private String nume="", matricol="", venit="", medie="", bursa=""; public Student() { } // Student.Student public public public public public String String String String String getNume() {return nume;} getMatricol() {return matricol;} getVenit() {return venit;} getMedie() {return medie;} getBursa() {return bursa;}

public void setNume(String nume) { this.nume = nume; } // Student.setNume public void setMatricol(String matricol) { this.matricol = matricol; } // Student.setMatricol public void setVenit(String venit) { this.venit = venit; puneBursa(); } // Student.setVenit public void setMedie(String medie) { this.medie = medie; puneBursa(); } // Student.setMedie private void puneBursa() { float medie; int venit; if ((this.medie.length()==0)||(this.venit.length()==0)) return; try { medie = Float.parseFloat(this.medie);

434

venit = Integer.parseInt(this.venit); // Criterii de acordare a burselor if ((medie >9.00)&&(venit<2000000)) bursa = "1500000"; else if ((medie >8.00)&&(venit<1500000)) bursa = "1000000"; else if ((medie >7.00)&&(venit<1000000)) bursa = "500000"; } // try catch (Exception e) { e.printStackTrace(); } // catch } // Student.puneBursa } // Student Programul 8.15. Student.java

Trebuie remarcat faptul c dei bean-ul stud.Student are cinci cmpuri, numai primele patru au metode setter. Cmpul bursa este actualizat automat de bean atunci cnd se actualizeaz venit sau media. Bean-ul stud.Student poate fi privit i de sine stttor, fr obligaia de a implementa interfaa stud.Identitate. n majoritatea cazurilor, beanurile JSP NU implementeaz interfee. (n schimb, bean-urile EJB ntotdeauna implementeaz interfee). Noi am definit interfaa doar cu scop didactic. Sursa acestei interfee este:
package stud; public interface Identitate { public public public public } // Identitate Programul 8.16. Identitate.java String getNume(); String getMatricol(); void setNume(String nume); void setMatricol(String matricol);

Fiierul Student.class (ca i Identitate.class dac se dorete) se depune (depun) n directorul:


$WEBAPP_NAME/WEB_INF/classes/stud/

pentru a respecta specificarea apartenenei la pachetul stud. Un posibil fiier de apel, la care ne vom referi i n seciunile viitoare, este dat n programul 8.17. 435

<html><head><title>Test usebean</title></head><body> <jsp:useBean id="student" class="stud.Student" /> <jsp:setProperty name="student" property="venit" value="1000" /> <%student.setMedie("9.50"); %> Venitul: <%=student.getVenit()%>. Medie: <jsp:getProperty name="student" property="medie" />. Bursa: <jsp:getProperty name="student" property="bursa" />. <jsp:useBean id="identitate" class="stud.Student" type="stud.Identitate"/> <jsp:setProperty name="identitate" property="nume" value="Ion Popescu Gopo" /> <jsp:setProperty name="identitate" property="matricol" value="75069" /> Numele: <%=identitate.getNume()%>. Matricol: <jsp:getProperty name="identitate" property="matricol"/>. </body></html> Programul 8.17. student.jsp

Efectul execuiei acestui fiier JSP este prezentat n fig. 8.10.

Figura 8.10. Informaii despre student

Primul useBean definete o referin la bean-ul Student. Se pot observa, de asemenea, utilizrile acestuia din construcii <% - - -%>. Al doilea useBean definete o referin la o instaniere a unui obiect creat din interfaa Identidate, implementat de bean-ul Student. i aici apar construcii <% - - -%> care utilizeaz referine la bean. Ct privete aciunile setProperty i getProperty, le prezentm n seciunile care urmeaz.

436

8.4.1.3. Aciunea getProperty Aceast aciune extrage valoarea unei proprieti din bean, o convertete la String i o depune n pagina rezultat (n obiectul out). Conversia la String este realizat implicit pentru tipurile de date char, byte, boolean, int, long, float, double. Sintaxa de apel a aciunii getProperty este:
<jsp:getProperty name="numeInstantaBean" property="numeProprietate" />

Evident, este necesar instanierea sau crearea prealabil a bean-ului prin tag-ul useBean. De exemplu, pentru bean-ul din seciunea precedent avem:
<jsp:getProperty name="student" property="bursa" /> - - <jsp:getProperty name="identitate" property="matricol"/>.

Acelai efect se obine dac n loc de <jsp:getproperty - - /> se folosete:


<% - - - numeInstantaBean.getNumeProprietate() - - - %>

aa cum se poate vedea n acelai exemplu din seciunea precedent. 8.4.1.4. Aciunea setProperty Efectul unei aciuni JSP este acela de a modifica valorile unora dintre proprietile unui bean specificat prin useBean. Dup cum se va vedea, prin setProperty se realizeaz mult mai uor modificarea unor proprieti dect prin specificaii de forma:
<% - - - numeBean.setNumeProprietate(valoareProprietate) - - - %>

Specificarea unei aciuni setProperty se poate face n cinci feluri, aa cum se poate vedea din sintaxa construciei:
<jsp:setProperty name="numeInstantaBean" property="numeProprietate" value="string" property="numeProprietate" value="<%= expresie %>" property="*" property="numeProprietate" property="numeProprietate" param="numeParametru" /> { | | | | | }

437

Prin name="numeInstantaBean" se denumete instana unui bean creat sau localizat anterior prin tag-ul useBean. Fixarea valorilor pentru proprietile bean-ului se poate face n mai multe moduri: Prin setarea explicit a valorii unei proprieti a bean-ului, valoare dat printr-un string sau printr-o expresie JSP (primele dou construcii property= ...). Prin transmiterea tuturor valorilor parametrilor din obiectul request care se potrivesc proprietilor bean-ului (construcia property="*"). Prin transmiterea valorii unui anumit parametru din obiectul request spre o anumit proprietate din bean, cu acelai nume sau cu nume diferit (ultimele dou construcii property= ...). Detaliem n continuare aceste fixri de valori. Toate exemplificrile le vom face pe bean-ul Student prezentat ntr-o seciune precedent i la fiierul student.jsp prezentat tot acolo. Prin
property="numeProprietate" value="string" property="numeProprietate" value="<%= expresie %>"

se atribuie proprietii numeProprietate din bean, dup caz, fie valoarea string fie valoarea rezultat din evaluarea expresie. De exemplu, urmtoarele aciuni sunt de acest fel:
<jsp:setProperty name="student" property="venit" value="1000" /> <jsp:setProperty name="identitate" property="nume" value="Ion Popescu Gopo"/> <jsp:setProperty name="identitate" property="matricol" value="75069" />

De asemenea, urmtoarea construcie (iertai semantica fr sens a ei):


<jsp:setProperty name="identitate" property="nume" value="<%=student.getMedie()%>" />

Prin
property="*"

se preia din obiectul request valorile tuturor parametrilor care se potrivesc bean-ului i se transmit metodelor setter ale bean-ului. De regul, obiectul request provine dintr-un formular HTML ale crui cmpuri au nite nume. Aceleai nume trebuie s le aib (unele dintre) proprietile bean-ului. n momentul setrii, fiecare valoare este convertit de la String la tipul 438

proprietii din bean. Este posibil setarea i a unor proprieti indexate, exact aa cum se fixeaz valorile unui tablou. Parametrii null din request nu sunt setai. De exemplu, dac utilizatorul lanseaz o cerere de forma:
http://masina:8080/pdpj/student.jsp?nume=Vasile&medie= 5.00&matricol=55448

i dac n fiierul student.jsp este o construcie de forma:


<jsp:setProperty name="student" property="*" />

atunci cmpurile nume, matricol, medie vor fi setate la Vasile, 55448, 5.00, iar celelalte cmpuri vor rmne neschimbate. Prin
property="numeProprietate"

Se extrage din obiectul request parametrul cu numele numeProprietate i valoarea lui se atribuie proprietii numeProprietate din bean. De exemplu, n urma cererii de mai sus se poate specifica doar:
<jsp:setProperty name="student" property="medie" />

ceea ce va modifica doar proprietatea medie din bean. Prin


property="numeProprietate" param="numeParametru"

se extrage din obiectul request parametrul cu numele numeParametru i valoarea lui se atribuie proprietii numeProprietate din bean. Acest gen de setri este util atunci cnd numele cmpurilor din cerere difer de numele cmpurilor din bean. De exemplu (iari o setare fr sens) este posibil ca la cererea precedent s se specifice:
<jsp:setProperty name="student" property="venit" param="matricol"/>

n urma creia proprietatea venit din bean este setat la valoarea numrului matricol sosit prin cerere! Aa cum am artat la aciunea useBean, este posibil ca s se cear aciuni explicite doar pentru cazul instanierii unui bean. De cele mai multe ori, instruciunile din interiorul tag-ului useBean sunt aciuni setProperty de atribuire, sub forma:
<jsp:useBean id="numeBean" ... > - - <jsp:setProperty name="numeBean" property= ... />

- - -

439

</jsp:useBean>

Reamintim c, n acest caz, setarea de valori iniiale este executat numai dac este vorba de o nou instaniere a bean-ului, NU i de localizarea unuia existent. Reamintim, de asemenea, c cele mai multe setri de proprieti se fac n afara tag-ului useBean.

8.4.2. Un exemplu: aplicaia Note n varianta JSP


Aplicaia Note a fost descris mai nti n capitolul de RMI (5.5). Apoi o variant simplificat a ei, dar cu pstrarea funcionalitii a fost descris n capitolul despre servlet-uri (7.3.2). Aceasta este cea de-a treia (i ultima) variant, folosind tehnologia JSP. 8.4.2.1. Particulariti ale implementrii JSP Funcionalitile oferite de ctre implementarea JSP sunt, practic, identice cu cele oferite de ctre implementarea servlet. Practic apare o singur deosebire din punctul de vedere al arhitecturii aplicaiei. n implementarea servlet componenta server Student nu are acces direct la baza de date. Pentru aceste accese server-ul apeleaz la serviciile server-ului Profesor. n implementarea JSP att componenta server Student ct i componenta server Profesor acceseaz baza de date pentru scopurile proprii. Decizia ca fiecare s i acceseze pentru el baza de date a fost luat din dou motive. n primul rnd apelul de la student la profesor se putea face numai prin URLConnection, deci se reproducea, practic, ceea ce am prezentat la servlet. n al doilea rnd, dup cum se poate vedea foarte uor, descrierile fiierelor *.jsp sunt (foarte) mult mai simple. Pentru accesul la baza de date, varianta JSP folosete drept bean clasa NoteAccessDB, descris n 7.3.2.1. Pentru a putea fi accesat ca i bean, este obligatoriu s fac parte dintr-un pachet. Drept urmare am recompilat sursa specificnd n prima linie c ea face parte din pachetul db (package db;). Dup compilare, fiierul NoteAccessDB.class a fost depus n directorul
$WEBAPP_NAME/WEB-INF/classes/db

Acelai tratament l-am aplicat i claselor AuthFTP i NivelJDBC, pe care le-am recompilat pentru a face parte din acelai pachet db. Am depus, evident, fiierele AuthFTP.class i NivelJDBC.class n acelai loc. Implementarea s-a realizat prin numai dou fiiere: NoteStudent.jsp i NoteProfesor.jsp. 440

8.4.2.2. NoteStudent.jsp Att partea de client, ct i partea de server necesare accesului studenilor este descris n acelai fiier jsp. Interfaa oferit utilizatorului este cea din fig. 8.11. Studentul i completeaz numele (de user) i parola, iar dup autentificare i sunt afiate notele la toate materiile.

Figura 8.11. Interfaa pentru student

Textul surs al fiierului NoteStudent.jsp este prezentat n programul 8.18.


<html><head><title>Student</title></head><body> <%! String resMaterii="", resNote="", resStudent="", resParola="", student, parola; %> <jsp:useBean id="adb" class="db.NoteAccessDB" /> <% if (request.getParameter("buton") != null) {// Cererea vine de la acest // fisier jsp student = request.getParameter("student"); parola = request.getParameter("parola");

441

if (!db.AuthFTP.isFTPUser("localhost", student, parola)) { resStudent = "ERR: student,parola"; } // Eroare de autentificare else { // Citire materii-note student = adb.getMaterieNota( request.getParameter("student")); resMaterii = student.substring(0, student.indexOf("\t")); resNote = student.substring(student.indexOf("\t")+1); resStudent = "OK citire"; resParola = ""; } // Terminat citire materii-note } //Terminat cererea din prezentul jsp %> <form method="post" action="NoteStudent.jsp"> <table border="0"> <tr> <td><center>Materie</center></td> <td><center>Nota</center></td> </tr><tr> <td><textarea name="materii" rows="10" cols="10"><%=resMaterii%></textarea></td> <td><textarea name="note" rows="10" cols="10"><%=resNote%></textarea></td> </tr><tr> <td align="right">Student:</td> <td><input type="text" name="student" size="13" value="<%=resStudent%>"></td> </tr><tr> <td align="right">Parola:</td> <td><input type="password" name="parola" size="13" value="<%=resParola%>"></td> </tr><tr> <td><input type="submit" name="buton" value="Citeste"></td> <td></td> </tr> </table></form></body></html> Programul 8.18. NoteStudent.jsp

Sursa are practic trei pri distincte. n prima parte este declarat antetul HTML, sunt declarate cteva stringuri ce vor fi folosite n script-urile JSP dup care este declarat folosirea beanului db.NoteAccessDB. Partea a treia (a doua o prezentm imediat) este un formular HTML care trimite cererea prin metoda POST i care apeleaz pentru aciune nsui fiierul NoteStudent.jsp. Corpul formularului este un tabel HTML. Pentru patru dintre celule am specificat prin expresii JSP c valorile lor vor fi preluate din string-urile definite n prima parte. Este de asemenea important de remarcat 442

faptul c am asociat butonului (de submit) "Citeste" numele de parametru "buton", al crui rol se va vedea n partea a doua. Partea a doua este un fragment de cod JSP destinat rezolvrii cererii. Aciunea fragmentului care rezolv efectiv cererea este condiionat de faptul c n cerere se afl parametrul numit "buton" (vezi instruciunea if care "mbrac" secvena). Acest parametru apare numai dup ce a fost apsat butonul "Citeste", deci dup ce s-a lansat efectiv o cerere. Absena acestei condiionri ar conduce la "NullPointerException", deoarece la ncrcarea iniial a paginii nici unul dintre cmpurile cererii nu ar fi definit! Tratarea cererii ncepe cu autentificarea studentului. n caz de eec n celula "Student" va apare un mesaj de eroare. Dup autentificarea cu succes, se cer din baza de date materiile i notele studentului respectiv care se afieaz pe interfa (atribuind valorile corespunztoare string-urilor de unde se "alimenteaz" interfaa).

Figura 8.12. Interfaa pentru profesor

443

8.4.2.3. NoteProfesor.jsp Att partea de client, ct i partea de server necesare accesului profesorilor este descris n acelai fiier JSP. Interfaa oferit utilizatorului este cea din fig. 8.12. Profesorul i completeaz numele (de user), parola i materia pentru care dorete s opereze. Dup autentificare i dup controlul corespondenei (materie,profesor), sunt afiate notele tuturor studenilor la materia respectiv. Textul surs al fiierului NoteProfesor.jsp este dat n programul 8.19.
<html><head><title>Profesor</title></head><body> <%@ page import="java.util.*" %> <%! String resStudenti="", resNote="", resProfesor="", resParola="", resMaterie="", profesor, parola, materie; %> <jsp:useBean id="adb" class="db.NoteAccessDB" /> <% if (request.getParameter("buton") != null) { // Cererea vine de la acest // fisier jsp profesor = request.getParameter("profesor"); parola = request.getParameter("parola"); materie = request.getParameter("materie"); if ((!db.AuthFTP.isFTPUser("localhost", profesor, parola))|| (!adb.isMaterieProfesor(materie, profesor))) { resProfesor = "ERR: profesor,materie,parola"; } // Eroare de autentificare else if (request.getParameter("buton").equals("Citeste")) { // Citire studenti-note profesor = adb.getStudentNota( request.getParameter("materie")); resStudenti = profesor.substring(0, profesor.indexOf("\t")); resNote = profesor.substring(profesor.indexOf("\t")+1); resProfesor = "OK citire"; resParola = ""; } // Terminat citire studenti-note else if (request.getParameter("buton").equals("Scrie")) { // Scriere studenti-note StringTokenizer stp = new StringTokenizer( request.getParameter("studenti"), "\r\n\t"); StringTokenizer std = new StringTokenizer( request.getParameter("note"), "\r\n\t"); int n = stp.countTokens(); int i = std.countTokens(); n = (n > i) ? i : n;

444

profesor = profesor+"\t"+parola+"\t"+materie; for (i=0; i<n; i++) profesor += "\t"+stp.nextToken()+"\t"+std.nextToken(); adb.setStudentNota(profesor); resProfesor = "OK scriere"; resStudenti = ""; resNote = ""; resMaterie = ""; resParola = ""; } // Terminat tratarea scrierii student-note } // Terminat cererea din prezentul fisier jsp %> <form method="post" action="NoteProfesor.jsp"> <table border="0"> <tr> <td><center>Student</center></td> <td><center>Nota</center></td> </tr><tr> <td><textarea name="studenti" rows="10" cols="10"><%=resStudenti%></textarea></td> <td><textarea name="note" rows="10" cols="10"><%=resNote%></textarea></td> </tr><tr> <td align="right">Profesor:</td> <td><input type="text" name="profesor" size="13" value="<%=resProfesor%>"></td> </tr><tr> <td align="right">Parola:</td> <td><input type="password" name="parola" size="13" value="<%=resParola%>"></td> </tr><tr> <td align="right">Materie:</td> <td><input type="text" name="materie" size="13" value="<%=resMaterie%>"></td> </tr><tr> <td><input type="submit" name="buton" value="Citeste"></td> <td align="right"><input type="submit" name="buton" value="Scrie"></td> </tr> </table></form></body></html> Programul 8.19. NoteProfesor.jsp

La fel ca i pentru accesul studenilor, sursa are trei pri distincte. n prima parte este declarat antetul HTML, se declar folosirea pachetului java.util (pentru StringTokenizer), sunt declarate cteva stringuri ce vor fi folosite n script-urile JSP dup care este declarat folosirea beanului db.NoteAccessDB.

445

Partea a treia (a doua o prezentm imediat) este un formular HTML care trimite cererea prin metoda POST i care apeleaz pentru aciune nsui fiierul NoteProfesor.jsp. Corpul formularului este un tabel HTML. Pentru cinci dintre celule am specificat prin expresii JSP c valorile lor vor fi preluate din string-urile definite n prima parte. Este de asemenea important de remarcat faptul c am asociat ambelor butoane de submit un acelai nume de parametru: "buton". Evident ele se difereniaz prin valoarea lor, "Citeste" sau "Scrie". Partea a doua este un fragment de cod JSP destinat rezolvrii cererii. Aciunea fragmentului care rezolv efectiv cererea este condiionat de faptul c n cerere se afl parametrul numit "buton" (vezi instruciunea if care "mbrac" secvena). Acest parametru apare numai dup ce a fost apsat unul dintre butoanele "Citeste" sau "Scrie", deci dup ce s-a lansat efectiv o cerere. Absena acestei condiionri ar conduce la "NullPointerException", deoarece la ncrcarea iniial a paginii nici unul dintre cmpurile cererii nu ar fi definit! Tratarea cererii ncepe cu autentificarea profesorului i controlul corespondenei materie - profesor. n caz de eec n celula "Profesor" va apare un mesaj de eroare. Dup autentificarea cu succes, secvena de cod decide dac trebuie s rspund la o citire sau la o scriere. Dup caz, ori se cer din baza de date studenii i notele la materia respectiv i se afieaz pe interfa, ori se transmit bazei de date perechile student-not care trebuie actualizate pentru materia respectiv.

8.5. Extinderea JSP prin tag-uri utilizator


Prin intermediul bean-urilor se poate separa partea de prezentare dintr-un document JSP de partea lui de business (codul Java). n anumite situaii accesul la bean prin getProperty i setProperty nu este suficient. Este necesar scrierea de fragmente de cod pentru realizarea de sarcini mai speciale. Aceste fragmente de cod ngreuneaz ntr-o oarecare msur portabilitatea paginilor JSP i le fac mai dependente de codul Java. Mecanismul definirilor de tag-uri JSP vine s compenseze ntr-o oarecare msur acest neajuns. S-a vorbit, i se mai vorbete nc, de faptul c definirea de tag-uri este o alternativ la folosirea bean-urilor. (n traducerea [40] se folosete termenul de etichet n loc de tag; noi l preferm pe acesta din urm). Prerea noastr este c fiecare dintre cele dou concepte i are propriul loc n cadrul tehnologiei JSP. Mai mult, folosirea lor combinat permite ca 446

partea de prezentare s nu conin practic deloc cod Java prin expresii, fragmente de cod, declaraii etc.

8.5.1. API i posibiliti de construcie a unor tag-uri noi


8.5.1.1. Tag-uri utilizator i locuri din context cu informaii despre ele Din punct de vedere formal, un tag utilizator (custom tag) este o construcie de forma:
<prefixTag:numeTag [ atribute ] > corpTag </prefixTag:numeTag>

n conformitate cu standardul XML, dac tag-ul nu are corpTag atunci el se poate specifica prin:
<prefixTag:numeTag [ atribute ] />

La baza funcionrii unui tag utilizator st un bean ce conine metode de tratare a tag-ului de nceput, a atributelor, a corpului tag-ului i a tag-ului de sfrit. Pentru a se putea defini i utiliza un tag utilizator, contextul aplicaiei ($WEBAPP_NAME) conine o structur de date cu informaii n urmtoarele patru locuri: 1. n fiierul (fiierele) JSP aflat n $WEBAPP_NAME/, se declar, prin <%@ taglib, prefixTag i numeTag pentru fiecre tag utilizator folosit n pagin. n fiierul descriptor al aplicaiei:
$WEBAPP_NAME/WEB_INF/web.xml,

2.

unde se specific, pentru fiecare tag declarat la punctul 1, numeTag i locaia unde este descris formal tag-ul respectiv. 3. n directorul
$WEBAPP_NAME/WEB_INF/

trebuie s se afle fiierul (fiierele) de tip .tld ce descriu formal tag-urile utilizator (de care am amintit la poziia 2). 4. n unul sau mai multe subdirectoare ale directorului
$WEBAPP_NAME/WEB_INF/classes/

447

trebuie s se afle, pentru fiecare tag, cte un fiier de tip .class (bean-ul) care descrie toate funcionalitile tag-ului utilizator respectiv. 8.5.1.2. Declarare i descriere formal Fiecare tag utilizator ce urmeaz a fi folosit ntr-o pagin JSP trebuie mai nti s fie declarat n acea pagin. Declararea se face n pagina JSP prin:
<%@ taglib uri="numeTag" prefix="prefixTag" %>

String-ul prefixTag este folosit doar n pagina JSP, pentru a identifica tag-urile utilizator. String-ul numeTag este folosit pentru identificarea descrierii formale a tag-ului. Descrierea formal a unui tag utilizator se face ntr-un fiier de tip .tld, numit i bibliotec de tag--uri (taglib). ntr-un astfel de fiier sunt descrise formal, n format XML, unul sau mai multe tag-uri. Principalele informaii formale despre un tag (specificate n <tag>) sunt: numele tag-ului (<name>); pachetul i clasa Java care descrie funcionalitile tag-ului (<tagclass>); fiecare dintre atributele care pot s apar n tag (<attribute><name>), mpreun cu precizarea c atributul este obligatoriu sau nu (<attribute><required>). Fiierul web.xml (deployment descriptor) al aplicaiei face legtura ntre descrierea formal i declararea tag-ului prin taglib n pagina JSP. n acest fiier se specific, dup tag-urile <servlet>, informaiile: numeTag (URI) al tag-ului respectiv (<taglib-uri>); locul n context unde se afl fiierul .tdl ce descrie formal tag-ul (<taglib-location>). 8.5.1.3. Descrierea funcionrii unui tag folosind un bean API oferit pentru descrierea funcionalitilor unui tag se gsesc n pachetul javax.servlet.tagext. Principalele clase i interfee din acest pachet, precum i descendenele dintre ele sunt:
public interface Tag - - pulic class TagSupport implements Tag - - public interface BodyTag extends tag - - -

448

public class BodyTagSupport extends TagSupport implements BodyTag - - -

Dac utilizatorul dorete s trateze numai tag-ul de nceput sau de sfrit i s ignore tratarea corpului tag-ului, atunci bean-ul tag-ului va implementa/ extinde Tag sau TagSupport (care are funcionaliti n plus). Dac se dorete inclusiv tratarea corpului tag-ului, atunci bean-ul tagului va implementa/extinde BodyTag sau BodyTagSupport. n codul bean-ului care deservete tag-ul pot s apar urmtoarele metode, care eventual suprascriu metodele omonime din clasa printe: 1. metode setNume pentru fiecare atribut (numit nume) ce poate s apar n tag; 2. metoda doStartTag; 3. metodadoInitBody; 4. metoda doAfterBody; 5. metoda doEndBody; 6. metoda release.

Ordinea de evaluare de ctre container a acestor metode coincide cu ordinea scris mai sus. n cazul n care unele dintre metode nu sunt rescrise, containerul le apeleaz pe cele din clasa printe. S lum pe rnd aceste metode. 1. Fiecare atribut din tag are un nume i poate avea ca valoare un string. Dac notm nume numele tag-ului, atunci trebuie declarat n codul bean-ului:
private String nume; - - - public void setNume(String nume) { this.nume = nume; } - - -

Dac n tag apare atributul respectiv, atunci containerul apeleaz automat aceast metod i d proprietii nume din bean valoarea specificat n tag. 2. La ntlnirea tag-ului de nceput, se apeleaz metoda doStartTag. n cadrul ei se pot face o serie de iniializri necesare tratrii tag-ului. La momentul execuiei ei, atributele tag-ului sunt deja depuse n bean, conform punctului precedent. Metoda se ncheie prin ntoarcerea unei valori ntregi dintr-un set de valori predefinite (descrise n [91] varianta Enterprise Edition). Cele mai importante valori ntoarse sunt: 449

EVAL_BODY_INCLUDE, dac nu se se dorete prelucrarea corpului de ctre bean, ci depunerea lui, n mod automat de ctre container, n obiectul out al paginii JSP. EVAL_BODY_BUFFERED, dac se dorete prelucrarea corpului de ctre bean. n acest caz acest corp se reine ntr-un obiect BodyContent de unde poate fi prelucrat prin doAfterBody. SKIP_BODY dac se dorete ignorarea complet a corpului tag-ului. 3. Metoda doInitBody acioneaz imediat dup doStartTag i permite efectuarea unor iniializri nainte de prelucrarea corpului tagului. De menionat c metoda dispune deja de un obiect BodyContent creat. Metoda doAfterBody este folosit pentru preluarea corpului tag-ului n vederea prelucrrii lui. n acest scop ea obine mai nti corpul tagului prin getBodyContent. De asemenea, poate obine obiectul JspWriter prin getPreviousOut, prin intermediul cruia trimite rspunsul prelucrrii. n ceea ce privesc modalitile de prelucrare a corpului, acestea pot varia de la prelucrri simple de tipul celei ce o vom da ca exemplu ntr-o seciune viitoare i pn la prelucrri deosebit de complexe. Astfel, dac corpul unui tag poate conine n interiorul lui alte structuri (tag--uri imbricate) XML, atunci prelucrarea poate folosi un parser XML ca i SAX sau DOM. n [40] sunt prezentate astfel de exemple. Uneori este posibil trecerea de mai multe ori prin corpul unui tag (tag-uri iterative), iar prelucrarea trebuie s tie, n orice moment la a cta iteraie se afl. Metoda poate ntoarce, printre altele, valorile EVAL_BODY_AGAIN pentru reevaluarea corpului sau SKIP_BODY pentru terminarea evalurii. Metoda doEndTag este invocat la ntlnirea tag-ului de sfrit. n interiorul ei se pot efectua o serie de prelucrri specifice sfritului de tag. Rezultatul ntors de ea poate fi: EVAL_PAGE pentru continuarea prelucrrii paginii, sau SKIP_PAGE pentru abandonarea prelucrrii. 6. Metoda release are drept scop eliberarea referinelor ctre obiectele folosite. Dei nu este obligatorie, se recomand folosirea ei.

4.

5.

450

8.5.2. Exemplu: tag-urile Semnat i Ordonat


n cele ce urmeaz vom defini dou tag-uri: Semnat, adaptat dup un exemplu foarte simplu preluat din [51] i Ordonat. Ambele tag-uri vor fi folosite cu prefixul utile. Prin intermediul acestora vom ilustra esena mecanismului de definire a noi tag-uri JSP i de utilizare a lor. 8.5.2.1. Definirea tag-urilor Semnat i Ordonat Tag-ul Semnat apare sub forma:
<utile:Semnat/>

care plasat ntr-o pagin JSP, trebuie s afieze numele mainii server i ora exact (server) a momentului afirii. Este, dac vrei, o alt variant de implementare a funciei semnaturaTemporala (programul 4.1). Evident, el mai poate fi scris i sub forma:
<utile:Semnat></utile:Semnat>

n sfrit, dac ntre tag-urile de nceput i de sfrit de mai sus se scrie un text pe post de corp, acesta va fi ignorat. Tag-ul Ordonat are sintaxa (XML):
<utile:Ordonat [ tip="fifo|linii|cuvinte" ]? > Linii text </utile:Ordonat>

Cu alte cuvinte, tag-ul de nceput poate s aib atributul tip, care la rndul lui poate avea una dintre valorile fifo, linii sau cuvinte. Tag-ul este opional ( [ ... ]? nseamna n XML apariia cel mult o dat). n absena atributului, valoarea considerat este fifo. Aciunea tag-ului depinde de valoarea atributului tip. n cazul tip="fifo" liniile sunt afiate ntr-o list HTML n ordinea scrierii lor. n cazul tip="linii" lista HTML conine liniile corpului n ordine alfabetic. n cazul tip="cuvinte" lista HTML conine cuvintele corpului ordonate alfabetic. Pentru orice alte valori ale lui tip, liniile corpului sunt ignorate, n schimb se afieaz un mesaj de eroare. n continuare vom prezenta aciunile i sursele necesare implementrii tag-urilor n ordinea invers a celei expuse n 8.5.1.1. Deci vom prezenta mai nti bean-urile Java, apoi descrierile formale, nregistrrile n web.xml i la urm o pagin JSP de test.

451

8.5.2.2. Definirea claselor tag-urilor Ambele clase bean ale tag-urilor sunt nregistrate n pachetul tag. Pentru tag-ul Semnat am elaborat proiectat clasa Semnatura, iar pentru tag-ul Ordonat am elaborat clasa OrdonareDeStringuri. Codul clasei Semnatura este prezentat n programul 8.20.
package tag; import import import import java.net.*; java.util.*; javax.servlet.jsp.*; javax.servlet.jsp.tagext.*;

public class Semnatura extends TagSupport { public int doEndTag() throws JspException { try { JspWriter out = pageContext.getOut(); out.println( (InetAddress.getLocalHost()).getCanonicalHostName()+ " "+new Date()); } // try catch(Exception e) { e.printStackTrace(); } // catch return EVAL_PAGE; } // Semnatura.doEndTag } // Semnatura Programul 8.20. Semnatura.java

n implementare am suprascris numai metoda doEndTag, care intr n aciune la ntlnirea sfritului corpului tag-ului. Restul aciunilor (descrise n 8.5.1.3) sunt efectuate de ctre clasa printe, TagSuport. Bean-ul corespunztor tag-ului Ordonat este clasa OrdonareDeStringuri, prezentat n programul 8.21.
package tag; import import import import java.net.*; java.util.*; javax.servlet.jsp.*; javax.servlet.jsp.tagext.*;

public class OrdonareDeStringuri extends BodyTagSupport { private String tip = "fifo";

452

public OrdonareDeStringuri() { } public void setTip(String tip) { this.tip = tip; } // OrdonareDeStringuri.setTip public int doStartTag() throws JspException { return EVAL_BODY_BUFFERED; } // OrdonareDeStringuri.doStartTag public int doAfterBody() throws JspException { StringTokenizer st = null; int i, j, n; String t; String[] ts; BodyContent bc = getBodyContent(); JspWriter out = getPreviousOut(); try { if (tip.equalsIgnoreCase("cuvinte")) st = new StringTokenizer(bc.getString(),"\n\r\t "); else if ((tip.equalsIgnoreCase("linii"))|| (tip.equalsIgnoreCase("fifo"))) st = new StringTokenizer(bc.getString(),"\n\r"); else st = new StringTokenizer("EROARE: atributul <b>tip=\""+ tip+"\"</b> este incorect!", "\n"); n = st.countTokens(); ts = new String[n]; for (i=0; i<n; i++) ts[i] = (st.nextToken()).trim(); if (!tip.equalsIgnoreCase("fifo")) for(i=0; i<n-1; i++) for (j=i+1; j<n; j++) if (ts[i].compareTo(ts[j]) > 0) { t = ts[i]; ts[i] = ts[j]; ts[j] = t; } // if, for, for for (i=0; i<n; i++) if (ts[i].length() > 0) out.println("<li> "+ts[i]+" </li>"); } // try catch(Exception e) { e.printStackTrace(); } // catch return SKIP_BODY; } // OrdonareDeStringuri.doAfterBody public void release() { tip = null;

453

super.release(); } // OrdonareDeStringuri.release } // OrdonareDeStringuri Programul 8.21. OrdonareDeStringuri.java

String-ul tip va conine valoarea curent a atributului tip din cadrul tag-ului. Iniializarea cu valoarea fifo asigur valoarea implicit a atributului. Metoda setTip va fi folosit de container la ncrcarea tag-ului de nceput pentru fixarea valorii atributului tip. Metoda doStartTag are doar rolul de a semnala faptul c corpul tagului urmeaz s fie prelucrat n cadrul bean-ului. Semnalarea este realizat prin ntoarcerea valorii EVAL_BODY_BUFFERED. Partea esenial a bean-ului este rescrierea metodei doAfterBody. Mai nti, metoda i obine obiectul corp al tag-ului i obiectul out pentru scrierea rezultatelor. Apoi, n funcie de valoarea curent a atributului tip, selecteaz ntr-un obiect StringTokenizer fie liniile corpului, fie cuvintele corpului, fie o linie cu mesaj de eroare. n continuare, din obiectul StringTokenizer se creeaz un tablou de string-uri. n final, string-urile nevide din tabloul de string-uri sunt depuse n obiectul out. Metoda ntoarce SKIP_BODY, ceea ce nseamn abandonarea corpului tag-ului. n final am rescris i metoda release. 8.5.2.3. Definirea formal a bibliotecii de tag-uri Fiierul descriptor al bibliotecii de tag-uri utiletaglib.tld i este prezentat n programul 8.22. l-am numit

<?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"> <taglib> <tlib-version>1.0</tlib-version> <jsp-version>1.2</jsp-version> <short-name/> <tag> <name>Semnat</name> <tag-class>tag.Semnatura</tag-class> </tag> <tag> <name>Ordonat</name> <tag-class>tag.OrdonareDeStringuri</tag-class> <attribute> <name>tip</name>

454

<required>false</required> </attribute> </tag> </taglib> Programul 8.22. utiletaglib.tld

Acest fiier descrie pentru fiecare dintre cele dou tag-uri: numele tagului, pachetul i clasa care i implementeaz funcionalitatea. Pentru tag-ul al doilea se specific c este vorba de un atribut (<attribute>) numit (<name>) tip, a crui apariie este opional (<required>false). 8.5.2.4. Declararea tag-urilor n web.xml n fiierul web.xml care este Deployment Descriptor al aplicaiei, trebuie declarate noile tag-uri. Aceast descriere trebuie s apar dup descrierile <servlet>. Programul 8.23 prezint coninutul acestui fiier pentru aplicaia propus.
<?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> <taglib> <taglib-uri>/Semnat</taglib-uri> <taglib-location>/WEB-INF/utiletaglib.tld</taglib-location> </taglib> <taglib> <taglib-uri>/Ordonat</taglib-uri> <taglib-location>/WEB-INF/utiletaglib.tld</taglib-location> </taglib> </web-app> Programul 8.23. web.xml

8.5.2.5. O pagin de utilizare a tag-urilor Noile tag-uri pot fi folosite n orice pagin JSP a aplicaiei respective, cu condiia ca folosirea lor s fie precedat de declaraii <%@ taglib ... corespunztoare. Pentru exemplificare prezentm n programul 8.24 fiierul TestTag.jsp, ce conine mai multe exemple de folosire a celor dou tag-uri.

455

<html><head><title>Utilizare taguri definite</title></head><body> <%@ taglib uri="/Semnat" prefix="utile" %> <%@ taglib uri="/Ordonat" prefix="utile" %> <% java.util.Random r = new java.util.Random(); %> <b><i>Semnatura cu tag vid:</i></b> <utile:Semnat/> <table border="4"> <tr> <td> <h6>Liniile in ordinea sosirii (implicit)</h6> <ol type="1" start="1"> <utile:Ordonat>Prima linie Doua numere generate automat <% for (int i=0; i<2; i++) { %> <%=r.nextInt() %> <% } %> Penultima linie In sfarsit, ultima linie</utile:Ordonat> </ol> </td> <td> <h6>Liniile ordonate alfabetic</h6> <ol type="1" start="1"> <utile:Ordonat tip="linii">Prima linie Doua numere generate automat <% for (int i=0; i<2; i++) { %> <%=r.nextInt() %> <% } %> Penultima linie In sfarsit, ultima linie</utile:Ordonat> </ol> </td> </tr> <tr> <td> <h6>Cuvintele ordonate alfabetic</h6> <ol type="1" start="1"> <utile:Ordonat tip="cuvinte">Prima linie Doua numere generate automat <% for (int i=0; i<2; i++) { %> <%=r.nextInt() %> <% } %> Penultima linie In sfarsit, ultima linie</utile:Ordonat> </ol> </td> <td> <h6>Liniile nu se afiseaza</h6> <ol type="1" start="1"> <utile:Ordonat tip="alandala">Prima linie Doua numere generate automat

456

<% for (int i=0; i<2; i++) { %> <%=r.nextInt() %> <% } %> Penultima linie In sfarsit, ultima linie</utile:Ordonat> </ol> </td> </tr> </table> <b><i>Semnatura cu tag nevid:</i></b> <utile:Semnat>blablabla</utile:Semnat> </body></html> Programul 8.24. TestTag.jsp

Mai nti sunt prezentate cele dou declaraii taglib corespunztoare celor dou tag-uri. Se pornete apoi un obiect Random, deoarece unele dintre linii vor fi generate aleator. Urmeaz un prim test al tag-ului Semnat. ntr-un tablou de 2x2 sunt introduse patru tag-uri Ordonat. Cele patru corpuri ale lor difer doar prin cte dou linii care vor conine fiecare cte un numr ntreg generat aleator. Atributul tip nu este specificat n prima celul, este specificat cu valorile linii i cuvinte n urmtoarele dou celule, iar n ultima celul are o valoare nepermis. Fiierul JSP se ncheie cu un al doilea test al unui tag Semnat, numai c de aceast dat el este scris cu tag de nceput, corp i tag de sfrit. 8.5.2.6. Plasarea fiierelor n context i relaii ntre ele Dup ce toate fiierele de mai sus sunt gata, fiecare dintre ele trebuie plasat ntr-un anumit loc din contextul aplicaiei, aa cum am precizat mai sus. Pentru fixarea ideilor, am definit o aplicaie numit NewTagJsp. Deci contextul WEBAPP_NAME n cazul aplicaiei noastre este:
$CATALINA_HOME/webapps/NewTagJsp

Fiierele care trebuie plasate pentru exemplul nostru sunt:


Semnatura.class (n pachetul tag); OrdonareDeStringuri.class (n pachetul tag); utiletaglib.tld; web.xml; TestTag.jsp.

457

Aceste fiiere vor fi plasate n conformitate cu specificaiile absolute de mai jos:


$WEBAPP_NAME/WEB-INF/classes/tag/Semnatura.class; $WEBAPP_NAME/WEB-INF/classes/tag/OrdonareDeStringuri.class $WEBAPP_NAME/WEB-INF/utiletaglib.tld; $WEBAPP_NAME/WEB-INF/web.xml; $WEBAPP_NAME/TestTag.jsp.

n fig. 8.13 prezentm cteva corelaii ntre principalele informaii din fiierele de mai sus, relative la tag-ul Semnat.
TestTag.jsp --. . . /Semnat . . .utile . . . --. . . <utile:Semnat . . . ---

web.xml --. . . /Semnat . . . . . . /utiletaglib.tld . . . ---

utiletaglib.tdl --. . . Semnat . . . . . . tag.Semnatura . . . ---

Semnatura.class

Figura 8.13. Relaii ntre informaiile taglib

n esen, cnd se ncarc pagina JSP, containerul gsete declaraia taglib. El tie atunci c este vorba de definirea unui tag nou. n consecin, containerul consult mai nti web.xml unde gsete uriul /Semnat i fiierul tld care l definete. Containerul reine acesast informaie. 458

Dup aceea, caut n propria pagin tag-urile cu prefixul utile, indicat n declaraia taglib. Printre acestea le gsete pe cele cu uri-ul specificat. Pentru fiecare astfel de tag ntlnit, i aplic aciunea clasei Semnatura care i descrie funcionarea. 8.5.2.7. Utilizarea noilor tag-uri Pentru a putea utiliza n pagini tag-urile definite, a mai rmas repornirea Tomcat. Dup aceast repornire, dac se invoc
http://masinaTomcat:8080/NewTagJsp/TestTag.jsp

se obine ca rspuns imaginea din fig. 8.14.

Figura 8.14. Imaginea dat de tag-urile nou definite

459

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