Università degli Studi di Modena e Reggio Emilia Facoltà di Ingegneria – Reggio Emilia JSP: Java Server Pages Ing. Marco Mamei M. Mamei – Java Server Pages (JSP) 1 JSP: Pagine come Servizi Nelle Servlet • si scrive codice che alla fine produce output in linguaggio HTML Difetti: • è lungo e noiso produrre l’output in HTML, e si devono scrivere un sacco di cose (p.e., head, html, body) sempre tutte uguali • si devono riscrivere un sacco di cose (tutti gli import, le varie dichiarazioni standard) sempre uguali • è difficile dal codice servlet “vedere” quello che la servlet produrrà. • è difficile dividere la parte di business-logic dalla presentazione (look-and-feel del sito). Soluzione: invertire completamente il concetto • Si scrivono pagine HTML che producano il codice dei servizi e vadano a includere direttamente l’output di questi servizi In pratica, si mette il codice con appositi tag nelle pagine HTML che andranno in output. M. Mamei – Java Server Pages (JSP) 2 Primo Esempio JSP Un file Hello.jsp JSP Che stampa i quadrati dei primo dieci numeri: <html> <head> <title> Primo Esempio JSP </title> </head> <body> <%@ page language="java"%> <h1> I quadrati dei numeri </h1> <% for (int i=0;i<11;i++) { %> <br> <%=i%> Al quadrato fa <%=i*i%> <% } %> </body> </html> NOTIAMO <% e %> sono i TAG SPECIFICI che definiscono quando inizia il codice. Per il resto è codice Java normale…. M. Mamei – Java Server Pages (JSP) 3 Primo Esempio: Risultato e Codice HTML Prodotto <html> <head> <title> Primo Esempio JSP </title> </head> <body> <h1> I quadrati dei numeri </h1> <br> 0 Al quadrato fa 0<br> 1 Al quadrato fa 1<br> 2 Al quadrato fa 4<br> 3 Al quadrato fa 9<br> 4 Al quadrato fa 16<br> 5 Al quadrato fa 25<br> 6 Al quadrato fa 36<br> 7 Al quadrato fa 49<br> 8 Al quadrato fa 64<br> 9 Al quadrato fa 81<br> 10 Al quadrato fa 100 </body> </html> Come funziona? Concettualmente semplice: nel server esiste un servizio che traduce automaticamente il file JSP nella corrispondente servlet. M. Mamei – Java Server Pages (JSP) 4 Sintassi JSP - Direttive Le direttive sono istruzioni inviate al JSP container (Tomcat) e che, pur potendo influenzare l’esito finale, non creano di per sé alcuna pagina. <%@ direttiva {attributo=”valore”} %> <%@ page language=”java” %> indca al container JSP che il linguaggio usato per specificare il contenuto dinamico è java. <%@ page import = “java.sql.*” %> importa il package specificato. <%@ include file=”header.txt” %> inserisce il file di testo header.txt al posto della direttiva. Usato, ad esempio, per definire intestazioni o chiusure HTML. Inoltre il file inserito può contenre codice JSP. Le direttive include possono essere innestate; cioè un file oggetto di una direttiva include può a sua volta avere una direttiva include. Un esempio particolarmente significativo della direttiva include riguarda l’includere un foglio di stile CSS all’interno di una JSP. <head> ... <jsp:include page="mio_stile.css" /> ... </head> M. Mamei – Java Server Pages (JSP) 5 Sintassi JSP – Azioni Tutto ciò che si trova in una JSP e che non è una direttiva è un’azione; le azioni dipendono dal linguaggio di scripting utilizzato dalla JSP (nel nostro caso Java). SCRIPTLET: <% codice linguaggio JSP (java) %> ESPRESSIONI: <%= codice linguaggio JSP (java) %> la differenza tra le due verisioni è che il codice prodotto da un’ espressione viene automaticamente incapsulato dentro a un out.println(). Questo ha due conseguenze: • Il risultato di quello che è messo in un’ espressione viene mandato in output nel punto corrispondente al tag jsp. • In un’ espressione non si possono usare istruzioni multiple o ; alla fine di un istruzione M. Mamei – Java Server Pages (JSP) 6 Due Semplici Esempi <html> <body> <%@ page language="java"%> <p> The date and time: <%= new java.util.Date() %></p> <body> <html> <html> <body> <%@ page language="java"%> <%@ page import="java.util.*" %> <%@ include file="header.txt" %> <p> The date and time: <% out.println(new Date()); %></p> <body> <html> M. Mamei – Java Server Pages (JSP) 7 Oggetti Impliciti (1) Nel definire il codice di pagine JSP, possiamo usare tutta una serie di oggetti che non dobbiamo creare o definire noi, ma che sono già implicitamente creati e definiti. Poiché a basso livello una JSP è tradotta automaticamente in una Servlet. In quesa parte useremo il termine servlet per intendere quella generata a partire dalla JSP. request Sottotipo di javax.servlet.ServletRequest Rappresenta la richiesta del client response Sottotipo di javax.servlet.ServletResponse Rappresenta la risposta del server Poco utilizzato (la risposta è il contenuto della pagina) application Oggetto di classe javax.servlet.ServletContext Rappresenta il contesto della servlet derivata dalla pagina JSP e di tutti i componenti Web della stessa pplicazione M. Mamei – Java Server Pages (JSP) 8 Oggetti Impliciti(2) config Oggetto di classe javax.servlet.ServletConfig Rappresenta le informazioni di inizializzazione per la Servlet derivata dalla pagina JSP exception Oggetto di classe java.lan.Throwable È accessibile solo da una pagina di errore out Oggetto di classe javax.servlet.jsp.JspWriter Rappresenta lo stream di output page Oggetto di classe java.lang.Object Rappresenta l’istanza della pagina processando la richiesta corrente Di solito, non è utilizzata JSP che sta pageContext Oggetto di classe javax.servlet.jsp.PageContext Rappresenta il contesto della pagina JSP Fornisce una API per gestire vari attributi Usato soprattutto dai tag handler session Oggetto di classe javax.servlet.http.HttpSession Rappresenta la sessione M. Mamei – Java Server Pages (JSP) 9 Alcuni Esempi Form HTML di login che comunica con una JSP <HTML> <BODY> <H1> Login Form </H1> <FORM action="prova3.jsp"> Username: <INPUT TYPE="text" NAME="username" /><BR> Password: <INPUT TYPE="text" NAME="password" /><BR> <BR> <INPUT TYPE="submit" VALUE="Login"/> <FORM> </BODY> </HTML> JSP che riceve i parametri <html> <body> <%@ page language="java"%> <% String username = request.getParameter("username"); String password = request.getParameter("password"); %> <p> You are logging in with:<br/> username: <%=username%><br/> password: <%=password%><br/> </p> <body> <html> M. Mamei – Java Server Pages (JSP) 10 Form HTML e JSP tutto insieme !!! <html> <body> <%@ page language="java"%> <% String name = null; name = request.getParameter("name"); %> <% if(name != null ) { %> <p> You entered:<br/> <%=name%> </p> <% } %> <% if(name == null ) { %> <form method=get> <input type="text" name="name"> <input type="submit" value="submit"> </form> <% } %> <body> <html> M. Mamei – Java Server Pages (JSP) 11 Sintassi JSP – Dichiarazioni Le dichiarazioni sono istruzioni usate per definire variabili di stato e metodi della JSP. <%! dichiarazione %> Per gli scriptlet, il codice Java generato viene inserito come codice del metodo service della corrispondente servlet. Con le dichiarazioni, invece, il codice che si va a scrivere viene messo fuori dal metodo service. Questo può quindi servire per: - definire dei metodi da usarsi con la servlet - dichiarare attibuti (variabili di oggetto) della servlet Esempi: <html> <body> <%@ page language="java"%> <%! int counter = 0; %> <%! public void inc() { counter ++; } %> This page has been accessed <%= counter %> times. <% inc(); %> <body> <html> Cosa sarebbe successo se avessimo scritto: <%int counter = 0; %> M. Mamei – Java Server Pages (JSP) 12 Problemi A forza di complicare le cose abbiamo ottento una pagina HTML (JSP) incompresibile…. Dove è finita la separazione tra business logic e lookand-feel??? Dobbiamo studiare altre soluzioni per separare il codice dai tag. A questo proposito, nelle pagine JSP si possono: Usare i Bean: sono oggetti con caratteristiche speciali. Sono degli oggetti auto-contenuti che possono essere usati come “componenti”. I bean possono essere incapsulati dentro una pagina JSP e contenere codice. Definire e Usare Tag Personalizzati: si possono definire nuovi tag JSP per racchiudere all’interno di poche righe anche operazioni complesse, e per poter riusare quester operazioni a piacere (come, se volete, quando di definiscono procedure e funzioni in un linguaggio di programmazione). Noi vedremo la prima soluzione. M. Mamei – Java Server Pages (JSP) 13 Verso i Java Bean Una possibilità interessante per risolvere il problema precedente è: 1. spostare tutto il codice java fuori dalla JSP. 2. lasciare nelle JSP solo le chiamate ai metodi java esterni In questo modo: 1. chi crea la pagina JSP può in effetti concentrasi solo sulla presentazione del sito. 2. chi crea la parte dinamica produce un file separato java di cui pubblica solo la specifica (prototipo) dei metodi. Il file java può inoltre essere “redatto” tramite un IDE congeniale. M. Mamei – Java Server Pages (JSP) 14 Esempio Prova.jsp <html> <head> <%@ page language= "java" %> <% MethodBean bean = new MethodBean(); %> </head> <body> <h1>This page accesses the Javabean that is created as a normal class</h1> <%= bean.getName() %> </body> </html> MethodBean.java public class MethodBean { public MethodBean() { } public String getName() { return new String("MethodBean"); } } Nota: 1. Nonostante il nome (MethodBean) ancora non stiamo usando le funzionalità dei java bean. 2. Per le specifiche di Tomcat, il file MethodBean.class deve essere messo sotto la cartella WEBINF/classes. Com’era per le servlet. 3. L’esempio è molto semplice, ma dentro ai metodi di MethodBean posso mettere quello che voglio: accesso a un db, etc. M. Mamei – Java Server Pages (JSP) 15 Esempio Login Ese2.html <html> <head> <script type="text/javascript" src="ese2.js"></script> </head> <body> <H1> Login Form </H1> <FORM action="ese2.jsp"> Username: <INPUT TYPE="text" NAME="username" id='user' /><BR> Password: <INPUT TYPE="text" NAME="password" id='password'/><BR> <BR> <INPUT TYPE="submit" VALUE="Login" id='submit'"/> <FORM> </body> </html> Ese2.js function check(e) { var user = document.getElementById('user'); var password = document.getElementById('password'); if(user.value == "" || password.value == "") { alert("Errore"); return false; // return true; // in this case the submit will happen anyway } } function addListeners(e) { var sbutton = document.getElementById('submit'); addEvent(sbutton,'click',check); } M. Mamei – Java Server Pages (JSP) 16 Ese2.jsp <html> <head> <%@ page language= "java" %> <% jspbeans.Bean1 bean = new jspbeans.Bean1(); %> <% String username = request.getParameter("username"); String password = request.getParameter("password"); %> </head> <body> <h1>This page accesses the Javabean that is created as a normal class</h1> <% if(bean.authenticate(username, password)) out.println("You have been authenticated"); else out.println("Insterted usrname and/or password are wrong"); %> </body> </html> Bean1.java package jspbeans; public class Bean1 { private String[] names; private String[] passwords; public Bean1() { names = new String[]{"marco", "matteo"}; passwords = new String[]{"marco76", "matteo80"}; } public boolean authenticate(String n, String p) { for(int i=0; i<names.length;i++) { if(n.equals(names[i])) { if(p.equals(passwords[i])) return true; } } return false; } public static void main(String[] args) { Bean1 b = new Bean1(); System.out.println(b.authenticate("pippo","pluto")); System.out.println(b.authenticate("marco","matteo80")); System.out.println(b.authenticate("matteo","matteo80")); } } M. Mamei – Java Server Pages (JSP) 17 Esempio Accesso File <html> <head> <%@ page language= "java" %> <% jspbeans.Bean2 bean = new jspbeans.Bean2("c:/pippo.txt"); %> <script type="text/javascript" src="ese3.js"></script> <link href="ese3.css" rel="stylesheet" type="text/css"/> </head> <body> <h1>This page accesses the Javabean that is created as a normal class</h1> <h2>The bean accesses a file</h2> <p id="para"> <%=bean.showData()%> </p> </body> </html> package jspbeans; import java.io.*; public class Bean2 { private String file; public Bean2(String file) { this.file = file; } public String showData() { String data = ""; try{ BufferedReader f = new BufferedReader(new FileReader(file)); String s; while((s=f.readLine())!=null) { data = data + s; } }catch(Exception e) {e.printStackTrace(); data="File not found"; } return data; } public static void main(String[] args) { Bean2 bean = new Bean2("C:/pippo.txt"); System.out.println(bean.showData()); }} M. Mamei – Java Server Pages (JSP) 18 È Tutto Risolto? Sicuramente, l’idea di spostare il codice java fuori dalla JSP è un ottimo punto di partenza. Ci sono però ancora alcune difficoltà: 1. l’approccio presentato tende a produrre metodi con molti parametri scambiati avanti e indietro (e.g. oggetti request, response, etc.) 2. gestire le sessioni (vedi dopo) è abbastanza scomodo Per ovviare a queste problematiche le JSP forniscono tag specifici per trattare classi java esterne come MethodBean.java. Queste classi devono però rispettare la specifica dei JavaBeans. M. Mamei – Java Server Pages (JSP) 19 Java Beans Un Java Bean è una normalissima classe java che rispetta qualche piccola convenzione relativa al suo contenuto. In particolare, ogni bean deve avere: 1. un costruttore vuoto 2. solo variabili di stato private o protected 3. metodi di get e set per tali variabili. In particolare, se la variabile si chiama name, questi metodi devono chiamarsi: getName e setName. Tutte queste convenzioni servono per permettere alle JSP di generare automaticamente il codice per creare una classe (bean) ed accedere in modo controllato allo stato di tale classe. M. Mamei – Java Server Pages (JSP) 20 Esempio Prova1.jsp <html> <head> <%@ page language= "java" %> <jsp:useBean id="jb" scope="session" class="UserPrefBean" /> <jsp:setProperty name="jb" property="color" param="newColor" /> </head> <body> <h1>This page accesses the Javabean</h1> <jsp:getProperty name="jb" property="color"/> </body> </html> UserPrefBean.java public class UserPrefBean { private String color; public UserPrefBean() { } public String getColor() { return color; } public void setColor(String newColor) { this.color = newColor; } } M. Mamei – Java Server Pages (JSP) 21 Tag JSP per JavaBeans 1/3 Vediamo la sintassi completa dei tag che accedono ai beans. Caricamento di un java bean: <jsp:useBean id=”name” scope=”page|session|application” typeSpec /> 1. id è un nome simbolico assegnatao al bean all’interno dell’applicazione. 2. scope definisce l’area di visibilità prevista per il bean: page è la singola invocazione, session per la sessione, application per tutta la webapplication indipendentemente dalle sessioni – viene messo nell’application context. Se nell’area di visibilità prevista il bean non c’è la JSP ne crea un’istanza, altrimenti viene recuperata l’isatnza già esistente. 3. typeSpec specifica come viene caricato il bean. Il modo di gran’lunga più usato è class=”MyBean” dove MyBean.class è in WEB-INF/classes. M. Mamei – Java Server Pages (JSP) 22 Tag JSP per JavaBeans 2/3 Impostazione di una proprietà Java Bean: <jsp:setProperty name=”beanName” property=”propertyName” param=”parameterName” /> Questo tag imposta la varaibile del bean “propertyName” al valore di “parameterName” passato dalla richiesta http. <jsp:setProperty name=”beanName” property=”*”/> Questo tag imposta tutte le variabili del bean ai rispettivi valori passati dalla richiesta http. <jsp:setProperty name=”beanName” property=”propertyName” param=”parameterName” /> Questo tag imposta la varaibile del bean “propertyName” al valore statico “parameterName”. M. Mamei – Java Server Pages (JSP) 23 Tag JSP per JavaBeans 3/3 recuperare una proprietà da un Java Bean: <jsp:getProperty name=”name” property=”propertyName” /> Questo tag recupera la varaibile del bean “propertyName” e la inserisce nella JSP (pagina HTML). Inoltre…. Una volta creato un bean possiamo accedervi come fosse una classe normale. <html> <head> <%@ page language= "java" %> <jsp:useBean id="jb" scope="session" class="MethodBean"/> </head> <body> <h1>This page accesses the Javabean</h1> <%= jb.getName() %> </body> </html> M. Mamei – Java Server Pages (JSP) 24 Esempio 1 Questa pagina gestisce una form tramite la quale un utente può registrarsi a un sito. <html> <head> <%@ page language= "java" %> <jsp:useBean id="regbean" scope="session" class="RegBean" /> </head> <body> <jsp:setProperty name="regbean" property="*" /> <H1> Registration Page: </H1> <BR> <FORM> Name: <INPUT TYPE="text" NAME="name" /><BR> Surname: <INPUT TYPE="text" NAME="surname" /><BR> Username: <INPUT TYPE="text" NAME="username" /><BR> Password: <INPUT TYPE="text" NAME="password" /><BR> Color: <INPUT TYPE="text" NAME="color" /><BR><BR> <INPUT TYPE="submit" VALUE="Submit"/> <FORM> <hr> <hr> <h1> You have selected </h1> Name: <jsp:getProperty name="regbean" property="name"/><br> Surname: <jsp:getProperty name="regbean" property="surname"/><br> Username: <jsp:getProperty name="regbean" property="username"/><br> Password: <jsp:getProperty name="regbean" property="password"/><br> Color: <jsp:getProperty name="regbean" property="color"/><br><br> </body> </html> M. Mamei – Java Server Pages (JSP) 25 Questa pagina estrae le informazioni inserite precedentmente. Poiché il bean è stato definito come avente uno scope=session. La pagina precedente crea automaticamente una sessione a cui questa altra JSP può accedere. <html> <head> <%@ page language= "java" %> <jsp:useBean id="regbean" scope="session" class="RegBean" /> </head> <body> <h1>You've been registered!</h1><br> Name: <jsp:getProperty name="regbean" property="name"/><br> Surname: <jsp:getProperty name="regbean" property="surname"/><br> Username: <jsp:getProperty name="regbean" property="username"/><br> Password: <jsp:getProperty name="regbean" property="password"/><br> Color: <jsp:getProperty name="regbean" property="color"/><br><br> </body> </html> M. Mamei – Java Server Pages (JSP) 26 ...E infine il bean vero e proprio. public class RegBean { private String name; private String surname; private String username; private String password; private String color; public RegBean() { } public public public public public String String String String String getName() {return name;} getSurname() {return surname;} getUsername() {return username;} getPassword() {return password;} getColor() {return color;} public void setName(String newName) {name = newName;} public void setSurname(String newSurame) {surname = newSurame;} public void setUsername(String newUsername) {username = newUsername;} public void setPassword(String newPassword) {password = newPassword;} public void setColor(String newColor) {color = newColor;} } M. Mamei – Java Server Pages (JSP) 27 Session e Cookie I server http rispondono ad ogni richiesta del client senza collegare quella richiesta alle richieste precedenti: si dice quindi che le interazioni sono stateless, ossia senza memoria di stato. Creare un meccanismo di gestione dello stato permetterebbe ai client e ai server si scambiare informazioni all’interno di un contesto più ambio che possiamo denominare sessione. Questo contesto sarebbe molto utile, per esempio, in applicazioni di shopping-on-line, dove è necessario raccogliere le selezioni effettuate dall’utente, i dati degli acquirenti, carte di credito,… Un Cookie è una piccola quantità di informazione trasmessa da una servelt, verso un client. Tale informazione viene conservata dal browser e, in un secondo tempo, trasmessa di nuovo al server. Il server può mantenere una sessione sulla base delle informaizioni ricevute tramite cookie. M. Mamei – Java Server Pages (JSP) 28 Esempio 2 (Session) Questa pagina gestisce una form tramite la quale un utente può effettuare il login a un sito. Ese4.html <html> <head> <script type="text/javascript" src="ese2.js"></script> </head> <body> <H1> Login Form </H1> <FORM action="ese4.jsp"> Username: <INPUT TYPE="text" NAME="username" id='user'/><BR> Password: <INPUT TYPE="text" NAME="password" id='password'/><BR> <BR> <INPUT TYPE="submit" VALUE="Login" id='submit'"/> <FORM> </body> </html> Ese4.jsp <html> <head> <%@ page language= "java" %> <jsp:useBean id="loginbean" scope="session" class="jspbeans.Bean3" /> <jsp:setProperty name="loginbean" property="n" param="username"/> <jsp:setProperty name="loginbean" property="p" param="password"/> </head> <body> <h1> <%= loginbean.authenticate() %> </h1> </body> </html> M. Mamei – Java Server Pages (JSP) 29 Secure Page.jsp <html> <head> <%@ page language= "java" %> <jsp:useBean id="loginbean" scope="session" class="jspbeans.Bean3" /> </head> <body> <% if (loginbean.getAuth() == true) { %> <h1>You've been registered!</h1><br> Username: <jsp:getProperty name="loginbean" property="n"/><br> Password: <jsp:getProperty name="loginbean" property="p"/> <% } else { %> <h1>You're not allowed to access this content!</h1> <% } %> </body> </html> M. Mamei – Java Server Pages (JSP) 30 Bean.java package jspbeans; public class Bean3 { private String[] names; private String[] passwords; private String n; private String p; private boolean auth; public Bean3() { names = new String[]{"marco", "matteo"}; passwords = new String[]{"marco76", "matteo80"}; auth = false; } public public public public public public void setN(String n) {this.n=n;} void setP(String p) {this.p=p;} void setAuth(boolean a) {this.auth=a;} String getN(){return n;} String getP(){return p;} boolean getAuth(){return auth;} public String authenticate() { for(int i=0; i<names.length;i++) { if(n.equals(names[i])) { if(p.equals(passwords[i])){ auth=true; return new String("You have been authenticated"); } } } return new String("You are NOT authenticated"); } public static void main(String[] args) { Bean3 b = new Bean3(); b.setN("marco");b.setP("matteo80"); System.out.println(b.authenticate()); b.setN("marco");b.setP("marco76"); System.out.println(b.authenticate()); } } M. Mamei – Java Server Pages (JSP) 31 Una seconda versione della pagina sicura Attraverso la direttiva include possiamo nascondere l’implementzione della logica applicativa. <html> <body> <%@ page language= "java" %> <%@ include file="startAllowed.jsp" %> <h1>You've been registered!</h1><br> Username: <jsp:getProperty name="loginbean" property="username"/><br> Password: <jsp:getProperty name="loginbean" property="password"/> <%@ include file="endAllowed.jsp" %> <%@ include file="startNotAllowed.jsp" %> <h1>You're not allowed to access this content!</h1> <%@ include file="endNotAllowed.jsp" %> </body> </html> M. Mamei – Java Server Pages (JSP) 32 Esercizi Esercizio 1: Realizzare un servizio di registrazione + login + pagina autenticata utilizzando solo le classi java (senza sfruttare le funzionalità dei java beans) Esercizio 2: Realizzare lo stesso servizio con i java beans (sfruttare lo scope=session). Esercizio 3: Utilizzando il risultato dell’esercizio 2, realizzare un servizio di carrello della spesa tramite java beans. In particolare, questo esercizio consiste in: 1. un db (Access o file) con una serie di articoli identificati da un codice e una descrizione. 2. una pagina che accede al db e visualizza gli articoli in una tabella html. La pagina ha anche una form tramite la quale un utente può effettuare un ordine. 3. Gli ordini vengono memorizzati in un carrello della spesa (bean) associato ad una sessione tra quell’utente e il server. Per semplicità considerate che un ordine consiste in un solo articolo. 4. un’altra pagina permette di fare il check-out del carrello. M. Mamei – Java Server Pages (JSP) 33