Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
laboratoare:laborator05 [2015/09/07 12:33] Andrei Roșu-Cojocaru |
laboratoare:laborator05 [2015/11/25 20:00] (current) Andrei Roșu-Cojocaru |
||
|---|---|---|---|
| Line 18: | Line 18: | ||
| ===== Materiale Ajutătoare ====== | ===== Materiale Ajutătoare ====== | ||
| - | {{ :laboratoare:laborator08:aipi2014-lab08-slides.pdf }} | + | TODO |
| - | + | ||
| - | {{ :laboratoare:laborator08:aipi2014-lab08-slides-3pp.pdf }} | + | |
| ===== Tehnologia JavaServer Pages - aspecte generale ===== | ===== Tehnologia JavaServer Pages - aspecte generale ===== | ||
| Line 44: | Line 42: | ||
| Deşi din punctul de vedere al programatorului un Java Servlet reprezintă o clasă Java (unde generarea elementelor de adnotare se face prin apelarea unor metode) iar o pagină JSP se aseamănă mai mult cu un document (unde conţinutul static este separat de conţinutul dinamic – generat de componente Java Beans sau etichete JSP), tehnologiile sunt echivalente. O pagină JSP este transformată într-un Java Servlet (care este compilat) responsabil de comunicaţia cu clientul şi de toate celelalte prelucrări. Modificările realizate asupra unei pagini JSP sunt detectate în mod automat, astfel încât atât procesul de transformare într-un Java Servlet cât şi procesul de compilare corespunzător sunt reluate atunci când se face o cerere pentru aceasta. | Deşi din punctul de vedere al programatorului un Java Servlet reprezintă o clasă Java (unde generarea elementelor de adnotare se face prin apelarea unor metode) iar o pagină JSP se aseamănă mai mult cu un document (unde conţinutul static este separat de conţinutul dinamic – generat de componente Java Beans sau etichete JSP), tehnologiile sunt echivalente. O pagină JSP este transformată într-un Java Servlet (care este compilat) responsabil de comunicaţia cu clientul şi de toate celelalte prelucrări. Modificările realizate asupra unei pagini JSP sunt detectate în mod automat, astfel încât atât procesul de transformare într-un Java Servlet cât şi procesul de compilare corespunzător sunt reluate atunci când se face o cerere pentru aceasta. | ||
| - | {{ :laboratoare:laborator08:figura01_interactiunea_client_server.png?nolink&600 }} | + | {{ :laboratoare:laborator05:01clientserverelationship.png?nolink&600 }} |
| Atunci când **1)** un client transmite (din browser) o cerere HTTP către server pentru o pagină .jsp, **2)** aceasta este transmisă mai departe motorului JSP care încarcă de pe disc resursa care a fost indicată prin intermediul URL-ului. Dacă pe server nu există un Java Servlet corespunzător celei mai recente versiuni a paginii respective, **3)** acesta este generat (prin instrucţiuni de tip ''println'' ce includ etichetele respective şi convertirea elementelor JSP în cod Java care implementează comportamentul dinamic al paginii) şi **4)** apoi compilat într-o clasă executabilă. Acest cod, căruia i se pasează cererea originală **5)** este rulat de motorul Java Servlet producând un rezultat în format HTML care este transmis serverului ca răspuns HTTP, acesta **6)** fiind pasat clientului care îl afişază în browser, ca şi când ar fi conţinut static. | Atunci când **1)** un client transmite (din browser) o cerere HTTP către server pentru o pagină .jsp, **2)** aceasta este transmisă mai departe motorului JSP care încarcă de pe disc resursa care a fost indicată prin intermediul URL-ului. Dacă pe server nu există un Java Servlet corespunzător celei mai recente versiuni a paginii respective, **3)** acesta este generat (prin instrucţiuni de tip ''println'' ce includ etichetele respective şi convertirea elementelor JSP în cod Java care implementează comportamentul dinamic al paginii) şi **4)** apoi compilat într-o clasă executabilă. Acest cod, căruia i se pasează cererea originală **5)** este rulat de motorul Java Servlet producând un rezultat în format HTML care este transmis serverului ca răspuns HTTP, acesta **6)** fiind pasat clientului care îl afişază în browser, ca şi când ar fi conţinut static. | ||
| - | {{ :laboratoare:laborator08:figura02_generare_JavaServlet_paginaJSP.png?nolink&700 }} | + | {{ :laboratoare:laborator05:02JavaServletJSPgeneration.png?nolink&700 }} |
| ===== Integrarea JavaServer Pages cu serverul Apache Tomcat 8.x ===== | ===== Integrarea JavaServer Pages cu serverul Apache Tomcat 8.x ===== | ||
| Line 55: | Line 53: | ||
| Paginile ''.jsp'' se vor găsi în rădăcina directorului unde a fost dezvoltată aplicaţia web. Pagina care va fi afişată automat atunci când se solicită adresa: ''%%http://<server_IP>:<server_port>/<application_directory>/%%'' este ''index.jsp'' sau cea precizată prin elementul ''<welcome-file>'' din secţiunea ''<welcome-file-list>'' a fişierului de configurare ''web.xml''. Acesta va fi plasat în directorul ''WEB-INF'', specificându-se diferiţi parametrii ai aplicaţiei web (inclusiv despre clasele Java Servlet ce implementează logica aplicaţiei). De asemenea, în condiţiile în care sunt folosite metode din clase Java, acestea vor fi plasate într-un director ''WEB-INF/classes''. Este recomandat ca acestea să fie modularizate pe pachete pentru ca referirea lor să se poată realiza cu uşurinţă. Dacă se folosesc biblioteci speciale (în arhive ''.jar''), acestea trebuie incluse în ''WEB-INF/lib''. Astfel de biblioteci speciale pot fi "driver"-ul de conectare la baza de date precum şi biblioteca pentru accesarea funcţionalităţilor oferite de JSTL (JavaServer Pages Standard Tag Library). Deşi sursele aplicaţiei se pot găsi în orice fişier, este recomandat ca acestea să se găsească tot aici, într-un subdirector denumit ''src'' sau ''sources'', astfel încât să poată fi identificat cu uşurinţă, iar procesul de compilare al surselor şi de transfer al claselor (realizat înainte de operaţia de configurare – //eng.// deploy a aplicaţiei web) să nu implice un efort deosebit. | Paginile ''.jsp'' se vor găsi în rădăcina directorului unde a fost dezvoltată aplicaţia web. Pagina care va fi afişată automat atunci când se solicită adresa: ''%%http://<server_IP>:<server_port>/<application_directory>/%%'' este ''index.jsp'' sau cea precizată prin elementul ''<welcome-file>'' din secţiunea ''<welcome-file-list>'' a fişierului de configurare ''web.xml''. Acesta va fi plasat în directorul ''WEB-INF'', specificându-se diferiţi parametrii ai aplicaţiei web (inclusiv despre clasele Java Servlet ce implementează logica aplicaţiei). De asemenea, în condiţiile în care sunt folosite metode din clase Java, acestea vor fi plasate într-un director ''WEB-INF/classes''. Este recomandat ca acestea să fie modularizate pe pachete pentru ca referirea lor să se poată realiza cu uşurinţă. Dacă se folosesc biblioteci speciale (în arhive ''.jar''), acestea trebuie incluse în ''WEB-INF/lib''. Astfel de biblioteci speciale pot fi "driver"-ul de conectare la baza de date precum şi biblioteca pentru accesarea funcţionalităţilor oferite de JSTL (JavaServer Pages Standard Tag Library). Deşi sursele aplicaţiei se pot găsi în orice fişier, este recomandat ca acestea să se găsească tot aici, într-un subdirector denumit ''src'' sau ''sources'', astfel încât să poată fi identificat cu uşurinţă, iar procesul de compilare al surselor şi de transfer al claselor (realizat înainte de operaţia de configurare – //eng.// deploy a aplicaţiei web) să nu implice un efort deosebit. | ||
| - | |||
| - | {{ :laboratoare:laborator08:figura03_structura_unei_aplicatii_web.png?nolink }} | ||
| - | |||
| - | Încărcarea tuturor acestor clase se face atunci când este pornit serverul: | ||
| - | <code> | ||
| - | Dec 4, 2014 12:00:00 AM org.apache.catalina.startup.HostConfig deployDirectory | ||
| - | INFO: Deploying web application directory ApacheTomcat\apache-tomcat-8.0.15\webapps\BookStore | ||
| - | </code> | ||
| Spre diferenţă de Java Servlets, nu este necesară realizarea configurării aplicaţiei web atunci când sunt realizate modificări asupra paginilor JSP, întrucât acestea sunt detectate automat, determinând generarea unor Java Servlets corespunzătoare atunci când paginile sunt accesate de către client. Repornirea serverului Apache Tomcat va fi necesară doar în cazul operării unor modificări pentru clasele Java ce sunt utilizate de aplicaţie, fiind necesară reîncărcarea lor (după ce compilarea lor este realizată de către programator). | Spre diferenţă de Java Servlets, nu este necesară realizarea configurării aplicaţiei web atunci când sunt realizate modificări asupra paginilor JSP, întrucât acestea sunt detectate automat, determinând generarea unor Java Servlets corespunzătoare atunci când paginile sunt accesate de către client. Repornirea serverului Apache Tomcat va fi necesară doar în cazul operării unor modificări pentru clasele Java ce sunt utilizate de aplicaţie, fiind necesară reîncărcarea lor (după ce compilarea lor este realizată de către programator). | ||
| Line 72: | Line 62: | ||
| Datorită faptului că o cerere pentru o pagină JSP implică (în unele situaţii) transformarea într-un Java Servlet precum şi compilarea acestuia, vizualizarea acesteia se va face după o perioadă mai mare decât în situaţia când aceste prelucrări nu mai trebuie realizate. De asemenea, trebuie avută în vedere situaţia în care o astfel de operaţie eşuează, astfel încât în browser sunt afişate excepţiile generate în loc de conţinutul paginii solicitate. | Datorită faptului că o cerere pentru o pagină JSP implică (în unele situaţii) transformarea într-un Java Servlet precum şi compilarea acestuia, vizualizarea acesteia se va face după o perioadă mai mare decât în situaţia când aceste prelucrări nu mai trebuie realizate. De asemenea, trebuie avută în vedere situaţia în care o astfel de operaţie eşuează, astfel încât în browser sunt afişate excepţiile generate în loc de conţinutul paginii solicitate. | ||
| - | Versiunea Apache Tomcat 8.0.15 suportă specificaţia JSP 2.3 şi EL 3.0. | + | Versiunea Apache Tomcat 8.0.28 suportă specificaţia JSP 2.3 şi EL 3.0. |
| ===== Ciclul de viață al unei pagini JSP ===== | ===== Ciclul de viață al unei pagini JSP ===== | ||
| Line 84: | Line 74: | ||
| <code java> | <code java> | ||
| public void _jspInit() { | public void _jspInit() { | ||
| - | // ... | + | // ... |
| } | } | ||
| public void _jspDestroy() { | public void _jspDestroy() { | ||
| - | // ... | + | // ... |
| } | } | ||
| public void _jspService (final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { | public void _jspService (final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { | ||
| - | // ... | + | // ... |
| } | } | ||
| </code> | </code> | ||
| - | {{ :laboratoare:laborator08:figura04_ciclul_de_viata_al_unei_pagini_jsp.png?nolink&400 }} | + | {{ :laboratoare:laborator05:03JSPpagelifecycle.png?nolink&400 }} |
| - | Toate aceste metode fac parte din interfaţa ''javax.servlet.HttpJspPage''. | + | Toate aceste metode fac parte din interfaţa [[https://docs.oracle.com/javaee/7/api/javax/servlet/jsp/HttpJspPage.html|javax.servlet.HttpJspPage]]. |
| În cadrul procesului de compilare, motorul JSP verifică dacă este necesar să compileze pagina respectivă (în situaţia în care aceasta nu a fost niciodată compilată, sau eticheta de timp a servlet-ului corespunzător nu corespunde celei mai recente modificări), acestă operaţie fiind precedată de transformarea paginii, ce include şi parsarea acesteia. | În cadrul procesului de compilare, motorul JSP verifică dacă este necesar să compileze pagina respectivă (în situaţia în care aceasta nu a fost niciodată compilată, sau eticheta de timp a servlet-ului corespunzător nu corespunde celei mai recente modificări), acestă operaţie fiind precedată de transformarea paginii, ce include şi parsarea acesteia. | ||
| Line 112: | Line 102: | ||
| </code> | </code> | ||
| - | Pentru ca excepţia (într-un obiect de tip ''javax.servlet.jsp.JspException'') să fie disponibilă în cadrul paginii de eroare pentru a o trata, trebuie specificată, la începutul paginii de eroare, directiva: | + | Pentru ca excepţia (într-un obiect de tip [[http://docs.oracle.com/javaee/7/api/javax/servlet/jsp/JspException.html|javax.servlet.jsp.JspException]]) să fie disponibilă în cadrul paginii de eroare pentru a o trata, trebuie specificată, la începutul paginii de eroare, directiva: |
| <code java> | <code java> | ||
| Line 128: | Line 118: | ||
| Combinarea de cod Java cu etichete HTML oferă posibilitatea realizării de pagini cu conţinut dinamic, însă în cazul aplicaţiilor cu funcţionalitate complexă, procesul de întreţinere poate fi dificil, problema provenind în special din faptul că partea de logică a aplicaţiei (care este dezvoltată de programatori – implicând algoritmi şi interacţiune cu baza de date) nu este separată de partea de prezentare (realizată de regulă de dezvoltatori web – concentrându-se mai ales pe elemente de grafică). Arhitectura aplicaţiei JSP va reflecta raportul dintre aceste aspecte. | Combinarea de cod Java cu etichete HTML oferă posibilitatea realizării de pagini cu conţinut dinamic, însă în cazul aplicaţiilor cu funcţionalitate complexă, procesul de întreţinere poate fi dificil, problema provenind în special din faptul că partea de logică a aplicaţiei (care este dezvoltată de programatori – implicând algoritmi şi interacţiune cu baza de date) nu este separată de partea de prezentare (realizată de regulă de dezvoltatori web – concentrându-se mai ales pe elemente de grafică). Arhitectura aplicaţiei JSP va reflecta raportul dintre aceste aspecte. | ||
| - | {{ :laboratoare:laborator08:figura05_arhitectura_unei_aplicatii_web.png?nolink&800 }} | + | {{ :laboratoare:laborator05:04webapplicationarchitecture.png?nolink&800 }} |
| În modelul 1, logica aplicaţiei este implementată în clase Java (componente Java Beans) şi poate fi apelată din partea de prezentare realizată prin pagini JSP. Această soluţie este adecvată pentru cazul în care aplicaţia nu este foarte complexă, o problemă fiind constituită de faptul că toată comunicaţia cu clientul trebuie realizată din pagina JSP. O astfel de abordare se mai numeşte client-server, are avantajul simplităţii şi dezavantajul lipsei de scalabilitate. | În modelul 1, logica aplicaţiei este implementată în clase Java (componente Java Beans) şi poate fi apelată din partea de prezentare realizată prin pagini JSP. Această soluţie este adecvată pentru cazul în care aplicaţia nu este foarte complexă, o problemă fiind constituită de faptul că toată comunicaţia cu clientul trebuie realizată din pagina JSP. O astfel de abordare se mai numeşte client-server, are avantajul simplităţii şi dezavantajul lipsei de scalabilitate. | ||
| Line 145: | Line 135: | ||
| * declaraţii. | * declaraţii. | ||
| - | {{ :laboratoare:laborator08:figura06_structura_unei_pagini_jsp.png?nolink&1024 }} | + | {{ :laboratoare:laborator05:05JSPpagestructure.png?nolink&1024 }} |
| De asemenea, pot fi folosite **comentarii** care pot fi: | De asemenea, pot fi folosite **comentarii** care pot fi: | ||
| Line 296: | Line 286: | ||
| | Prin acţiunile ''<jsp:attribute>'', ''<jsp:body>'' şi ''<jsp:element>'' elementele XML pot fi generate în momentul rulării, ca răspuns la o cerere şi nu atunci când sunt compilate sursele. <code java> | | Prin acţiunile ''<jsp:attribute>'', ''<jsp:body>'' şi ''<jsp:element>'' elementele XML pot fi generate în momentul rulării, ca răspuns la o cerere şi nu atunci când sunt compilate sursele. <code java> | ||
| <jsp:element name="xmlElement"> | <jsp:element name="xmlElement"> | ||
| - | <jsp:attribute name="xmlAttribute"> | + | <jsp:attribute name="xmlAttribute"> |
| - | Attribute Value | + | Attribute Value |
| - | </jsp:attribute> | + | </jsp:attribute> |
| - | <jsp:body> | + | <jsp:body> |
| - | Body for XML element | + | Body for XML element |
| - | </jsp:body> | + | </jsp:body> |
| </jsp:element> | </jsp:element> | ||
| </code> → <code java> | </code> → <code java> | ||
| <xmlElement xmlAttribute="Attribute Value"> | <xmlElement xmlAttribute="Attribute Value"> | ||
| - | Body for XML element | + | Body for XML element |
| </xmlElement> | </xmlElement> | ||
| </code> || | </code> || | ||
| Line 318: | Line 308: | ||
| | ''<jsp:setProperty>'' | stabilirea valorii proprietăţii unei componente Java Bean; anterior utilizării acestei proprietăţi, componenta Java Bean referită trebuie să fi fost definită; poate fi utilizată în cadrul acţiunii ''useBean'' (situaţie în care se execută numai dacă a fost instanţiat un obiect nou) sau independent de ea (caz în care se execută atât atunci când a fost găsit un element cu numele respectiv atunci când a fost instanţiat un obiect nou)\\ \\ Atributele asociate acţiunii ''setProperty'' sunt:\\ • ''name'' – desemnează componenta Java Bean a cărei proprietate va fi stabilită; trebuie să aibă aceeaşi valoare cu a identificatorului precizat în acţiunea ''useBean'';\\ • ''property'' – indică proprietatea care se doreşte a fi stabilită; valoarea specifică faptul că parametrii cererii ale căror nume se potrivesc cu numele proprietăţilor componentei Java Beans vor fi transmişi către metodele setter respective;\\ • ''value'' – specifică valoarea care se doreşte asignată proprietăţii în cauză; dacă valoarea parametrului e ''null'' sau parametrul nu există, acţiunea este ignorată;\\ • ''param'' – numele parametrului cererii a cărei valoare trebuie să o primească proprietatea; nu se poate folosi concomitent cu ''value'' (dar cei doi parametrii pot fi omişi); <code java> | | ''<jsp:setProperty>'' | stabilirea valorii proprietăţii unei componente Java Bean; anterior utilizării acestei proprietăţi, componenta Java Bean referită trebuie să fi fost definită; poate fi utilizată în cadrul acţiunii ''useBean'' (situaţie în care se execută numai dacă a fost instanţiat un obiect nou) sau independent de ea (caz în care se execută atât atunci când a fost găsit un element cu numele respectiv atunci când a fost instanţiat un obiect nou)\\ \\ Atributele asociate acţiunii ''setProperty'' sunt:\\ • ''name'' – desemnează componenta Java Bean a cărei proprietate va fi stabilită; trebuie să aibă aceeaşi valoare cu a identificatorului precizat în acţiunea ''useBean'';\\ • ''property'' – indică proprietatea care se doreşte a fi stabilită; valoarea specifică faptul că parametrii cererii ale căror nume se potrivesc cu numele proprietăţilor componentei Java Beans vor fi transmişi către metodele setter respective;\\ • ''value'' – specifică valoarea care se doreşte asignată proprietăţii în cauză; dacă valoarea parametrului e ''null'' sau parametrul nu există, acţiunea este ignorată;\\ • ''param'' – numele parametrului cererii a cărei valoare trebuie să o primească proprietatea; nu se poate folosi concomitent cu ''value'' (dar cei doi parametrii pot fi omişi); <code java> | ||
| <jsp:useBean id="myObject" class="myPackage.myClass"> | <jsp:useBean id="myObject" class="myPackage.myClass"> | ||
| - | <jsp:setProperty name="myObject" property="myProperty" value="myValue" ... /> | + | <jsp:setProperty name="myObject" property="myProperty" value="myValue" ... /> |
| </jsp:useBean> | </jsp:useBean> | ||
| <jsp:useBean id="myObject" class="myPackage.myClass" /> | <jsp:useBean id="myObject" class="myPackage.myClass" /> | ||
| Line 332: | Line 322: | ||
| | ''<jsp:plugin>'' | generarea codului specific browser-ului (o etichetă ''<OBJECT>'' sau ''<EMBED>'') pentru o componentă Java (applet sau clasă Java Bean); dacă plugin-ul necesar nu este prezent, acesta este descărcat şi apoi se poate executa componenta Java; parametrii sunt transmişi prin acţiunea ''<jsp:param>'', în caz de producere a unei erori, se poate specifica un şir de caractere care să fie afişat prin acţiunea ''<jsp:fallback>'' <code java> | | ''<jsp:plugin>'' | generarea codului specific browser-ului (o etichetă ''<OBJECT>'' sau ''<EMBED>'') pentru o componentă Java (applet sau clasă Java Bean); dacă plugin-ul necesar nu este prezent, acesta este descărcat şi apoi se poate executa componenta Java; parametrii sunt transmişi prin acţiunea ''<jsp:param>'', în caz de producere a unei erori, se poate specifica un şir de caractere care să fie afişat prin acţiunea ''<jsp:fallback>'' <code java> | ||
| <jsp:plugin type="applet" codebase="mydir" code="MyClass.class" width="100" height="100"> | <jsp:plugin type="applet" codebase="mydir" code="MyClass.class" width="100" height="100"> | ||
| - | <jsp:param name="paramname" value="paramvalue" /> | + | <jsp:param name="paramname" value="paramvalue" /> |
| - | <jsp:fallback> | + | <jsp:fallback> |
| - | Unable to load Java Plugin | + | Unable to load Java Plugin |
| - | </jsp:fallback> | + | </jsp:fallback> |
| </jsp:plugin> | </jsp:plugin> | ||
| </code> | | </code> | | ||
| Line 352: | Line 342: | ||
| <code java> | <code java> | ||
| <jsp:scriptlet> | <jsp:scriptlet> | ||
| - | Java code fragment | + | Java code fragment |
| </jsp:scriptlet> | </jsp:scriptlet> | ||
| </code> | </code> | ||
| Line 370: | Line 360: | ||
| <code java> | <code java> | ||
| <jsp:expression> | <jsp:expression> | ||
| - | expression | + | expression |
| </jsp:expression> | </jsp:expression> | ||
| </code> | </code> | ||
| Line 384: | Line 374: | ||
| <code java> | <code java> | ||
| <jsp:declaration> | <jsp:declaration> | ||
| - | declaration; | + | declaration; |
| - | [declaration; ]+ | + | [declaration; ]+ |
| </jsp:declaration> | </jsp:declaration> | ||
| </code> | </code> | ||
| Line 394: | Line 384: | ||
| ^ Obiect Implicit ^ Tip ^ Descriere ^ | ^ Obiect Implicit ^ Tip ^ Descriere ^ | ||
| - | | ''request'' | subclasă a ''javax.servlet.ServletRequest'' | cererea care a invocat pagina JSP | | + | | ''request'' | subclasă a [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html|javax.servlet.ServletRequest]] | cererea care a invocat pagina JSP | |
| - | | ''response'' | subclasă a ''javax.servlet.ServletResponse'' | răspunsul pe care îl generează pagina JSP | | + | | ''response'' | subclasă a [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletResponse.html|javax.servlet.ServletResponse]] | răspunsul pe care îl generează pagina JSP | |
| - | | ''out'' | ''javax.servlet.jsp.JspWriter'' | obiect care scrie în fluxul de ieşire | | + | | ''out'' | [[http://docs.oracle.com/javaee/7/api/javax/servlet/jsp/JspWriter.html|javax.servlet.jsp.JspWriter]] | obiect care scrie în fluxul de ieşire | |
| - | | ''session'' | ''javax.servlet.http.HttpSession'' | obiect sesiune asociat cererii care a invocat pagina JSP | | + | | ''session'' | [[https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html|javax.servlet.http.HttpSession]] | obiect sesiune asociat cererii care a invocat pagina JSP | |
| - | | ''application'' | ''javax.servlet.ServletContext'' | context pagină JSP | | + | | ''application'' | [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletContext.html|javax.servlet.ServletContext]] | context pagină JSP | |
| - | | ''config'' | ''javax.servlet.ServletConfig'' | informaţii de configurare referitoare la servlet | | + | | ''config'' | [[https://docs.oracle.com/javaee/7/api/javax/servlet/ServletConfig.html|javax.servlet.ServletConfig]] | informaţii de configurare referitoare la servlet | |
| - | | ''pageContext'' | ''javax.servlet.jsp.PageContext'' | contextul paginii JSP | | + | | ''pageContext'' | [[http://docs.oracle.com/javaee/7/api/javax/servlet/jsp/PageContext.html|javax.servlet.jsp.PageContext]] | contextul paginii JSP | |
| - | | ''page''' | ''java.lang.Object'' | referinţă către pagina JSP prin care poate fi accesat servlet-ul asociat | | + | | ''page'' | [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html|java.lang.Object]] | referinţă către pagina JSP prin care poate fi accesat servlet-ul asociat | |
| - | | ''exception'' | ''java.lang.Throwable'' | acces la detalii cu privire la eroare, în paginile de tratare a excepţiei | | + | | ''exception'' | [[https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html|java.lang.Throwable]] | acces la detalii cu privire la eroare, în paginile de tratare a excepţiei | |
| Astfel de obiecte vor fi disponibile **doar** în cadrul metodei ''_jspService()'', astfel încât referirea acestora în cadrul unei declaraţii JSP nu are sens. | Astfel de obiecte vor fi disponibile **doar** în cadrul metodei ''_jspService()'', astfel încât referirea acestora în cadrul unei declaraţii JSP nu are sens. | ||
| Line 447: | Line 437: | ||
| ... | ... | ||
| <table> | <table> | ||
| - | <tr><th>Header Name</th><th>Header Value</th></tr> | + | <tr><th>Header Name</th><th>Header Value</th></tr> |
| - | <% | + | <% |
| - | Enumeration headers = request.getHeaderNames(); | + | Enumeration headers = request.getHeaderNames(); |
| - | while (headers.hasMoreElements()) { | + | while (headers.hasMoreElements()) { |
| - | String headerName = (String)headers.nextElement(); | + | String headerName = (String)headers.nextElement(); |
| - | String headerValue = request.getHeader(headerName); | + | String headerValue = request.getHeader(headerName); |
| - | %> | + | %> |
| - | <tr><td><%= headerName %></td><td><%= headerValue %></td></tr> | + | <tr><td><%= headerName %></td><td><%= headerValue %></td></tr> |
| - | <% | + | <% |
| - | } | + | } |
| - | %> | + | %> |
| </table> | </table> | ||
| ... | ... | ||
| Line 501: | Line 491: | ||
| ... | ... | ||
| <% | <% | ||
| - | response.setDateHeader("Last-Modified",System.currentTimeMillis()); | + | response.setDateHeader("Last-Modified",System.currentTimeMillis()); |
| - | response.setHeader("Content-Type","text/html"); | + | response.setHeader("Content-Type","text/html"); |
| - | response.setIntHeader("Refresh", 60); | + | response.setIntHeader("Refresh", 60); |
| %> | %> | ||
| ... | ... | ||
| Line 535: | Line 525: | ||
| * ''void setMaxInactiveInterval(int)'' – stabileşte perioada de timp maximă, exprimată în secunde, care se poate scurge între diferite accesări provenite de la clienţi până când sesiunea va fi invalidată de containerul servletului; valoarea poate fi specificată şi în fişierul de configurare ''web.xml'': <code xml> | * ''void setMaxInactiveInterval(int)'' – stabileşte perioada de timp maximă, exprimată în secunde, care se poate scurge între diferite accesări provenite de la clienţi până când sesiunea va fi invalidată de containerul servletului; valoarea poate fi specificată şi în fişierul de configurare ''web.xml'': <code xml> | ||
| <session-config> | <session-config> | ||
| - | <session-timeout>60</session-timeout> | + | <session-timeout>60</session-timeout> |
| </session-config> | </session-config> | ||
| </code> Această valoare va suprascrie valoarea implicită specificată de serverul Apache Tomcat 8.x, care este de 30 de minute. În fişierul de configurare ''web.xml'' timpul de expirare va fi specificat, spre diferenţă de metoda ''setMaxInactiveInterval()'' nu în secunde, ci în minute. | </code> Această valoare va suprascrie valoarea implicită specificată de serverul Apache Tomcat 8.x, care este de 30 de minute. În fişierul de configurare ''web.xml'' timpul de expirare va fi specificat, spre diferenţă de metoda ''setMaxInactiveInterval()'' nu în secunde, ci în minute. | ||
| Line 618: | Line 608: | ||
| <code xml> | <code xml> | ||
| <context-param> | <context-param> | ||
| - | <param-name>file-upload</param-name> | + | <param-name>file-upload</param-name> |
| - | <param-value> | + | <param-value> |
| - | My Upload Location | + | My Upload Location |
| - | </param-value> | + | </param-value> |
| </context-param> | </context-param> | ||
| </code> | </code> | ||
| Line 627: | Line 617: | ||
| <code html> | <code html> | ||
| <form action="myJSPPage.jsp" method="POST" enctype="multipart/form-data"> | <form action="myJSPPage.jsp" method="POST" enctype="multipart/form-data"> | ||
| - | <input type="file" name="file" size="100" /> | + | <input type="file" name="file" size="100" /> |
| - | <br /> | + | <br /> |
| - | <input type="submit" value="Upload File" /> | + | <input type="submit" value="Upload File" /> |
| </form> | </form> | ||
| </code> | </code> | ||
| Line 676: | Line 666: | ||
| ... | ... | ||
| <% | <% | ||
| - | Properties properties = System.getProperties(); | + | Properties properties = System.getProperties(); |
| - | properties.setProperty("mail.smtp.host","localhost"); | + | properties.setProperty("mail.smtp.host","localhost"); |
| - | properties.setProperty("mail.user",myUser); | + | properties.setProperty("mail.user",myUser); |
| - | properties.setProperty("mail.password",myPassword); | + | properties.setProperty("mail.password",myPassword); |
| - | Session mailSession = Session.getDefaultInstance(properties); | + | Session mailSession = Session.getDefaultInstance(properties); |
| - | try { | + | try { |
| - | MimeMessage mailMimeMessage = new MimeMessage(maiSession); | + | MimeMessage mailMimeMessage = new MimeMessage(maiSession); |
| - | mailMimeMessage.setFrom(new InternetAddress(from)); | + | mailMimeMessage.setFrom(new InternetAddress(from)); |
| - | mailMimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); | + | mailMimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); |
| - | mailMimeMessage.setSubject("My Subject"); | + | mailMimeMessage.setSubject("My Subject"); |
| - | Multipart mailMultipart = new MimeMultipart(); | + | Multipart mailMultipart = new MimeMultipart(); |
| - | BodyPart mailBodyPart; | + | BodyPart mailBodyPart; |
| - | mailBodyPart = new MimeBodyPart(); | + | mailBodyPart = new MimeBodyPart(); |
| - | mailBodyPart.setText("My Mail Body"); | + | mailBodyPart.setText("My Mail Body"); |
| - | mailMultipart.addBodyPart(mailBodyPart); | + | mailMultipart.addBodyPart(mailBodyPart); |
| - | mailBodyPart = new MimeBodyPart(); | + | mailBodyPart = new MimeBodyPart(); |
| - | String filename = "myFileName.myExtension"; | + | String filename = "myFileName.myExtension"; |
| - | mailBodyPart.setDataHandler(new DataHandler(new FileDataSource(filename))); | + | mailBodyPart.setDataHandler(new DataHandler(new FileDataSource(filename))); |
| - | mailBodyPart.setFileName(filename); | + | mailBodyPart.setFileName(filename); |
| - | mailMultiPart.addBodyPart(mailBodyPart); | + | mailMultiPart.addBodyPart(mailBodyPart); |
| - | mailMimeMessage.setContent(mailMultiPart); | + | mailMimeMessage.setContent(mailMultiPart); |
| - | Transport.send(mailMimeMessage); | + | Transport.send(mailMimeMessage); |
| - | } catch (MessagingException exception) { | + | } catch (MessagingException exception) { |
| - | System.out.println("An exception has occurred: "+exception.getMessage(); | + | System.out.println("An exception has occurred: "+exception.getMessage(); |
| - | if (Constants.DEBUG) | + | if (Constants.DEBUG) { |
| - | exception.printStackTrace(); | + | exception.printStackTrace(); |
| } | } | ||
| + | } | ||
| %> | %> | ||
| </code> | </code> | ||
| Line 937: | Line 928: | ||
| | ''<c:catch>'' | gestionează orice obiect de tip ''Throwable'' întâlnit în corpul său, eventual expunându-l utilizatorului\\ \\ Atributul asociat etichetei este ''var'' ce indică denumirea variabilei care va stoca excepţia generată, în cazul în care va fi produsă de instrucţiunile din corpul său <code java> | | ''<c:catch>'' | gestionează orice obiect de tip ''Throwable'' întâlnit în corpul său, eventual expunându-l utilizatorului\\ \\ Atributul asociat etichetei este ''var'' ce indică denumirea variabilei care va stoca excepţia generată, în cazul în care va fi produsă de instrucţiunile din corpul său <code java> | ||
| <c:catch var="${exception}"> | <c:catch var="${exception}"> | ||
| - | <% some expression(s) that may potentially throw an error %> | + | <% some expression(s) that may potentially throw an error %> |
| </c:catch> | </c:catch> | ||
| <c:out value="exception: ${exception.message}" /> | <c:out value="exception: ${exception.message}" /> | ||
| Line 943: | Line 934: | ||
| | ''<c:if>'' | etichetă de tip condiţional, al cărui corp este evaluat în cazul când condiţia asociată este îndeplinită\\ \\ Atributele asociate etichetei sunt:\\ • ''test'' (obligatoriu) – condiţia care se doreşte a fi evaluată;\\ • ''var'' – denumirea variabilei care va stoca rezultatul condiţiei;\\ • ''scope'' – scopul variabilei care va stoca rezultatul condiţiei. <code java> | | ''<c:if>'' | etichetă de tip condiţional, al cărui corp este evaluat în cazul când condiţia asociată este îndeplinită\\ \\ Atributele asociate etichetei sunt:\\ • ''test'' (obligatoriu) – condiţia care se doreşte a fi evaluată;\\ • ''var'' – denumirea variabilei care va stoca rezultatul condiţiei;\\ • ''scope'' – scopul variabilei care va stoca rezultatul condiţiei. <code java> | ||
| <c:if test="${expression}" /> | <c:if test="${expression}" /> | ||
| - | <% do some operations %> | + | <% do some operations %> |
| </c:if> | </c:if> | ||
| </code> | | </code> | | ||
| | ''<c:choose>'' | etichetă de tip condiţional, indicând condiţii ce se exclud mutual, specificate prin ''<when>'' şi ''<otherwise>''; funcţionează ca instrucţiunea ''switch'' din Java, permiţând alegerea dintre mai multe alternative: ramurile case sunt specificate prin ''<when>'' în timp ce ramura default este specificată prin ''<otherwise>''.\\ \\ Eticheta nu are atribute. <code java> | | ''<c:choose>'' | etichetă de tip condiţional, indicând condiţii ce se exclud mutual, specificate prin ''<when>'' şi ''<otherwise>''; funcţionează ca instrucţiunea ''switch'' din Java, permiţând alegerea dintre mai multe alternative: ramurile case sunt specificate prin ''<when>'' în timp ce ramura default este specificată prin ''<otherwise>''.\\ \\ Eticheta nu are atribute. <code java> | ||
| <c:choose> | <c:choose> | ||
| - | <c:when test="${expression1}"><% do some operations %></c:when> | + | <c:when test="${expression1}"><% do some operations %></c:when> |
| - | <c:when test="${expression2}"><% do some operations %></c:when> | + | <c:when test="${expression2}"><% do some operations %></c:when> |
| - | ... | + | ... |
| - | <c:when test="${expressionn}"> | + | <c:when test="${expressionn}"> |
| - | <% do some operations %> | + | <% do some operations %> |
| - | </c:when> | + | </c:when> |
| - | <c:otherwise><% do some other operations %></c:otherwise> | + | <c:otherwise><% do some other operations %></c:otherwise> |
| </c:choose /> | </c:choose /> | ||
| </code> | | </code> | | ||
| Line 964: | Line 955: | ||
| | ''<c:forEach>'' | etichetă de tip iteraţie, acceptând mai multe tipuri de colecţii, suportând parcurgerea submulţimilor; este o alternativă pentru instrucţiunile de iterare ''for'', ''while'' şi ''do-while'' din cadrul Java, care pot fi utilizate în cadrul unui scriplet\\ \\ Atributele asociate etichetei sunt:\\ • ''items'' – informaţia (colecţia) pe care se realizează iteraţia;\\ • ''begin'' – elementul colecţiei de la care se începe iteraţia;\\ • ''end'' – elementul colecţiei la care se termină iteraţia;\\ • ''step'' – pasul cu care se parcurg elementele colecţiei;\\ • ''var'' – denumirea variabilei care expune elementul curent;\\ • ''varStatus'' – denumirea variabilei care expune statutul iteraţiei; <code java> | | ''<c:forEach>'' | etichetă de tip iteraţie, acceptând mai multe tipuri de colecţii, suportând parcurgerea submulţimilor; este o alternativă pentru instrucţiunile de iterare ''for'', ''while'' şi ''do-while'' din cadrul Java, care pot fi utilizate în cadrul unui scriplet\\ \\ Atributele asociate etichetei sunt:\\ • ''items'' – informaţia (colecţia) pe care se realizează iteraţia;\\ • ''begin'' – elementul colecţiei de la care se începe iteraţia;\\ • ''end'' – elementul colecţiei la care se termină iteraţia;\\ • ''step'' – pasul cu care se parcurg elementele colecţiei;\\ • ''var'' – denumirea variabilei care expune elementul curent;\\ • ''varStatus'' – denumirea variabilei care expune statutul iteraţiei; <code java> | ||
| <c:forEach var="myVariabile" items="${myCollection}"> | <c:forEach var="myVariabile" items="${myCollection}"> | ||
| - | <c:out value="${myVariabile}" /><br /> | + | <c:out value="${myVariabile}" /><br /> |
| </c:forEach> | </c:forEach> | ||
| </code> | | </code> | | ||
| | ''<c:forTokens>'' | iterează asupra unor particule, separate prin delimitatori\\ \\ Suportă aceleaşi atribute ca şi <foreach>, la care se adaugă delim, care indică caracterele utilizate ca delimitatori <code java> | | ''<c:forTokens>'' | iterează asupra unor particule, separate prin delimitatori\\ \\ Suportă aceleaşi atribute ca şi <foreach>, la care se adaugă delim, care indică caracterele utilizate ca delimitatori <code java> | ||
| <c:forTokens var="myVariabile" items="${myString}" delim=","> | <c:forTokens var="myVariabile" items="${myString}" delim=","> | ||
| - | <c:out value="${myVariabile}" /><br /> | + | <c:out value="${myVariabile}" /><br /> |
| </c:forTokens> | </c:forTokens> | ||
| </code> | | </code> | | ||
| | ''<c:param>'' | adaugă un parametru la URL-ul specificat în cadrul unei etichete ''<import>'', realizând şi codificarea acestuia\\ \\ Atributele asociate etichetei sunt:\\ • ''name'' – denumirea parametrului care va fi inclus în URL;\\ • ''value'' – valoarea parametrului care va fi inclus în URL; <code java> | | ''<c:param>'' | adaugă un parametru la URL-ul specificat în cadrul unei etichete ''<import>'', realizând şi codificarea acestuia\\ \\ Atributele asociate etichetei sunt:\\ • ''name'' – denumirea parametrului care va fi inclus în URL;\\ • ''value'' – valoarea parametrului care va fi inclus în URL; <code java> | ||
| <c:import var="myVariabile" url="http://www.mysite.com"> | <c:import var="myVariabile" url="http://www.mysite.com"> | ||
| - | <c:param name="param1Name" value="param1Value" /> | + | <c:param name="param1Name" value="param1Value" /> |
| - | <c:param name="param2Name" value="param2Value" /> | + | <c:param name="param2Name" value="param2Value" /> |
| - | ... | + | ... |
| - | <c:param name="paramnName" value="paramnValue" /> | + | <c:param name="paramnName" value="paramnValue" /> |
| </c:import> | </c:import> | ||
| </code> | | </code> | | ||
| Line 1005: | Line 996: | ||
| | ''<fmt:bundle>'' | încarcă o resursă ce urmează să fie utilizată în corpul său, de eticheta ''<message>''\\ \\ Atributele asociate etichetei sunt:\\ • ''basename'' (obligatoriu) – specifică numele de bază pentru resursa care se doreşte a fi încărcată;\\ • ''prefix'' – valoarea care va preceda fiecare denumire de cheie în subeticheta ''<message>''. <code java> | | ''<fmt:bundle>'' | încarcă o resursă ce urmează să fie utilizată în corpul său, de eticheta ''<message>''\\ \\ Atributele asociate etichetei sunt:\\ • ''basename'' (obligatoriu) – specifică numele de bază pentru resursa care se doreşte a fi încărcată;\\ • ''prefix'' – valoarea care va preceda fiecare denumire de cheie în subeticheta ''<message>''. <code java> | ||
| <fmt:bundle basename="myBaseName"> | <fmt:bundle basename="myBaseName"> | ||
| - | <fmt:message key="myPrefix.myKey" /> | + | <fmt:message key="myPrefix.myKey" /> |
| </fmt:bundle> | </fmt:bundle> | ||
| echivalent cu | echivalent cu | ||
| <fmt:bundle basename="myBaseName" prefix="myPrefix"> | <fmt:bundle basename="myBaseName" prefix="myPrefix"> | ||
| - | <fmt:message key="myKey" /> | + | <fmt:message key="myKey" /> |
| </fmt:bundle> | </fmt:bundle> | ||
| </code> | | </code> | | ||
| Line 1040: | Line 1031: | ||
| | ''<sql:update>'' | execută instrucţiunea SQL de actualizare a informaţiilor (de tip ''INSERT'', ''UPDATE'', ''DELETE'') – care nu întoarce date, definită în cadrul corpului folosind atributul sql\\ \\ Atributele asociate etichetei sunt:\\ • ''sql'' – comanda SQL care va fi executată (ar trebui să NU întoarcă un obiect de tip ''ResultSet'');\\ • ''dataSource'' – conexiunea la baza de date care va fi utilizată (suprascrie valoarea implicită);\\ • ''var'' – denumirea variabilei care va stoca numărul de înregistrări afectate de instrucţiune;\\ • ''scope'' – domeniul de vizibilitate al variabilei care va stoca numărul de înregistrări afectate de instrucţiune. <code java> | | ''<sql:update>'' | execută instrucţiunea SQL de actualizare a informaţiilor (de tip ''INSERT'', ''UPDATE'', ''DELETE'') – care nu întoarce date, definită în cadrul corpului folosind atributul sql\\ \\ Atributele asociate etichetei sunt:\\ • ''sql'' – comanda SQL care va fi executată (ar trebui să NU întoarcă un obiect de tip ''ResultSet'');\\ • ''dataSource'' – conexiunea la baza de date care va fi utilizată (suprascrie valoarea implicită);\\ • ''var'' – denumirea variabilei care va stoca numărul de înregistrări afectate de instrucţiune;\\ • ''scope'' – domeniul de vizibilitate al variabilei care va stoca numărul de înregistrări afectate de instrucţiune. <code java> | ||
| <sql:update dataSource="${connection}" var="count"> | <sql:update dataSource="${connection}" var="count"> | ||
| - | <%-- some INSERT, UPDATE or DELETE query --> | + | <%-- some INSERT, UPDATE or DELETE query --> |
| </sql:update> | </sql:update> | ||
| </code> | | </code> | | ||
| | ''<sql:param>'' | stabileşte valoarea unui parametru al unei instrucţiuni SQL, fiind folosit de obicei împreună cu etichetele ''<query>'' sau ''<update>''\\ \\ Atributul asociat etichetei este value prin care se indică valoarea care se doreşte a fi asociată parametrului. <code java> | | ''<sql:param>'' | stabileşte valoarea unui parametru al unei instrucţiuni SQL, fiind folosit de obicei împreună cu etichetele ''<query>'' sau ''<update>''\\ \\ Atributul asociat etichetei este value prin care se indică valoarea care se doreşte a fi asociată parametrului. <code java> | ||
| <sql:query dataSource="${connection}" var="result"> | <sql:query dataSource="${connection}" var="result"> | ||
| - | SELECT FROM table WHERE attribute = ? | + | SELECT FROM table WHERE attribute = ? |
| - | <sql:param value="${missingTableAttributeValue}" /> | + | <sql:param value="${missingTableAttributeValue}" /> |
| </sql:query> | </sql:query> | ||
| </code> <code java> | </code> <code java> | ||
| <sql:update dataSource="${connection}" var="count"> | <sql:update dataSource="${connection}" var="count"> | ||
| - | <%-- some INSERT, UPDATE or DELETE query with one or more | + | <%-- some INSERT, UPDATE or DELETE query with one or more |
| - | missing attribute values --> | + | missing attribute values --> |
| - | <sql:param value="${missingTableAttributeValue}" /> | + | <sql:param value="${missingTableAttributeValue}" /> |
| </sql:update> | </sql:update> | ||
| </code> | | </code> | | ||
| Line 1058: | Line 1049: | ||
| | ''<sql:transaction>'' | oferă elemente care realizează acţiuni folosind un obiect ''Connection'' partajat, executate în cadrul unei tranzacţii; grupează interogări exprimate de etichetele ''<query>'' şi ''<update>'' într-o tranzacţie, asigurând că efectul acestora este fie unitar asupra bazei de date, menţinându-se starea sa iniţială în cazul producerii unei erori.\\ \\ Atributele asociate etichetei sunt:\\ • ''dataSource'' – conexiunea la baza de date care va fi utilizată (suprascrie valoarea implicită);\\ • ''isolation'' – poate avea valorile ''READ_COMMITED'', ''READ_UNCOMMMITTED'', ''REPEATABLE_READ'' sau ''SERIALIZABLE''. <code java> | | ''<sql:transaction>'' | oferă elemente care realizează acţiuni folosind un obiect ''Connection'' partajat, executate în cadrul unei tranzacţii; grupează interogări exprimate de etichetele ''<query>'' şi ''<update>'' într-o tranzacţie, asigurând că efectul acestora este fie unitar asupra bazei de date, menţinându-se starea sa iniţială în cazul producerii unei erori.\\ \\ Atributele asociate etichetei sunt:\\ • ''dataSource'' – conexiunea la baza de date care va fi utilizată (suprascrie valoarea implicită);\\ • ''isolation'' – poate avea valorile ''READ_COMMITED'', ''READ_UNCOMMMITTED'', ''REPEATABLE_READ'' sau ''SERIALIZABLE''. <code java> | ||
| <sql:transaction dataSource="${connection}"> | <sql:transaction dataSource="${connection}"> | ||
| - | <sql:update var="count1"> | + | <sql:update var="count1"> |
| - | <%-- some INSERT queries --> | + | <%-- some INSERT queries --> |
| - | </sql:update> | + | </sql:update> |
| - | <sql:update var="count2"> | + | <sql:update var="count2"> |
| - | <%-- some UPDATE queries --> | + | <%-- some UPDATE queries --> |
| - | </sql:update> | + | </sql:update> |
| - | <sql:update var="count3"> | + | <sql:update var="count3"> |
| - | <%-- some DELETE queries --> | + | <%-- some DELETE queries --> |
| - | </sql:update> | + | </sql:update> |
| </sql:transaction> | </sql:transaction> | ||
| </code> | | </code> | | ||
| Line 1094: | Line 1085: | ||
| <x:parse xml="${myXmlDocument}" var="variable" /> | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| <x:if select="$variable/root/element[index]/attribute != 0" /> | <x:if select="$variable/root/element[index]/attribute != 0" /> | ||
| - | The attribute of the element at index is not null! | + | The attribute of the element at index is not null! |
| </x:if> | </x:if> | ||
| </code> | | </code> | | ||
| Line 1100: | Line 1091: | ||
| <x:parse xml="${myXmlDocument}" var="variable" /> | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| <x:forEach select="$variable/root/element/attribute" var="item" /> | <x:forEach select="$variable/root/element/attribute" var="item" /> | ||
| - | <x:out select="$item" /> | + | <x:out select="$item" /> |
| </x:forEach> | </x:forEach> | ||
| </code> | | </code> | | ||
| Line 1106: | Line 1097: | ||
| <x:parse xml="${myXmlDocument}" var="variable" /> | <x:parse xml="${myXmlDocument}" var="variable" /> | ||
| <x:choose> | <x:choose> | ||
| - | <x:when select="$variable//element/attribute eq value1"> | + | <x:when select="$variable//element/attribute eq value1"> |
| - | Attribute has value 1! | + | Attribute has value 1! |
| - | </x:when> | + | </x:when> |
| - | <x:when select="$variable//element/attribute eq value2"> | + | <x:when select="$variable//element/attribute eq value2"> |
| - | Attribute has value 2! | + | Attribute has value 2! |
| - | </x:when> | + | </x:when> |
| - | ... | + | ... |
| - | <x:when select="$variable//element/attribute eq valuen"> | + | <x:when select="$variable//element/attribute eq valuen"> |
| - | Attribute has value n! | + | Attribute has value n! |
| - | </x:when> | + | </x:when> |
| - | <x:otherwise> | + | <x:otherwise> |
| - | Attribute has unknown value! | + | Attribute has unknown value! |
| - | </x:otherwise> | + | </x:otherwise> |
| </x:choose> | </x:choose> | ||
| </code> | | </code> | | ||
| Line 1128: | Line 1119: | ||
| <x:transform doc="${variable}" xslt="${xslt}" /> | <x:transform doc="${variable}" xslt="${xslt}" /> | ||
| </code> | | </code> | | ||
| - | | ''<x:param>'' | utilizat împreună cu eticheta de transformare pentru a stabili un parametru în foaia de stil XSLT\\ \\ Atributele asociate etichetei sunt:\\ • ''name'' – denumirea parametrului XSLT ce se doreşte a fi stabilit;\\ • ''value'' – valoarea parametrului XSLT ce se doreşte a fi stabilit. <code java> | + | | ''<x:param>'' | utilizat împreună cu eticheta de transformare pentru a stabili un parametru în foaia de stil XSLT\\ \\ Atributele asociate etichetei sunt:\\ • ''name'' – denumirea parametrului XSLT ce se doreşte a fi stabilit;\\ • ''value'' – valoarea parametrului XSLT ce se doreşte a fi stabilit. <code java> |
| <x:transform doc="${variable}" xslt="${xslt}" /> | <x:transform doc="${variable}" xslt="${xslt}" /> | ||
| - | <x:param name="attributeName" value="attributeValue" /> | + | <x:param name="attributeName" value="attributeValue" /> |
| </x:transform> | </x:transform> | ||
| </code> | | </code> | | ||
| Line 1212: | Line 1203: | ||
| public class CustomTag extends SimpleTagSupport { | public class CustomTag extends SimpleTagSupport { | ||
| | | ||
| - | private String customAttribute; | + | private String customAttribute; |
| - | public void setCustomAttribute(String customAttribute) { | + | public void setCustomAttribute(String customAttribute) { |
| - | this. customAttribute = customAttribute; | + | this. customAttribute = customAttribute; |
| - | } | + | } |
| - | public String getCustomAttribute() { | + | public String getCustomAttribute() { |
| - | return customAttribute; | + | return customAttribute; |
| - | } | + | } |
| | | ||
| - | StringWriter stringWriter = new StringWriter(); | + | StringWriter stringWriter = new StringWriter(); |
| - | public void doTag() throws JspException, IOException { | + | public void doTag() throws JspException, IOException { |
| - | if (customAttribute != null) { | + | if (customAttribute != null) { |
| - | // process tag attribute | + | // process tag attribute |
| - | getJspContext().getOut().println(customAttribute); | + | getJspContext().getOut().println(customAttribute); |
| - | } else { | + | } else { |
| - | // get the content from the tag body | + | // get the content from the tag body |
| - | getJspBody().invoke(stringWriter); | + | getJspBody().invoke(stringWriter); |
| - | // process tag body’s content | + | // process tag body’s content |
| - | getJspContext().getOut().println(stringWriter.toString()); | + | getJspContext().getOut().println(stringWriter.toString()); |
| - | } | + | |
| } | } | ||
| + | } | ||
| } | } | ||
| Line 1242: | Line 1233: | ||
| <code xml> | <code xml> | ||
| <taglib> | <taglib> | ||
| - | <tlib-version>1.0</tlib-version> | + | <tlib-version>1.0</tlib-version> |
| - | <jsp-version>2.0</jsp-version> | + | <jsp-version>2.0</jsp-version> |
| - | <short-name>A short description of my custom tag</short-name> | + | <short-name>A short description of my custom tag</short-name> |
| - | <tag> | + | <tag> |
| - | <name>CustomTag</name> | + | <name>CustomTag</name> |
| - | <tag-class>mypackage.CustomTag</tag-class> | + | <tag-class>mypackage.CustomTag</tag-class> |
| - | <body-content>scriptless</body-content> | + | <body-content>scriptless</body-content> |
| - | <attribute> | + | <attribute> |
| - | <name>customAttribute</name> | + | <name>customAttribute</name> |
| - | <required>true</true> | + | <required>true</true> |
| - | <type>java.lang.Integer</type> | + | <type>java.lang.Integer</type> |
| - | <fragment>false</fragment> | + | <fragment>false</fragment> |
| - | </attribute> | + | </attribute> |
| - | </tag> | + | </tag> |
| </taglib> | </taglib> | ||
| </code> | </code> | ||
| Line 1270: | Line 1261: | ||
| ... | ... | ||
| <customPrefix:CustomTag customAttribute="0"> | <customPrefix:CustomTag customAttribute="0"> | ||
| - | Some custom tag body | + | Some custom tag body |
| </customPrefix:CustomTag> | </customPrefix:CustomTag> | ||
| ... | ... | ||
| Line 1281: | Line 1272: | ||
| ===== Activitate de Laborator ===== | ===== Activitate de Laborator ===== | ||
| - | * {{ :laboratoare:laborator08:aipi2014-lab08-eclipseee.zip }} (proiect EclipseEE ) | + | ==== Structura aplicației web BookStore ==== |
| - | * {{ :laboratoare:laborator08:aipi2014-lab08-netbeans.zip }} (proiect NetBeans ) | + | Se doreşte implementarea unei interfeţe grafice cu utilizatorul (dezvoltată sub forma unei aplicaţii web, folosind serverul Apache Tomcat 8.x) pentru gestiunea informaţiilor reţinute într-o bază de date, aceasta urmând a fi utilizată de un sistem ERP destinat unei librării care comercializează doar cărţi. |
| - | * {{ :laboratoare:laborator08:aipi2014-lab08-noide.zip }} (proiect NoIDE - fără mediu integrat de dezvoltare) | + | Sistemul informatic va putea fi accesat de: |
| + | * un utilizator tip **administrator**, care va manipula – prin intermediul aplicaţiei – informaţiile din baza de date; acesta are la dispoziție operații de adăugare, editare și ștergere pentru oricare dintre tabele; | ||
| + | * un utilizator tip **client**, care va formula o comandă după ce şi-a specificat un anumit coş de cumpărături ca urmare a consultării catalogului de produse; pe baza comenzii va fi emisă o factură (''invoice_header''), caracterizată printr-un număr de identificare (''identification_number''), data la care a fost emisă (''issue_date''), stare (''state'') și identificatorul utilizatorului către care va fi transmisă (''user_id''); aceasta conține la rândul ei mai multe înregistrări, corespunzătoare cărților care au fost cumpărate (''invoice_line''), definite de factura corespunzătoare (''invoice_header_id''), identificatorul formatului de prezentare al cărții (''book_presentation_id'') și cantitatea (''quantity''). | ||
| - | **1.** [**0 puncte**] Să se instaleze baza de date prin rularea script-ului ''Laborator08.sql''. | + | Pentru fiecare funcționalitate există o pagină dedicată, gestionată de câte o clasă Java Servlet și de o pagină .jsp: pagina de autentificare (''LoginServlet'' / ''login.jsp'') de unde, în funcţie de rolul utilizatorului se trece la pagina de tip administrator (''AdministratorServlet'' / ''administrator.jsp'') respectiv pagina de tip client (''ClientServlet'' / ''client.jsp''). Pentru fiecare pagină, cererea primită din navigator este preluată de clasa servlet corespunzătoare, unde sunt realizate procesările ce țin de logica aplicației, inclusiv accesarea informațiilor din baza de date. Prezentarea informațiilor astfel obținute este delegată către pagina .jsp, către care se transferă contextul. Datele care se doresc a fi vizualizate sunt transmise dinspre servlet către pagina JSP sub formă de atribute. În acest mod se construiește răspunsul care va fi trimis către navigator. |
| - | <note>Conţinutul script-ului'' Laborator08.sql'' este identic cu cel din ''Laborator03.sql'', astfel că această etapă nu mai este necesară în cazul în care a fost deja realizată.</note> | + | {{ :laboratoare:laborator05:bookstore_webapplication_structure.png?nolink&300 }} |
| - | **2.** [**0 puncte**] În cazul Unix, daţi drepturi de execuţie tuturor fişierelor .sh din directorul ''bin'' al serverului Apache Tomcat, întrucât acestea sunt apelate la rândul lor de ''startup.sh'', respectiv ''shutdown.sh''. | + | <html> |
| + | <center> | ||
| + | </html> | ||
| + | **Structura aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| - | <code bash> | + | Atributele care sunt transmise între clasele servlet și paginile .jsp sunt: |
| - | aipi2014@ubuntu:~/apache-tomcat-8.0.15$ cd bin | + | - LoginServlet → login.jsp |
| - | aipi2014@ubuntu:~/apache-tomcat-8.0.15/bin$ sudo chmod +x *.sh | + | * ''Constants.ERROR_ATTRIBUTE'' - furnizează informații cu privire la rezultatul operației de autentificare a unui utilizator în cadrul aplicației web (succes, eșec); |
| + | - AdministratorServlet → administrator.jsp | ||
| + | * ''Constants.DISPLAY'' - identificatorul utilizatorului autentificat în cadrul aplicației web (format din prenume și nume); | ||
| + | * ''Constants.DATABASE_STRUCTURE'' - structura bazei de date, formată din lista tuturor tabelelor; | ||
| + | * ''Constants.CURRENT_TABLE'' - denumirea tabelei vizualizată la un moment dat de timp; | ||
| + | * ''Constants.ATTRIBUTES'' - structura tabelei vizualizată la un moment dat de timp, conținând lista tuturor atributelor; | ||
| + | * ''Constants.IDENTIFIER'' - denumirea identificatorului în lista de atribute; | ||
| + | * ''Constants.IDENTIFIER_INDEX'' - poziția identificatorului în lista de atribute; | ||
| + | * ''Constants.IDENTIFIER_NEXT_VALUE'' - valoarea identificatorului unei înregistrări pentru adăugare; | ||
| + | * ''Constants.TABLE_CONTENT'' - conținutul tabelei vizualizate la un moment dat de timp, conținând lista tuturor înregistrărilor, pentru fiecare înregistrare fiind reținute valorile tuturor atributelor; | ||
| + | * ''Constants.IDENTIFIER_VALUE_OF_RECORD_TO_BE_UPDATED'' - valoarea identificatorului unei înregistrări selectate pentru modificare sau ștergere, în situația în care aceasta a fost selectată; | ||
| + | - ClientServlet → client.jsp | ||
| + | * ''Constants.DISPLAY'' - identificatorul utilizatorului autentificat în cadrul aplicației web (format din prenume și nume); | ||
| + | * ''Constants.BOOKS'' - lista cărților care vor fi vizualizate, împreună cu toate atributele, în funcție de criteriile de filtrare care au fost precizate; | ||
| + | * ''Constants.ERROR_MESSAGE'' - mesaj de eroare legat de procesarea coșului de cumpărături; | ||
| + | * ''Constants.SHOPPING_CART'' - conținutul coșului de cumpărături (identificatorul formatului de prezentare și cantitatea solicitată); | ||
| + | * ''Constants.FORMATS_FILTER'' - lista cu criteriile de sortare în funcție de formatul de prezentare; | ||
| + | * ''Constants.LANGUAGES_FILTER'' - lista cu criteriile de sortare în funcție de limbă; | ||
| + | * ''Constants.CATEGORIES_FILTER'' - lista cu criteriile de sortare în funcție de categorie; | ||
| + | * ''Constants.CURRENT_RECORDS_PER_PAGE'' - numărul maxim de înregistrări care poate fi vizualizat pe o pagină la un moment dat; | ||
| + | * ''Constants.CURRENT_PAGE'' - pagina vizualizată la un moment dat; | ||
| + | * ''Constants.FILTER_CHANGE'' - indică dacă informațiile au fost reîncărcate din baza de date datorită modificării criteriilor de filtrare; | ||
| + | * ''Constants.FORMATS_LIST'' - lista cu toate formatele de prezentare disponibile; | ||
| + | * ''Constants.LANGUAGES_LIST'' - lista cu toate limbile disponibile; | ||
| + | * ''Constants.CATEGORIES_LIST'' - lista cu toate categoriile disponibile. | ||
| + | |||
| + | {{ :laboratoare:laborator04:bookstore_webapplication_loginservlet.png?nolink&300 }} | ||
| + | |||
| + | <html> | ||
| + | <center> | ||
| + | </html> | ||
| + | **Pagina de tip autentificare din cadrul aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| + | |||
| + | {{ :laboratoare:laborator04:bookstore_webapplication_administratorservlet.png?nolink&800 }} | ||
| + | |||
| + | <html> | ||
| + | <center> | ||
| + | </html> | ||
| + | **Pagina de tip administrator din cadrul aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| + | |||
| + | {{ :laboratoare:laborator04:bookstore_webapplication_clientservlet.png?nolink&800 }} | ||
| + | |||
| + | <html> | ||
| + | <center> | ||
| + | </html> | ||
| + | **Pagina de tip client din cadrul aplicaţiei BookStore** | ||
| + | <html> | ||
| + | </center> | ||
| + | </html> | ||
| + | |||
| + | ===== ===== | ||
| + | |||
| + | **0**. Să se cloneze în directorul de pe discul local conținutul depozitului la distanță de la [[https://www.github.com/aipi2015/Laborator05|]]. În urma acestei operații, directorul ''Laborator05'' va trebui să conțină subdirectorul ''labtasks'', fișierele ''README.md'' și ''LICENSE''. <code> | ||
| + | student@aipi2015:~$ git clone https://www.github.com/aipi2015/Laborator05.git | ||
| </code> | </code> | ||
| - | **3.** [**0 puncte**] Să se completeze în clasa ''Constants'' din pachetul ''ro.pub.cs.aipi.lab08.general'' valorile pentru utilizatorul şi parola pentru accesarea bazei de date. | + | **1**. Să se ruleze, folosind MySQL Workbench (sau alt utilitar similar), scriptul ''Laborator05l.sql'', localizat în directorul ''scripts''. Acesta instalează baza de date ''bookstore''. |
| - | **4.** [**0 puncte**] | + | <note>În cazul în care baza de date ''bookstore'' este deja instalată, nu mai este necesar să se ruleze acest script.</note> |
| - | ==== No IDE ==== | + | <note important>Această operație poate dura o perioadă de timp îndelungată, în funcție de configurațiile mașinilor pe care se lucrează.</note> |
| - | Să se specifice variabilele de mediu ''JAVA_HOME'' şi ''JAVA_JRE'' în script-urile ''setClasspath[.bat|.sh]'' (din directorul ''bin'' al serverului Apache Tomcat). | + | **2.** În cazul Unix, daţi drepturi de execuţie tuturor fişierelor .sh din directorul ''bin'' al serverului Apache Tomcat, întrucât acestea sunt apelate la rândul lor de ''startup.sh'', respectiv ''shutdown.sh''. |
| - | Să se "publice" aplicaţia BookStore în contextul serverului Apache Tomcat prin rularea script-ului ''deploy[.bat|.sh]'' din directorul ''scripts''. | + | <code bash> |
| + | student@aipi2015:~/apache-tomcat-8.0.28$ cd bin | ||
| + | student@aipi2015:~/apache-tomcat-8.0.28/bin$ sudo chmod +x *.sh | ||
| + | </code> | ||
| - | <note>De remarcat faptul că aplicaţia ''BookStore'' se găseşte în directorul ''webapps'' al serverului Apache Tomcat.</note> | + | **3.** Modificați în interfața ''Constants'' din pachetul ''ro.pub.cs.aipi.lab05.general'' informațiile necesare obținerii drepturilor de acces la baza de date (nume de utilizator, parola). |
| - | <note tip>În cazul Unix, daţi drepturi de execuţie fişierului ''deploy.sh''. În cazul în care calea către Java există în variabila de mediu ''$PATH'', puteţi comenta linia care face acest lucru precum şi apelul compilatorului ''javac'' de la adresa absolută.</note> | + | **4.** Să se configureze mediile integrate de dezvoltare astfel încât acestea să fie interfațate cu serverul web Apache Tomcat 8.x. Mai multe informații cu privire la modul în care poate fi realizată interfațarea dintre aceste componente pot fi găsite la [[:utile:apache_tomcat|serverul Apache Tomcat]]. |
| ==== Eclipse ==== | ==== Eclipse ==== | ||
| - | Să se creeze o [[:laboratoare:laborator07#eclipse|referinţă către serverul Apache Tomcat]] care să fie adăugată la proiectul BookStore. | + | Să se creeze o referinţă către serverul HTTP Apache Tomcat care să fie adăugată la proiectul 04-BookStore-JavaServlets. |
| Să se deschidă proiectul folosind opţiunea //File// → //Import// → //General// → //Existing Project into Workspace..//. | Să se deschidă proiectul folosind opţiunea //File// → //Import// → //General// → //Existing Project into Workspace..//. | ||
| - | Se accesează opţiunea //Run as...// → //Run On Server// din meniul contextual al aplicaţiei BookStore (right-click), bifându-se opţiunea //Always use this server when running this project//. | + | Se accesează opţiunea //Run as...// → //Run On Server// din meniul contextual al aplicaţiei 04-BookStore-JavaServlets (right-click), bifându-se opţiunea //Always use this server when running this project//. |
| - | {{ :laboratoare:laborator07:eclipse05.png?nolink&600 }} | + | {{ :laboratoare:laborator04:eclipse01.png?nolink }} |
| - | {{ :laboratoare:laborator07:eclipse06.png?nolink&600 }} | + | {{ :laboratoare:laborator04:eclipse02.png?nolink }} |
| - | {{ :laboratoare:laborator07:eclipse07.png?nolink&600 }} | + | {{ :laboratoare:laborator05:eclipse03.png?nolink }} |
| ==== NetBeans ==== | ==== NetBeans ==== | ||
| - | Să se creeze o [[:laboratoare:laborator07#netbeans|referinţă către serverul Apache Tomcat]] care să fie adăugată la proiectul BookStore. | + | Să se creeze o referinţă către serverul HTTP Apache Tomcat care să fie adăugată la proiectul 05-BookStore-JSP. |
| Se accesează opţiunea //Deploy// din meniul contextual al proiectului (accesat cu right-click). | Se accesează opţiunea //Deploy// din meniul contextual al proiectului (accesat cu right-click). | ||
| - | {{ :laboratoare:laborator07:netbeans05.png?nolink }} | + | {{ :laboratoare:laborator04:netbeans01.png?nolink }} |
| - | <note tip>Alternativ, se poate porni serverul Apache Tomcat și dezvolta aplicația web în contextul său și prin opțiunea //Run// (F6), care va lansa și browser-ul implicit în care va fi prezentată pagina principală a aplicației web.</note> | + | Alternativ, se poate porni serverul Apache Tomcat și dezvolta aplicația web în contextul său și prin opțiunea //Run// (F6), care va lansa și browser-ul implicit în care va fi prezentată pagina principală a aplicației web. |
| ===== ===== | ===== ===== | ||
| - | |||
| - | **5.** [**0 puncte**] Să se testeze aplicaţia prin accesarea adresei http://localhost:8080/BookStore/. | ||
| - | <note tip> | + | În fișierul ''catalina.properties'' din directorul ''conf'' al serverului web Apache Tomcat 8.x, suprascrieți proprietatea ''org.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING'' astfel încât să se folosească o politică permisivă în privința caracterelor ''"'' imbricate (aceasta va avea valoarea ''false''). O astfel de configurație este necesară pentru a putea fi accesate atribute ale contextului paginii JSP din cadrul unor scripleți. |
| - | Se poate consulta script-ul ''Laborator08.sql'' există exemple de utilizatori care pot fi folosite pentru accesarea paginilor de administrator, respectiv de client. | + | |
| - | * administrator: ''daniel.wright'' / ''-'' | + | |
| - | * client: ''richard.allen'' / ''-'' | + | |
| - | </note> | + | |
| - | **6.** [**0 puncte**] Să se acceseze pagina de administrator şi să se testeze funcţionalităţile implementate în cadrul acesteia (adăugare, editare, ştergere). | + | <file catalina.properties> |
| + | # other properties | ||
| + | org.apache.jasper.compiler.Parser.STRICT_QUOTE_ESCAPING=false | ||
| + | </file> | ||
| - | **7.** [**10 puncte**] În pagina ''client.jsp'', să se construiască clauza ''WHERE'' a interogării corespunzătoare tabelei ''book'', astfel încât conţinutul tabelei să fie filtrat după valoarea selectată din lista de colecţii / domenii. | + | ==== Eclipse ==== |
| - | <note tip>Filtrarea se va realiza numai în cazul valorile selectate sunt diferite de şirul de caractere 'all' (= ''Constants.ALL''). În cazul în care vor fi specificate ambele valori, condiţia de filtrare va presupune îndeplinirea ambelor criterii.</note> | + | Fișierul ''catalina.properties'' poate fi editat din mediul integrat de dezvoltare, în cazul în care sunt preluate informațiile din configurația de rulare specifică spațiului de lucru curent. În acest sens, în secțiunea //Properties// asociată serverului Apache Tomcat 8.x (accesibilă prin intermediul meniului contextual, din panoul //Servers//), atributul //Location// trebuie să refere metadatele din cadrul spațiului de lucru curent (având valoarea //[workspace metadata]//). În situația în care este precizată o altă valoare, se accesează butonul //Switch Location//. |
| - | <note tip>Pentru fiecare colecţie / domeniu există mai mulţi identificatori în tabelele aferente (colecţii / domenii) care au denumirea respectivă, astfel încât interogarea va avea forma: <code mysql> | + | {{ :laboratoare:laborator04:eclipse04.png?nolink }} |
| - | SELECT ... FROM book | + | |
| - | WHERE | + | |
| - | series_id IN (SELECT id FROM series WHERE name='... ') | + | |
| - | AND | + | |
| - | genre_id IN (SELECT id FROM genre WHERE name= '... '); | + | |
| - | </code></note> | + | |
| - | <note tip>În specificaţia EL 2.2 concatenarea a două şiruri de caractere se face prin alăturarea lor (operatorul + pentru şiruri de caractere este definit în EL 3.0): <code java> | + | În panoul //Project Explorer//, în secțiunea //Servers//, se editează fișierul ''catalina.properties'' corespunzător configurației de server Apache Tomcat 8.x pe care este rulată aplicația web. |
| - | <c:set scope= "request" var= "myvar" value="${var1} some text ${var2}" /> | + | |
| - | </code></note> | + | |
| - | **8.** [**35 puncte**] În pachetul ''ro.pub.cs.aipi.lab08.servlets'', în clasa ''ClientServlet'' să se completeze metoda ''doPost()'' pentru a crea conţinutul coşului de cumpărături, ţinând cont de situaţia în care pentru un produs care există deja în coşul de cumpărături se poate actualiza cantitatea. | + | {{ :laboratoare:laborator04:eclipse05.png?nolink }} |
| - | În situaţia în care solicitarea pentru un produs depăşeşte stocul existent, aceasta nu va fi luată în considerare, afişându-se un mesaj de eroare. | + | ==== NetBeans ==== |
| - | Dacă un produs există deja în coşul de cumpărături, valoarea respectivă va fi suprascrisă. Dacă valoarea este 0, produsul va fi şters din coşul de cumpărături. | + | Fișierul ''catalina.properties'' va fi editat manual, după ce se identifică locația la care este instalată instanța serverului Apache Tomcat 8.x pe care este rulată aplicația web. Aceasta poate fi determinată din secțiunea //Servers// corespunzătoare, în panoul //Connection//, fiind referită prin atributul //Catalina Base//. |
| - | <note tip>Parametrul care conţine identificatorul cărţii care se doreşte adăugată în coş are forma ''copies_bookId'' (de exemplu, ''copies_1'', pentru ''bookId=1''). Se verifică dacă parametrul are această formă şi în acest caz, identificatorul cărţii se obţine prin parsarea acestui câmp, iar numărul de exemplare prin apelul ''request.getParameter(parameter)''. | + | {{ :laboratoare:laborator04:netbeans02.png?nolink }} |
| - | Dacă în coşul de cumpărături există o intrare cu acelaşi ''bookId'', aceasta este actualizată (suprascrisă / ştearsă în cazul în care numărul de exemplare este 0), altfel se introduce o nouă intrare, nu înainte de a se verifica faptul că operaţia este posibilă (numărul de exemplare solicitat nu depăşeşte stocul). În cazul în care sunt solicitate mai multe exemplare decât sunt disponibile, se va afişa un mesaj de eroare. | + | ===== ===== |
| + | |||
| + | **5.** Să se testeze aplicaţia prin accesarea adresei [[http://localhost:8080/05-BookStore-JSP/|]]. | ||
| - | Coşul de cumpărături este un obiect ''ArrayList<Record>'' unde ca atribut se reţine identificatorul cărţii, iar ca valoare numărul de exemplare.</note> | + | Se poate consulta script-ul ''Laborator05l.sql'' există exemple de utilizatori care pot fi folosite pentru accesarea paginilor de administrator, respectiv de client. |
| + | * administrator: mary.smith / - | ||
| + | * client: linda.williams / - | ||
| - | **9.** [**15 puncte**] În pagina ''client.jsp'', să se afişeze conţinutul coşului de cumpărături. | + | **6.** Să se acceseze pagina de tip administrator şi să se testeze funcţionalităţile implementate în cadrul acesteia (adăugare, editare, ştergere). |
| - | În coşul de cumpărături se va afişa numărul de exemplare comandate, titlul cărţii, editura şi anul, precum şi suma pentru fiecare produs în parte, respectiv preţul total pentru întreg coşul de cumpărături. | + | **7.** Să se acceseze pagina de tip client. Să se implementeze funcționalitatea corespunzătoare filtrării în funcție de limbile în care sunt disponibile cărțile din librărie. Un utilizator poate adăuga o valoare din lista de limbi disponibile. Filtrarea se face în funcție de limbile selectate, pentru acele formate de prezentare a cărții care conțin cel puțin una dintre aceste valori. În situația în care nu s-a specificat nici o valoare, sunt incluse toate volumele comercializate. Un utilizator poate șterge una sau mai multe dintre limbile selectate anterior. |
| - | {{ :laboratoare:laborator07:exercitiile9_10.png?nolink }} | + | {{ :laboratoare:laborator04:activitate_de_laborator_exercitiu07.png?nolink }} |
| - | <note tip>În cazul în care rezultatul unei interogări se află într-un obiect ''result'', elementele sale pot fi obţinute prin indexare, începând cu 0: ''result.rows[0]'', ''result.rows[1]'', ..., ''result.rows[n-1]''. Acestea sunt nişte tablouri care conţin toate atributele interogării, acestea putând fi accesate tot prin indexare, prin numele lor: ''result.rows[k]['attribute1']'', ''result.rows[k]['attribute2']'', ..., ''result.rows[k]['attributem']''.</note> | + | <spoiler|Indicații de Rezolvare> |
| + | În pagina ''client.jsp'' (accesibilă în directorul ''WebContent'' din proiectul //Eclipse//, respectiv în directorul ''web'' din proiectul //NetBeans//), se afișează lista cu limbile în funcție de care se realizează filtrarea, pentru fiecare dintre acestea atașându-se un buton pentru eliminarea valorii respective. | ||
| - | **10.** [**10 puncte**] În pagina ''client.jsp'' să se să se adauge două butoane prin care se poate anula, respectiv finaliza o comandă (o comandă conţine produsele selectate în coşul de cumpărături). | + | Se iterează pe lista cu filtre în funcție de limbi (atributul ''languagesFilter'', transmis din ''ClientServlet''), iar pentru fiecare element: |
| + | * se afișează șirul de caractere conținând limba; | ||
| + | * se afișează un element de tip [[http://www.w3schools.com/tags/tag_input.asp|<input>]], având atributul ''type'' cu valoarea ''image'' și denumirea ''delete_language: _{language_name}'' (valori reținutr de constantele ''DELETE_BUTTON_NAME'' și ''LANGUAGE'' din interfața ''Constants''). Resursa grafică se regăsește în directorul ''images'', în subdirectorul ''user_interface'', având denumirea ''delete.png'' (se recomandă să se forțeze dimensiunea acesteia la 16x16, prin specificarea atributelor ''width'' și ''height''). | ||
| - | <note tip>Resursele grafice pentru butoane se regăsesc în directorul ''images'', în subdirectorul ''user_interface'', având denumirile: | + | Elementele vor fi incluse ca linii în cadrul unui tabel (''<tr><td>...</td></tr>''). |
| - | * ''remove_from_shopping_cart.png''; | + | |
| - | * ''shopping_cart_accept.png''; | + | |
| - | </note> | + | |
| - | **11.** [**40 puncte**] În pachetul ''ro.pub.cs.aipi.lab08.servlets'', în clasa ''ClientServlet'', metoda ''doPost()'', să se implementeze operaţia pentru anularea, respectiv finalizarea unei comenzi. | + | Iterația pe elementele unei liste în cadrul unei pagini JSP se face folosind eticheta [[http://www.tutorialspoint.com/jsp/jstl_core_foreach_tag.htm|<c:forEach>]], obiectul care se dorește a fi parcurs fiind referit prin atributul ''items''. |
| - | <note tip>În cazul anulării unei comenzi, se şterge conţinutul obiectului ''shoppingCart''. | + | Valoarea unei constante din cadrul interfeței ''ro.pub.cs.aipi.lab05.general.Constants'' poate fi obținută prin evaluarea unei expresii, încadrată între elementele ''<%= ... %>''. |
| - | În cazul finalizării unei comenzi, trebuie realizate următoarele operaţii: | + | În clasa ''ClientServlet'' din pachetul ''ro.pub.cs.aipi.lab05.servlets'', se tratează acțiunile corespunzătoare evenimentelor de tip apăsare a butoanelor de tip ''insert'', respectiv ''delete'' corespunzătoare filtrului în funcție de limba în care a fost selectată cartea. |
| - | * adăugarea unei înregistrări în tabela ''invoice''; pentru generarea aleatoare a câmpului ''identification_number'' se poate folosi metoda ''Utilities.generateInvoiceNumber();'' ca dată de emitere (câmpul ''issue_date'') se va completa data calendaristică curentă (prin funcţia MySQL ''CURDATE()''), starea (coloana ''state'') este emisă (''issued''), iar identificatorul utilizatorului (atributul ''personal_identifier'') va fi dedus din ''userDisplayName'' care este concatenarea dintre prenumele şi numele reţinute în tabela ''user''; | + | * pentru parametrii având denumirea de tipul ''insert_language: '' (valori conținute de constantele ''INSERT_BUTTON_NAME'', respectiv ''LANGUAGE'' din interfața ''Constants''), se obține denumirea limbii (ca valoare atașată parametrului, prin invocarea metodei ''request.getParameter(parameter)''), se verifică dacă aceasta nu este conținută în lista de limbi în funcție de care se face filtrarea și, în caz afirmativ, este adăugată la listă, marcându-se faptul că lista de filtre a fost modificată (parametrul ''filterChange'' de tip ''boolean''); |
| - | * pentru fiecare element din coşul de cumpărături: | + | * pentru parametrii având denumirea de tipul ''delete_language: _{language_name}'' (valori conținute de constantele ''DELETE_BUTTON_NAME'', respectiv ''LANGUAGE'' din interfața ''Constants''), se obține denumirea limbii (prin parsarea denumirii parametrului), se verifică dacă aceasta este conținută în lista de limbi în funcție de care se face filtrarea și, în caz afirmativ, este ștearsă din listă, marcându-se faptul că lista de filtre a fost modificată (parametrul ''filterChange'' de tip ''boolean''). |
| - | * se compară numărul de exemplare din coşul de cumpărături cu stocul din tabela ''book'' şi dacă relaţia este de tipul mai mic sau egal, se actualizează stocul (scăzând exemplarele comercializate); | + | |
| - | * se adaugă o înregistrare în tabela ''invoice_detail''; | + | |
| - | * se goleşte coşul de cumpărături. | + | |
| - | </note> | + | |
| - | <note important>În situația în care sunt realizate modificări la nivelul coșului de cumpărături (pe obiectul ''shoppingCart''), starea acestuia va trebui consemnată în cadrul sesiunii, printr-un apel de tipul: <code java> | + | <note tip>Se poate utiliza ca model implementarea corespunzătoare filtrării în funcție de formatul de prezentare a cărții.</note> |
| + | </spoiler> | ||
| + | |||
| + | **8.** În pachetul ''ro.pub.cs.aipi.lab05.servlets'', în clasa ''ClientServlet'' să se completeze metoda ''doPost()'' pentru a crea conţinutul coşului de cumpărături, ţinând cont de situaţia în care pentru un produs deja existent să se poate actualiza cantitatea, astfel: dacă un produs există deja în coşul de cumpărături, cantitatea respectivă va fi suprascrisă, iar dacă aceasta este 0, produsul va fi şters din coşul de cumpărături. | ||
| + | |||
| + | <spoiler|Indicații de Rezolvare> | ||
| + | În cazul în care se apasă un buton atașat unui câmp text pentru precizarea unei cantități pentru un anumit format de prezentare a unei cărți, este necesar să se realizeze următoarele operații: | ||
| + | * se determină identificatorul formatului de prezentare a cărții și cantitatea corespunzătoare: | ||
| + | |||
| + | {{ :laboratoare:laborator04:activitate_de_laborator_exercitiu08.png?nolink&700 }} | ||
| + | |||
| + | **a)** **butonul** are denumirea ''insert_shoppingcart_{book_presentation_id}'' unde ''book_presentation_id'' reprezintă identificatorul formatului de prezentare a cărții (de exemplu, ''insert_shoppingcart_1'' pentru formatul de identificare a cărții cu identificatorul 1); prin parsarea denumirii acestui parametru se obține identificatorul formatului de prezentare a cărții: <code java> | ||
| + | if (parameter.startsWith(Constants.INSERT_BUTTON_NAME.toLowerCase() + "_" + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "_") && parameter.endsWith(".x")) { | ||
| + | String bookPresentationId = parameter.substring(parameter.lastIndexOf("_") + 1, parameter.indexOf(".x")); | ||
| + | } | ||
| + | </code> | ||
| + | <note tip>Pentru un element de tip ''<input>'' având atributul ''type'' cu valoarea ''submit'', se transmit ca parametrii coordonatele la care se găsește mouse-ul în momentul în care se produce evenimentul de tip apăsare, acestea având aceeași denumire, sufixată de ''.x'', respectiv ''.y''. Este important ca un singur parametru să fie procesat, în acest caz.</note> | ||
| + | **b)** **câmpul text** ce conține cantitatea corespunzătoare are denumirea ''copies_shoppingcart_{book_presentation_id}'' unde ''book_presentation_id'' reprezintă identificatorul formatului de prezentare a cărții (de exemplu, ''copies_shoppingcart_1'' pentru formatul de identificare a cărții cu identificatorul 1); valoarea corespunzătoare acestui parametru reprezintă cantitatea solicitată: <code java> | ||
| + | if (parameter.startsWith(Constants.INSERT_BUTTON_NAME.toLowerCase() + "_" + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "_") && parameter.endsWith(".x")) { | ||
| + | String quantity = request.getParameter(Constants.COPIES.toLowerCase() + "_" + Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()) + "_" + bookPresentationId); | ||
| + | } | ||
| + | </code> | ||
| + | <note tip>Vor fi transmiși un număr de parametrii egal cu numărul de câmpuri text afișate în cadrul paginii Internet, însă va fi luat în considerare doar cel asociat butonului care a fost apăsat, chiar dacă pot fi introduse valori și în cadrul acestora. Obținerea valorii transmise prin intermediul unui parametru se realizează prin apelul ''request.getParameter(parameter)''.</note> | ||
| + | * se iterează asupra conținutului coșului de cumpărături (obiectul ''shoppingCart'', transmis prin intermediul sesiunii, este de tipul ''List<Record>'' unde ca atribut se reţine identificatorul formatului de prezentare a cărţii, iar ca valoare cantitatea): | ||
| + | * dacă se identifică un element având același identificator al formatului de prezentare a cărții: | ||
| + | * în situația în care cantitatea este nenulă, aceasta este modificată; | ||
| + | * în situația în care cantitatea este nulă, aceasta este ștearsă; | ||
| + | * dacă nu se identifică un element având același identificator al formatului de prezentare a cărții, acesta este adăugată. | ||
| + | |||
| + | <note important> | ||
| + | Obiectul ''shoppingCart'' astfel modificat trebuie să fie transmis prin intermediul sesiunii pentru a fi persistent, având în vedere faptul că protocolul HTTP nu reține și starea. | ||
| + | <code java> | ||
| session.setAttribute(Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()), shoppingCart); | session.setAttribute(Utilities.removeSpaces(Constants.SHOPPING_CART.toLowerCase()), shoppingCart); | ||
| </code> | </code> | ||
| </note> | </note> | ||
| + | </spoiler> | ||
| - | **12.** [**10 puncte**] Să se implementeze operaţia de deautentificare printr-un buton plasat sub mesajul de întâmpinare pentru fiecare utilizator în pagina de tip client. În această situație, utilizatorul se va întoarce în pagina de autentificare (''login.jsp''). | + | **9.** În pagina ''client.jsp'', să se implementeze funcționalitatea necesară pentru a se vizualiza coţinutul coşului de cumpărături. Se va afişa numărul de exemplare comandate, titlul cărţii, formatul de prezentare și limba, precum şi suma pentru fiecare produs în parte, respectiv preţul total pentru întregul coş de cumpărături. |
| - | {{ :laboratoare:laborator07:exercitiul12.png?nolink }} | + | {{ :laboratoare:laborator04:activitate_de_laborator_exercitiu09.png?nolink }} |
| - | <note tip>Se va lucra în clasa ''ClientServlet'', plasarea butonului realizându-se în pagina ''client.jsp''.</note> | + | <spoiler|Indicații de Rezolvare> |
| + | Se verifică dacă lista corespunzătoare coșului de cumpărături, accesibilă în atributul ''shoppingCart'', conține sau nu elemente. În acest scop se va folosi un element [[http://www.tutorialspoint.com/jsp/jstl_core_choose_tag.htm|<c:choose>]]: | ||
| + | * în cazul în care lista nu este vidă (condiția de verificare este ''<c:when test="${not empty shoppingCart}">''), se afișează conținutul coșului de cumpărături; | ||
| + | * în cazul în care lista este vidă (condiția de verificare este ''<c:otherwise>''), se afișează mesajul conținut de constanta ''EMPTY_CART'', definită în interfața ''Constants''. | ||
| - | <note tip>Puteți folosi ca model implementarea din cadrul paginii de administrator (clasa ''AdministratorServlet'' / pagina ''administrator.jsp'').</note> | + | <code> |
| + | <c:choose> | ||
| + | <c:when test="${not empty shoppingCart}"> | ||
| + | <%-- display shopping cart content --%> | ||
| + | </c:when> | ||
| + | <c:otherwise> | ||
| + | <%-- display Constants.EMPTY_CART message --%> | ||
| + | </c:otherwise> | ||
| + | </c:choose> | ||
| + | </code> | ||
| - | <note important>Înainte de transferul contextului către pagina care gestionează operația de autentificare, se vor elimina din cerere toți parametrii, se va invalida sesiunea curentă (printr-un apel al metodei ''invalidate()'' pe obiectul ''session'') și se vor îndepărta preferințele cu privire la filtre.</note> | + | Se iterează asupra conținutului coșului de cumpărături (obiectul ''shoppingCart''), determinându-se, pentru fiecare element, identificatorul formatului de prezentare (atributul) și cantitatea (valoarea). Pentru a crea un atribut și pentru a-l inițializa cu o anumită valoare, se poate folosi eticheta [[http://www.tutorialspoint.com/jsp/jstl_core_set_tag.htm|<c:set>]]. |
| + | |||
| + | <code> | ||
| + | <c:forEach var="shoppingCartContent" items="${shoppingCart}"> | ||
| + | <c:set var="bookPresentationIdentifier" value="${shoppingCartContent.attribute}" /> | ||
| + | <c:set var="quantity" value="${shoppingCartContent.value}" /> | ||
| + | <%-- do other processing --%> | ||
| + | </c:forEach> | ||
| + | </code> | ||
| + | |||
| + | Prețul unitar pentru un format de prezentare poate fi obținut apelând metoda ''getPrice()'' din clasa ''BookPresentationManager'', ce primește ca argument identificatorul formatului de prezentare respectiv. | ||
| + | |||
| + | Informațiile cu privire la un format de prezentare (titlul, formatul de prezentare și limba) pot fi obținute apelând metoda ''getInformation()'' din clasa ''BookPresentationManager'', ce primește ca argument identificatorul formatului de prezentare respectiv. Acesta întoarce o listă de obiecte de tip șir de caractere. | ||
| + | |||
| + | Instanțierea unui obiect de tipul ''BookPresentationManager'', necesar pentru invocarea metodelor ce furnizează informațiile ce se doresc a fi afișate, se face prin intermediul acțiunii [[http://www.tutorialspoint.com/jsp/jsp_java_beans.htm|<jsp:useBean>]]. | ||
| + | |||
| + | <code> | ||
| + | <jsp:useBean id="bookPresentationManager" class="ro.pub.cs.aipi.lab05.businesslogic.BookPresentationManager" /> | ||
| + | </code> | ||
| + | |||
| + | Apelul metodelor ''getPrice()'', respectiv ''getInformation()'' va fi realizată în cadrul unei expresii (scriplet), din care trebuie accesată valoarea atributului ''bookPresentationIdentifier'' definit în contextul paginii JSP. În acest scop, va fi utilizată metoda [[https://tomcat.apache.org/tomcat-8.0-doc/jspapi/javax/servlet/jsp/JspContext.html#getAttribute%28java.lang.String%29|getAttribute()]] a obiectului implicit ''pageContext'' (de tipul [[https://tomcat.apache.org/tomcat-8.0-doc/jspapi/javax/servlet/jsp/PageContext.html|PageContext]]). | ||
| + | |||
| + | <code> | ||
| + | <c:set var="currentBookPrice" scope="request" value="<%= bookPresentationManager.getPrice(Long.parseLong(pageContext.getAttribute("bookPresentationIdentifier").toString())) %>" /> | ||
| + | <c:set var="currentBookInformation" scope="request" value="<%= bookPresentationManager.getInformation(Long.parseLong(pageContext.getAttribute("bookPresentationIdentifier").toString())) %>" /> | ||
| + | </code> | ||
| + | |||
| + | Este necesar să se calculeze și prețul total al coșului de cumpărături, într-un atribut al paginii JSP, prin însumarea tuturor valorilor corespunzătoare volumelor care se doresc a fi achiziționate. | ||
| + | |||
| + | Prezentarea se va face în cadrul unui tabel (element de tip [[http://www.w3schools.com/tags/tag_table.asp|<table>]]), datele corespunzătoare unui obiect din coșul de cumpărături fiind incluse pe o linie a acestuia (''<tr><td>...</td></tr>''). | ||
| + | </spoiler> | ||
| + | |||
| + | **10.** În pagina ''client.jsp'', să se adauge două butoane prin care se poate anula, respectiv finaliza o comandă, în condițiile în care există produse în coșul de cumpărături. | ||
| + | |||
| + | <spoiler|Indicații de Rezolvare> | ||
| + | Resursele grafice pentru butoane se regăsesc în directorul ''images'', în subdirectorul ''user_interface'', având denumirile: | ||
| + | * ''remove_from_shopping_cart.png''; | ||
| + | * ''shopping_cart_accept.png''; | ||
| + | |||
| + | Butoanele vor fi incluse în cadrul unui element de tip [[http://www.w3schools.com/tags/tag_input.asp|<input>]], având atributul ''type'' cu valoarea ''image'' și denumirile ''cancelcommand'', respectiv ''completecommand'' (valori conținute de constantele ''CANCEL_COMMAND'' și ''COMPLETE_COMMAND'' din interfața ''Constants'', pentru care se elimină spațiile și se folosesc numai minuscule). Pentru a se obține aceste valori, vor fi utilizate funcțiile [[http://www.tutorialspoint.com/jsp/jstl_function_tolowercase.htm|fn:toLowerCase()]], respectiv [[http://www.tutorialspoint.com/jsp/jstl_function_replace.htm|fn:replace()]], după ce s-au obținut valorile corespunzătoare constantelor definite în interfața ''Constants''. Locațiile la care se găsesc resursele ce vor fi afișate vor fi precizate în cadrul atributului ''src''. | ||
| + | </spoiler> | ||
| + | |||
| + | **11.** În pachetul ''ro.pub.cs.aipi.lab04.servlets'', în clasa ''ClientServlet'', metoda ''doPost()'', să se implementeze operaţiile de anulare, respectiv finalizare a unei comenzi. | ||
| + | |||
| + | <spoiler|Indicații de Rezolvare> | ||
| + | În cazul anulării unei comenzi, se şterge conţinutul obiectului ''shoppingCart''. | ||
| + | |||
| + | În cazul finalizării unei comenzi, trebuie realizate următoarele operaţii: | ||
| + | * se adaugă o înregistrare în tabela ''invoice_header''; se va folosi metoda ''create()'' din cadrul clasei ''InvoiceHeaderManager'' pentru care trebuie precizate valorile ce vor fi adăugate, aceasta furnizând identificatorul înregistrării din tabelă: | ||
| + | * numărul de identificare (câmpul ''identification_number'') va fi generat aleator folosind metoda ''Utilities.generateIdentificationNumber()'', care primește ca parametri numărul de caractere de tip literă (3), respectiv cifră (6); | ||
| + | * data de emitere (câmpul ''issue_date'') - ziua curentă - va fi obținută folosind metoda [[https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html#now--|now()]] din clasa [[https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html|LocalDate]]; | ||
| + | * starea (câmpul ''state'') are valoarea ''issued'' reținut de constanta ''STATE_ISSUED'' din interfața ''Constants''; | ||
| + | * identificatorul utilizatorului (câmpul ''user_id'') va fi determinat pe baza denumirii (stocate în obiectul ''display'') - concatenarea dintre prenumele şi numele reţinute în tabela ''user'' - prin apelul metodei ''getIdentifier()'' din clasa ''UserManager''; | ||
| + | * se iterează asupra conținutului coșului de cumpărături (obiectul ''shoppingCart''): | ||
| + | * se obține identificatorul formatului de prezentare a cărții (atributul), cantitatea (valoarea) și stocul corespunzător, așa cum este reținut în tabela ''book_presentation'' (prin apelul metodei ''getStockpile()'') din clasa ''BookPresentationManager''); | ||
| + | * se compară numărul de exemplare din coşul de cumpărături cu stocul existent şi în situația în care comanda poate fi satisfăcută, se actualizează stocul (se apelează metoda ''update()'' din clasa ''BookPresentationManager'' care primește ca parametri atât atributul cât și valoarea care trebuie să fie modificate); se adaugă o înregistrare în tabela ''invoice_line''; se va folosi metoda ''create()'' din cadrul clasei ''InvoiceLineManager'' pentru care trebuie precizate valorile ce vor fi adăugate: | ||
| + | * identificatorul facturii (câmpul ''invoice_header_id''), determinat anterior; | ||
| + | * identificatorul formatului de prezentare a cărții (câmpul ''book_presentation_id''); | ||
| + | * cantitatea (câmpul ''quantity''); | ||
| + | * altfel, se adaugă un mesaj de eroare care va fi afișat în cadrul paginii JSP; | ||
| + | * se goleşte coşul de cumpărături. | ||
| + | </spoiler> | ||
| + | |||
| + | **12.** Să se implementeze operaţia de deautentificare printr-un buton plasat sub mesajul de întâmpinare pentru fiecare utilizator în pagina de tip client. În această situație, utilizatorul se va întoarce în pagina de autentificare. | ||
| + | |||
| + | {{ :laboratoare:laborator04:activitate_de_laborator_exercitiu12.png?nolink }} | ||
| + | |||
| + | <spoiler|Indicații de Rezolvare> | ||
| + | În pagina ''client.jsp'', se afișează un element de tip [[http://www.w3schools.com/tags/tag_input.asp|<input>]], având atributul ''type'' cu valoarea ''image'' și denumirea ''signout'' (valoare reținută de constanta ''SIGNOUT'' din interfața ''Constants''). Resursa grafică se regăsește în directorul ''images'', în subdirectorul ''user_interface'', având denumirea ''signout.png''. | ||
| + | |||
| + | În clasa ''ClientServlet'', în cazul în care a fost apăsat butonul pentru operația de deautentificare: | ||
| + | * se obține lista cu toți parametrii (metoda [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#getParameterNames--|getParameterNames()]] din clasa [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html|ServletRequest]]), aceștia fiind eliminați, prin invocarea metodei [[http://docs.oracle.com/javaee/7/api/javax/servlet/ServletRequest.html#removeAttribute-java.lang.String-|removeAttribute()]]; | ||
| + | * se elimină elementele conținute de listele ''shoppingCart'', ''formatsFilter'', ''languagesFilter'', ''categoriesFilter''; | ||
| + | * valorile conținute de obiectele ''previousRecordsPerPage'', ''currentRecordsPerPage'', ''currentPage'' vor fi cele implicite; | ||
| + | * se elimină conținutul obiectului ''books''; | ||
| + | * se transferă contextul către servletul care gestionează operația de autentificare (''LoginServlet''): <code java> | ||
| + | RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/" + Constants.LOGIN_SERVLET_PAGE_CONTEXT); | ||
| + | if (dispatcher != null) { | ||
| + | dispatcher.forward(request, response); | ||
| + | } | ||
| + | </code> | ||
| + | * se invalidează sesiunea prin invocarea metodei [[https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html#invalidate--|invalidate()]] pe obiectul de tip [[https://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSession.html|HttpSession]], - după această operație nu mai este permis să se utilizeze pagina Internet curentă; <code java> | ||
| + | session.invalidate(); | ||
| + | </code> | ||
| - | <note important>După apelul metodei ''forward()'' pentru obiectul ''requestDispatcher'', este recomandat să se apeleze instrucțiunea ''return'' pentru că apelul ulterior al altor metode poate genera o excepţie de tipul ''IllegalStateException''.</note> | + | <note tip>Se poate utiliza ca model implementarea din cadrul paginii de administrator (clasa ''AdministratorServlet'' / pagina ''administrator.jsp'').</note> |
| + | </spoiler> | ||
| ===== Resurse ====== | ===== Resurse ====== | ||
| Line 1438: | Line 1616: | ||
| ===== Soluții ===== | ===== Soluții ===== | ||
| - | [[https://github.com/aipi2014/Laborator08/tree/master/EclipseEE/|Proiect EclipseEE]]\\ | + | [[https://github.com/aipi2015/Laborator05/tree/master/solutions/eclipse/05-BookStore-JSP|Proiect Eclipse]]\\ |
| - | [[https://github.com/aipi2014/Laborator08/tree/master/NetBeans/|Proiect NetBeans]] | + | [[https://github.com/aipi2015/Laborator05/tree/master/solutions/netbeans/05-BookStore-JSP|Proiect NetBeans]] |
