|
|
|||
|
|
12/05/2008 |
|
|
|
|
|
|
In aceasta lucrare de laborator vor fi acoperite
urmatoarele probleme:
- Tehnologia Java Servlet, Crearea aplicatiilor Web bazate pe
servlet-uri utilizand NetBeans
- Precizari privind temele pentru
acasa si colocviul de laborator si teme suplimentare
- Anexa
Un servlet este un obiect
al unei clase Java ce extinde functionalitatea unui server care lucreaza dupa
modelul de acces cerere-raspuns (cum este cel utilizat de protocolul HTTP, pe
care se bazeaza aplicatiile Web) prin crearea unui continut dinamic.
Un servlet Web (care adauga
functionalitate unui server HTTP) trebuie sa extinda (prin mostenire)
clasa HttpServlet din pachetul javax.servlet.http.
Servlet-urile Web sunt componente care se executa intr-un container Web (Web container sau Web engine),
tot asa cum applet-urile sunt executate intr-un browser Web.
Astfel,
operatiile care tin de ciclul de viata al servlet-ului (apelul metodelor init(), destroy(), service()) sunt realizate de catre container in momentele in care acestea
sunt necesare (initializare, incarcare, etc.).
De
asemenea, crearea obiectelor care incapsuleaza cererea si raspunsul HTTP,
pasarea acestora metodei service(), gestionarea
variabilelor CGI precum si multe alte servicii sunt realizate de catre container
la momentul potrivit.
Metoda
service() mostenita de la clasa HttpServlet are o implementare generica dar care se recomanda sa fie
pastrata, deoarece ea identifica tipul de metoda a cererii HTTP si apeleaza
metoda potrivita (doPost() in cazul metodei POST, doGet() in cazul metodei GET, etc.).
Pentru
a putea fi accesat servlet-ul, clientului trebuie sa i se furnizeze o adresa URL care in general difera de adresa la care se afla cu adevarat fisierul cu
codul sursa al servlet-ului.
Adresa URL (1) este asociata prin intermediul unui alias (2) dat de programator cu calea completa necesara identificarii fisierului sursa (3) prin codul XML scris
intr-un fisier (web.xml) denumit deployment descriptor (descriptor de
desfasurare/instalare - DD).
De
exemplu, urmatorul continut al unui fisier web.xml
specifica:
- existenta unui
servlet cu numele ClasaServlet (al carui cod sursa se afla in ClasaServlet.java iar
codul compilat in ClasaServlet.class) cu
ajutorul tag-urilor XML <servlet> si <servlet-class>,
- asocierea servlet-ului ClasaServlet cu aliasul
numeintern (prin
intermediul tag-ului <servlet-name>),
- asocierea aliasului
numeintern cu formatul utilizat de client pentru URL /ServletAccesServiciu (prin
intermediul tag-urilor <servlet-mapping> si <url-pattern>),
|
<web-app> <servlet> <servlet-name>numeintern</servlet-name> <servlet-class>ClasaServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>numeintern</servlet-name> <url-pattern>/ServletAccesServiciu</url-pattern> </servlet-mapping> </web-app> |
Rolurile pe care componentele Web
(servlet-urile dar si paginile JSP) le pot juca sunt:
1) primirea
cererilor HTTP de la client (sub
forma de obiecte HttpServletRequest) si eventual utilizarea parametrilor obtinuti din formularul care a generat cererea,
2) executarea
sarcinilor aplicatiei (denumite business logic) fie direct fie prin delegarea catre o alta componenta:
- alte componente Web
– servlet-uri sau pagini JSP,
-
componente business locale
(JavaBeans) sau distribuite (Enterprise JavaBeans),
3) generarea
dinamica a continutului si trimiterea
lui in raspunsul catre client prin
intermediul raspunsurilor HTTP (sub forma de obiecte HttpServletResponse).
Un posibil template al servlet-urilor Java:
|
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class ClasaServlet
extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException,
IOException { processRequest(request,
response); } protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException,
IOException { processRequest(request,
response); } protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { // Stabilirea tipului de continut response.setContentType("text/html"); // Utilizare "request" pentru a citi antetele HTTP primite (de ex. cookies) // si datele formularului HTML (pe care utilizatorul le-a introdus
si trimis) // Utilizare "response" pentru a specifica linia si antetele raspunsului
HTTP // (tipul de continut, cookies). PrintWriter out = response.getWriter(); // Utilizare "out" pentru a trimite
continut HTML catre browser } } |
Serverul Web de la
Apache realizat in cadrul proiectului Jakarta, numit Tomcat, reprezinta o implementare de
referinta oficiala a specificatiilor servlet
si JSP. El include un container pentru servlet-uri si
a JSP-uri. Ultima versiune de Tomcat poate fi obtinuta de la adresa Web: http ://jakarta.apache.org/site/binindex.cgi. Mai multe detalii despre lucrul direct cu
containerele Jackarta Tomcat (structura de directoare, modul de desfasurare,
etc.) pot fi obtinute la adresa http://discipline.elcom.pub.ro/swrtc/2006_Laborator/2006_SwRTc_Lab_3_Main_v01.htm.
Pentru exemplificare, vom folosi din clasa Orar, accesata la distanta prin
intermediul servlet-urilor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public class Orar { private String[]
orar; // public Orar() { orar = new String[7]; // alocarea dinamica a spatiului pentru
tablou // popularea tabloului cu
valori orar[0] = "Luni nu sunt
ore de LPAI."; orar[1] = "Marti sunt
laboratoare de LPAI."; orar[2] = "Miercuri nu
sunt ore de LPAI."; orar[3] = "Joi sunt
proiecte de LPAI."; orar[4] = "Vineri este
curs de LPAI."; orar[5] = "Sambata nu
sunt ore de LPAI."; orar[6] = "Duminica nu
sunt ore de LPAI."; } public String getOrar(int zi) { // metoda accesor - getter return orar[zi]; // returneaza referinta la tablou } public void setOrar(int zi, String text)
{ // metoda accesor - setter orar[zi] = text; // inlocuieste un element } } |
In laborator: 1. Se deschide
NetBeans IDE 5.5 si se sterg (Delete
Project) toate proiectele
anterior deschise. 2. Se creaza un nou proiect (File > New Project sau Ctrl-Shift-N). 3. In Categories se selecteaza Web,
in Projects se selecteaza Web
Application, si se apasa Next. 4. La Project Name
se scrie numele ales pentru noul proiect: AplicatieOrar1 5. La Server se selecteaza: Bundled Tomcat (5.5.17).
Se apasa Next. 6. La Frameworks nu se selecteaza
nici un framework. Se apasa Finish. |
In laborator: 1. Se adauga un New File/Folder cu
numele Orar, selectand Java Classes si Java Class. 2. Se inlocuieste codul generat automat
cu codul de mai sus. |
Vom incepe cu un servlet simplu care permite accesul la obiecte Orar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
import java.io.*; import java.net.*; import javax.servlet.*; import
javax.servlet.http.*; public class ServletOrarInitial extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out =
response.getWriter(); // Generarea formularului
pentru accesul recursiv la servicii out.println("<html>"); out.println("<head>"); out.println("<title>Acces orar</title>"); out.println("</head>"); out.println("<body>");
out.println("<h1>Acces orar (forma initiala) - generat de
servlet</h1>"); out.println("<hr><form name=\"input\"
action=\"AccesInitial\"" + "
method=\"get\">");
out.println("<input type=\"radio\"
name=\"zi\" checked=\"checked\"" + "
value=\"0\"> Luni"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"1\">
Marti"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"2\">
Miercuri"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"3\">
Joi"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"4\">
Vineri"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"5\">
Sambata"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"6\">
Duminica"); out.println("<hr>");
out.println("<input type=\"radio\" name=\"serviciu\"
checked=\"checked\"" + "
value=\"getOrar\"> Obtinere
orar");
out.println("<br><input type=\"radio\"
name=\"serviciu\" value=\"setOrar\">" + "
Modificare orar");
out.println("<input type=\"text\" name=\"modificare\"
value=\"\">"); out.println("<hr><input type=\"submit\"
value=\"Trimite\">");
out.println("</form><hr>"); Orar orar = new Orar(); // Obtinerea parametrilor introdusi de utilizator in formular int zi = Integer.parseInt(request.getParameter("zi")); //
Daca serviciu cerut e obtinere orar if (request.getParameter("serviciu").equals("getOrar")) { out.println("<b>Orarul
cerut:</b> <br>" + orar.getOrar(zi)); } //
Daca serviciu cerut e modificare orar else if (request.getParameter("serviciu").equals("setOrar")) { String modificare = request.getParameter("modificare"); orar.setOrar(zi, modificare);
out.println("<b>Modificarea ceruta:</b>
<br>" + orar.getOrar(zi)); } out.println("</body>"); out.println("</html>"); out.close(); } protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException,
IOException { processRequest(request,
response); } protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException,
IOException { processRequest(request,
response); } } |
In laborator: 1. Se adauga un New File/Folder selectand Web
si Servlet.
2. La Name
and Location se precizeaza numele clasei ServletOrarInitial. 3. La Configure Servlet Deployment se precizeaza numele intern (Servlet Name) servletinitial si URL Pattern /AccesInitial. Se apasa
Finish. 4. Se inlocuieste codul generat
automat pentru ServletOrarInitial cu codul
de mai sus. |
Se observa (in directorul WEB-INF) continutul generat automat al fisierului
web.xml:
|
<?xml
version="1.0" encoding="UTF-8"?> <web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>servletinitial</servlet-name> <servlet-class>ServletOrarInitial</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletinitial</servlet-name> <url-pattern>/AccesInitial</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file> index.jsp </welcome-file> </welcome-file-list> </web-app> |
In laborator: 1. Se inlocuieste codul generat
automat al fisierului index,jsp cu codul de mai jos. |
|
<%@page
contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <html> <head> <meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>Pagina Index</h1> <hr> <a
href="PaginaAccesInitiala.html">Pagina
acces la orar (initiala)</a> <hr> </body> </html> |
Acum va fi adaugata pagina HTML care
contine formularul pentru accesul la servlet:
In laborator: 1. Se adauga un New File/Folder selectand Web
si HTML.
2. La Name
and Location se precizeaza numele PaginaAccesInitiala. Se
apasa Finish. 3. Se inlocuieste codul generat
automat pentru cu codul de mai jos. |
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type"
content="text/html; charset=UTF-8"> <title>Acces orar</title> </head> <body> <h1>Acces orar (forma initiala)</h1>
<hr><form name="input" action="AccesInitial" method="get"> <input
type="radio" name="zi" checked="checked" value="0"> Luni <br> <input
type="radio" name="zi" value="1"> Marti <br> <input
type="radio" name="zi" value="2"> Miercuri <br> <input
type="radio" name="zi" value="3"> Joi <br> <input
type="radio" name="zi" value="4"> Vineri <br> <input
type="radio" name="zi" value="5"> Sambata <br> <input
type="radio" name="zi" value="6"> Duminica <hr> <input
type="radio" name="serviciu" checked="checked" value="getOrar"> Obtinere orar <br>
<input type="radio" name="serviciu" value="setOrar"> Modificare orar <input
type="text" name="modificare" value=""> <input
type="submit" value="Trimite"> </form> <hr> </body> </html> |
In laborator: 1. Se selecteaza Build Project pe nodul proiectului AplicatieOrar1.
2. Se selecteaza Run Project pe nodul proiectului AplicatieOrar1. 3. Se utilizeaza pagina in diverse
moduri, testand serviciile obtinere si modificare. |
Utilizand serviciul de modificare orar se face apel la metoda setOrar():
Dar daca se acceseaza din nou serviciul de obtinere modificarea nu se
regaseste. Pentru ca
modificarea sa fie retinuta trebuie modificat servlet-ul.
Protocolul HTTP nu are stari (este stateless) asa incat serverul HTTP nu
retine informatii privind cererile anterioare. In plus, pentru ca servlet-urile sa fie accesate eficient de catre mai multi
clienti in acelasi timp containerul de servlet-uri formeaza un asa-numit thread pool cu instante ale servlet-ului
din care alege unul oarecare pentru fiecare client. De aceea declararea obiectului de tip Orar ca
variabila instanta nu este o solutie.
Obiectele din clasa HttpSession
gestionate de containerul de servlet-uri permit pastrarea referintelor catre obiecte ale aplicatiei, numite atribute, si regasirea acestora, prin intermediul metodelor setAttribute() si getAttribute().
Vom modifica servletul pentru a crea si utiliza o sesiune.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
import java.io.*; import java.net.*; import javax.servlet.*; import
javax.servlet.http.*; public class ServletOrarFinal extends HttpServlet { protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out =
response.getWriter(); // Generarea formularului
pentru accesul recursiv la servicii out.println("<html>"); out.println("<head>"); out.println("<title>Acces orar</title>"); out.println("</head>"); out.println("<body>");
out.println("<h1>Acces orar (forma finala) - generat de
servlet</h1>"); out.println("<hr><form name=\"input\"
action=\"AccesFinal\"" + "
method=\"get\">");
out.println("<input type=\"radio\"
name=\"zi\" checked=\"checked\"" + "
value=\"0\"> Luni"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"1\">
Marti"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"2\">
Miercuri"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"3\">
Joi"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"4\">
Vineri"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"5\">
Sambata"); out.println("<br> <input
type=\"radio\" name=\"zi\" value=\"6\">
Duminica"); out.println("<hr>");
out.println("<input type=\"radio\" name=\"serviciu\"
checked=\"checked\"" + "
value=\"getOrar\"> Obtinere
orar");
out.println("<br><input type=\"radio\"
name=\"serviciu\" value=\"setOrar\">" + "
Modificare orar");
out.println("<input type=\"text\" name=\"modificare\"
value=\"\">"); out.println("<hr><input type=\"submit\"
value=\"Trimite\">"); out.println("</form><hr>"); //
Transformarea obiectului orar in atribut al sesiunii curente pentru // salvarea
starii lui HttpSession ses = request.getSession(); Orar orar = (Orar) ses.getAttribute("orar"); if (orar == null) { // Daca nu exista orarul salvat ca atribut
al sesiunii orar = new Orar(); ses.setAttribute("orar",
orar); } //
Obtinerea parametrilor introdusi de utilizator in formular int zi = Integer.parseInt(request.getParameter("zi")); //
Daca serviciu cerut e obtinere orar if (request.getParameter("serviciu").equals("getOrar")) { out.println("<b>Orarul
cerut:</b> <br>" + orar.getOrar(zi)); } //
Daca serviciu cerut e modificare orar else if (request.getParameter("serviciu").equals("setOrar")) { String modificare = request.getParameter("modificare"); orar.setOrar(zi, modificare);
out.println("<b>Modificarea ceruta:</b>
<br>" + orar.getOrar(zi)); } out.println("</body>"); out.println("</html>"); out.close(); } protected void doGet(HttpServletRequest request, HttpServletResponse
response) throws ServletException,
IOException { processRequest(request,
response); } protected void doPost(HttpServletRequest request, HttpServletResponse
response) throws ServletException,
IOException { processRequest(request,
response); } } |
In laborator: 1. Se adauga un New File/Folder selectand Web
si Servlet.
2. La Name
and Location se precizeaza numele clasei ServletOrarFinal. 3. La Configure Servlet Deployment se precizeaza numele intern (Servlet Name) servletfinal si URL Pattern /AccesFinal. Se apasa Finish. 4. Se inlocuieste codul generat
automat pentru ServletOrarFinal cu codul
de mai sus. 5. Se inlocuieste codul generat
automat al fisierului index,jsp cu codul de mai jos. |
|
<%@page
contentType="text/html"%> <%@page
pageEncoding="UTF-8"%> <html> <head> <meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>Pagina Index</h1> <hr> <a
href="PaginaAccesInitiala.html">Pagina
acces la orar (initiala)</a> <hr> <a
href="PaginaAccesFinala.html">Pagina
acces la orar (finala)</a>
<hr> </body> </html> |
Acum va fi adaugata pagina HTML care
contine formularul pentru accesul la servlet:
In laborator: 1. Se adauga un New File/Folder selectand Web
si HTML.
2. La Name
and Location se precizeaza numele PaginaAccesFinala. Se
apasa Finish. 3. Se inlocuieste codul generat
automat pentru cu codul de mai jos. |
<!DOCTYPE HTML PUBLIC
"-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8"> <title>Acces orar</title> </head> <body> <h1>Acces orar (forma finala)</h1>
<hr><form name="input" action="AccesFinal" method="get"> <input
type="radio" name="zi" checked="checked" value="0"> Luni <br> <input
type="radio" name="zi" value="1"> Marti <br> <input
type="radio" name="zi" value="2"> Miercuri <br> <input
type="radio" name="zi" value="3"> Joi <br> <input
type="radio" name="zi" value="4"> Vineri <br> <input
type="radio" name="zi" value="5"> Sambata <br> <input
type="radio" name="zi" value="6"> Duminica <hr><input type="radio" name="serviciu"
checked="checked" value="getOrar"> Obtinere
orar <br>
<input type="radio" name="serviciu" value="setOrar"> Modificare orar <input
type="text" name="modificare" value=""> <input
type="submit" value="Trimite"> </form><hr> </body> </html> |
In laborator: 1. Se selecteaza Build Project pe nodul proiectului AplicatieOrar1.
2. Se selecteaza Run Project pe nodul proiectului AplicatieOrar1. 3. Se utilizeaza pagina in diverse
moduri, testand serviciile obtinere si modificare. |
De aceasta data, daca se acceseaza serviciul de obtinere dupa cel de modificare,
aceasta se regaseste.
Colocviul de laborator va fi sustinut la ultimul lucrare
(in saptamanile 13-14), pe baza temelor pentru acasa de la laboratoarele 1-4
(care au fost realizate pe grupuri de 2-3 studenti) si a unor intrebari
adresate individual din continutul temelor. De aceea este necesara existenta
temelor pe hartie (scrise de mana sau listing).
De la www.javapassion.com (Java EE Programming (with Passion!)):
LAB-4002:
Servlet Basics (arhiva 4002_servletbasics.zip)
LAB-4004:
Session Tracking (arhiva 4004_sessiontracking.zip)
LAB-4005:
Servlet Advanced (Filtering, Event Handling) (arhiva 4005_servletadv.zip)
LAB-4016 Building
Bookstore Sample Apps (arhiva 4016_jspbookstore.zip)
De la www.javapassion.com:
LAB-4001:
Web Application Structure (arhiva 4001_webappstructure.zip)
LAB-4011:
NetBeans Quick Start Guide for Web Apps II (arhiva 4011_netbeanswebapp2.zip)
De la NetBeans IDE 5.5.1 Documentation (http://www.netbeans.org/kb/55/index.html)
NetBeans
IDE 5.5 Quick Start Guide