JSP: Gestione input e generazione di contenuti dinamici

Analizziamo da più da vicino le specifiche JSP e vediamo come poter iniziare a creare delle applicazioni che interagiscano con l’utente.

Direttive

Le direttive sono un elemento statico delle pagine JSP che permettono la definizione di una serie di direttive appunto che verranno utilizzate nella pagina che verrà visualizzata. In una semplice pagina JSP possono essere usate tre diverse direttive che ora andremo ad analizzare : include, page e taglib. La prima direttiva, include, e’ abbastanza intuitiva : permette l’inclusione statica di una risorsa.

Pensiamo allo schema classico di una pagina HTML di un qualsiasi sito web. Di solito abbiamo degli elementi che troviamo in ogni pagina del sito web (un menu, un banner etc. etc.). Senza doverci preoccupare ogni volta di riscrivere il codice che deve essere ripetuto in tante pagine possiamo utilizzare questa direttiva, anche più di una volta in una pagina. Ecco quindi un esempio

<%@ include file="banneralto.html" %>
<H1>
<CENTER>TITOLO</CENTER> 
</H1>
<%@ include file="menu.html" %>
<TABLE BORDER=1>
<TR><TD>...
...
...
<%@ include file="disclaimer.html" %>

Nella nostra pagina d’esempio abbiamo tre elementi che dobbiamo ripetere sempre, il banner in alto, il menu e un disclaimer in basso. Come potete vedere la direttiva include accetta il solo parametro “file”, che rappresenta appunto l’URI della risorsa che vogliamo includere nella nostra pagina.

Passiamo ora alla direttiva più importante, page. Questa ci permette di definire una serie di aspetti fondamentali per la nostra pagina. Praticamente a differenza della direttiva include, che mette a disposizione un solo tipo di coppia attributo-valore, la direttiva page offre diverse opzioni, ognuna con una sua funzionalità specifica. Vediamo come sempre un esempio per chiarirci le idee.

<%@page language="java" import="mypackage.myclass" %>
<%@page errorPage="error.jsp"  %> 
<%@page contentType="text/html;charset=ISO-8859-1"  %>
<%@page isThreadSafe="true">

Allora prima di tutto vediamo l’attributo contentType. Praticamente questo permette di specificare il content type che sarà scritto nell’header HTTP di risposta al client. Se noi ad esempio scriviamo la nostra pagina di risposta in HTML ma settiamo il contentType al valore “text/plain” il browser del client penserà che la risposta è testo semplice e quindi non provvederà a parsarlo e rappresentarlo come dovrebbe.

Un altro attributo fondamentale della direttiva page è errorPage. Tramite quest’ultimo possiamo specificare la pagina d’errore relativa alla nostra pagina. Visto che quello che inseriamo nella pagina JSP è alla fine del codice, in questo potrebbe essere presente un errore. Avendo specificato la pagina d’errore è come se avessimo chiuso tutta la pagina in un blocco try. Nel caso di eccezione veniamo ridirezionati ad una pagina di errore che personalizzeremo in base all’errore verificatosi nella nostra applicazione.

Passiamo ora ad un attributo che risulterà molto familiare ai programmatori Java, ovvero import. Nella pagina JSP, in special modo nei blocchi di scriptlet, possiamo istanziare delle classi per utilizzarle nella logica della nostra web application. Chiaramente per utilizzare questa classe la dobbiamo avere disponibile nel nostro CLASSPATH e soprattutto importarla con un classico import Java, anche perchè non dobbiamo dimenticarci che la JSP poi verrà tradotta in una Servlet.

C’è poi l’attributo isThreadSafe che permette di specificare, con i due valori permessi true/false, il fatto che la pagina possa essere eseguita più volte in parallelo. Praticamente se abbiamo l’attributo posto a false la pagina viene eseguita con una coda di richieste e non in parallelo. La decisione su come impostare questo valore (che di default è true) dipende da come è implementata la nostra web application, anche se nella maggior parte dei casi converrebbe gestire la concorrenza con componenti diverse dalle pagine JSP!!

Esistono anche altri tipi di attributi di minore importanza per i quali vi rimando alla documentazione su JSP. Vediamo infine l’ultima direttiva utilizzabile in pagine JSP, ovvero taglib. Questa direttiva assomiglia come funzionalità ad un import, perchè praticamente permette di importare nella nostra pagina JSP ulteriori funzionalità offerte da librerie di tag.

<%@taglib uri="server/path/" prefix="miotag" %>

Nella direttiva l’attributo prefix è quello che specifica quale sarà il nome con cui verrà richiamata questa libreria di tag all’interno della nostra pagina JSP. L’attributo uri invece permette di definire l’URI dove si trova la libreria. L’utilizzo delle librerie e delle potenzialità che esse offrono verranno affrontate successivamente nel corso. Esistono anche altre direttive che non possono essere utilizzate in una pagina JSP ma in pagine di tag.

Oggetti impliciti

Il container JSP mette a disposizione della pagina una serie di oggetti impliciti che possiamo utilizzare direttamente senza doverli istanziare. Questi oggetti infatti esistono a priori anche se noi nel nostro codice non li richiamiamo mai e possono essere utilizzati per differenti cose.

Il primo oggetto implicito che andiamo a vedere è request. Questo è un’istanza di una classe che implementa l’interfaccia javax.servlet.ServletRequest. In questo oggetto è memorizzata la richiesta HTTP che è stata fatta dal client, con tutti i parametri inviati. Leggendo le API di questa interfaccia vediamo infatti i metodi, come getParameter() o getParameterValues(), che ci permettono di reperire i parametri che sono stati inviati dal client attraverso l’HTTP.

Inoltre, con i metodi getRemoteAddr() e getRemoteHost(), possiamo avere informazioni riguardanti il client che ha effettuato la richiesta. In un esempio contenuto in questo articolo andremo poi ad utilizzare questo oggetto implicito per realizzare una prima interazione di input/output con JSP. Oltre all’oggetto che ci permette di avere le informazioni sulla richiesta effettuata in JSP abbiamo anche l’oggetto “response” (ServletResponse), che ci permette di amministrare la risposta che verrà data al client.

Un oggetto implicito molto importante per noi sarà out, istanza della classe JspWriter. Come abbiamo già visto noi possiamo tranquillamente utilizzare template text all’interno della nostra pagina JSP, isolando dei pezzi di codice che servono per generare la parte dinamica e funzionale del nostro sito. Chiaramente in questi pezzi di codice dobbiamo avere la possibilità di scrivere sull’output, ovvero sulla risposta che deve essere consegnata al client. L’oggetto implicito out ci permette appunto di avere un classico oggetto writer java per scrivere sull’output, con metodi classici come print() e println().

Un altro oggetto molto importante è application, istanza dell’interfaccia ServletContext, che permette di gestire dalla pagina JSP il contesto della web application su cui stiamo lavorando. Ci sono poi oggetti come session e exception che rappresentano rispettivamente la sessione di lavoro che è stata instaurata con il client e l’eccezione che è stata generata dal qualche scriptlet (disponibile solo nelle pagine di errore). Come in tutte le cose, la pratica ci insegnerà piano piano ad utilizzare tutti questi strumenti che vengono messi a nostra disposizione da JSP.

Gestione di una richiesta

Esempio di form

Esempio di form

Passiamo ora a qualche esempio che possa chiarire tutte le nozioni introdotte in questa lezione. Prima di tutto dobbiamo partire da una classica pagina HTML, che ci è sicuramente capitato di vedere navigando su internet, ovvero il classico questionario.

<html>
<head>
<title>Questionario di test</title>
</head>
<body>
<center>
<h2> Questionario di test </h2><br><hr><br>
<form action="questionario.jsp" method="post">
Nome: 
<input type="text" name="nome">
<br>
Cognome: 
<input type="text" name="cognome">
<br>
Email: 
<input type="text" name="email">
<br>
Sesso:<br>
<input type="radio" name="sesso" value="maschio"> Maschio
<br>
<input type="radio" name="sesso" value="femmina"> Femmina
<br>
Linguaggi di programmazione conosciuti:<br>
<input type="checkbox" name="java">
Java
<br>
<input type="checkbox" name="c">
C
<br>
<input type="checkbox" name="cplusplus">
C++
<br>
<input type="checkbox" name="cobol">
Cobol
<br>
<input type="checkbox" name="perl">
Perl
<br><br>
<input type="submit" name="submit" value="Invia">
</form>
</center>
</body>
</html>

In questa pagina HTML abbiamo inserito un form con diversi campi da compilare. Inoltre abbiamo deciso che l’action di questa form, ovvero la pagina che riceverà questi valori è la pagina JSP questionario.jsp.

Il metodo con cui questi dati saranno passati alla pagina è specificato dal metodo HTTP POST (ovvero l’url non conterrà tutti i parametri ma questi verranno passati all’interno della chiamata HTTP). Dobbiamo ora iniziare a manipolare i dati che ci vengono spediti dal form HTML. Quello che vogliamo fare inizialmente è semplicemente stampare a schermo questi dati.

<%@page contentType="text/html"  %>
<html>
<head>
<title>Parametri passati dal questionario</title>
</head>
<body>
<% 
out.println("Il tuo nome e' "+request.getParameter("nome")+"<br>");
out.println("Il tuo cognome e' "+request.getParameter("cognome")+"<br>");
out.println("La tua email e' "+request.getParameter("email")+"<br>");
out.println("Il tuo sesso e' "+request.getParameter("sesso")+"<br>");
out.println("Linguaggi conosciuti :<br>");
if (request.getParameter("java") != null)
out.println("Java<br>");
if (request.getParameter("c") != null)
out.println("C<br>");
if (request.getParameter("cplusplus") != null)
out.println("C++<br>");
if (request.getParameter("cobol") != null)
out.println("Cobol<br>");
if (request.getParameter("perl") != null)
out.println("Perl<br>");
%>
<br>
<img src='imgbottom.gif'>
<br><br><hr><br>
<%@include file="copyright.txt"%>
</body>
</html>

Risposta al submit

 

Senza stare troppo a tergiversare sulla bellezza e utilità del codice spieghiamo i semplici comandi cha abbiamo riportato nella nostra pagina JSP.

All’inizio del file JSP abbiamo definito attraverso la direttiva page il contentType della risposta che verrà restituita al browser, settandolo a text/html. Successivamente abbiamo iniziato uno scriptlet, dove utilizzando l’oggetto implicito request abbiamo recuperato i parametri passati. Infine questi dati sono stati scritti sull’output dal metodo println() dell’oggetto implicito out. Per ultima cosa abbiamo utilizzato la direttiva include per aggiungere in fondo alla nostra pagina un file dove sono contenute informazioni sul coryright.

C’è da notare il diverso utilizzo che viene fatto della richiesta in base alle diverse tipologie di parametri. Ad esempio sappiamo che sicuramente ci verrà inviato il parametro nome (al massimo vuoto), mentre non è sicuro che l’utente abbiamo selezionato il parametro java. Proprio per questo motivo controlliamo il parametro prima di scriverlo a schermo (utilizzando poi librerie e framework che poggiano sopra alla tecnologia JSP/Servlet magari potremo risolvere questi controlli in maniera più elegante e performante).

Action JSP standard

Cerchiamo ora di raffinare il nostro primo esempio di pagina JSP con qualche strumento che ci viene messo a disposizione. JSP definisce una serie di tag che possono essere utilizzati, come ad esempio l’Action, molto simile ad un tag HTML, anzi ad un tag XML per essere precisi.

Praticamente possiamo avere un tag di apertura e un tag di chiusura per la Action, e per ogni Action i relativi parametri necessari. Vediamo quindi quali sono queste Action che la specifica JSP mette a nostra disposizione. Una delle action standard è <jsp:useBean/>. Questa permette appunto di utilizzare un JavaBean nella nostra pagina JSP. Tramite altre due action, <jsp:getProperty/> e <jsp:setProperty/>, possiamo utilizzare un JavaBean per modellare i dati che manipoliamo in una pagina JSP.

Ci sono poi action che ci permettono di includere l’elaborazione di un’altra pagina (<jsp:include/>) o addirittura ridirezionare direttamente l’elaborazione ad un’altra (<jsp:forward/> ). Come primo esempio pratico ora vedremo come creare un JavaBean nelle nostre pagine e come orchestrare il tutto con le Action.

Costruire il Bean

Prima di tutto dobbiamo implementare una classe che ci permetta di avere contenute tutte le informazioni che dobbiamo manipolare nella nostra web application. Questo JavaBean quindi dovrà avere tutti i metodi get e set per ogni attributo che abbiamo inserito nel form HTML.

package com.javastaff.jsp;
import java.util.Vector;
public class BeanQuestionario {

    private String nome, cognome, email,
                   sesso, java, c, cplusplus,
                   cobol, perl;
    private Vector lang;

    public BeanQuestionario(){
        lang=new Vector();
    }

    public void setNome(String nome) {
        this.nome=nome;
    }
    public String getNome() {
        return nome;
    }
    public void setCognome(String cognome) {
        this.cognome=cognome;
    }
    public String getCognome() {
        return cognome;
    }
    public void setEmail(String email) {
        this.email=email;
    }
    public String getEmail() {
        return email;
    }
    public void setSesso(String sesso) {
        this.sesso=sesso;
    }
    public String getSesso() {
        return sesso;
    }
    public void setJava(String java) {
        this.java="on";
        insertLang("Java");
    }
    public String getJava() {
        return java;
    }
    public void setC(String c) {
        this.c="on";
        insertLang("C");
    }
    public String getC() {
        return c;
    }
    public void setCplusplus(String cplusplus) {
        this.cplusplus="on";
        insertLang("C++");
    }
    public String getCplusplus() {
        return cplusplus;
    }
    public void setCobol(String cobol) {
        this.cobol="on";
        insertLang("Cobol");
    }
    public String getCobol() {
        return cobol;
    }
    public void setPerl(String perl) {
        this.perl="on";
        insertLang("Perl");
    }
    public String getPerl() {
        return perl;
    }

    public String getLang() {
        String temp="";
        for (int i=0;i<lang.size();i++)
            temp=temp+((String)lang.elementAt(i))+"<br>";
        return temp;
    }

    public void insertLang(String nome) {
        lang.addElement(nome);
    }

}

Come potete vedere abbiamo creato un semplice Bean con l’aggiunta due metodi particolari: insertLang() e getLang(). Questi due ci serviranno per inserire tutti i linguaggi presenti nella richiesta http in una prima fase (insertLang()) e poi per formattarli in HTML successivamente (getLang()).

Una volta che abbiamo creato questa classe e che l’abbiamo inserita nel nostro progetto dobbiamo creare una pagina JSP simile a quella di prima, ma in questo caso utilizzeremo delle Action JSP. Praticamente all’inizio della pagina JSP, grazie alle Action e , il container JSP provvederà a creare un’istanza della classe BeanQuestionario ed ad assegnarli automaticamente tutte le proprietà presenti nella richiesta http.

Infatti noi nel nostro Bean abbiamo definito un metodo set e un metodo get per ogni attributo che ci potrebbe essere passato. In questo modo utilizzando le due Action avremo a disposizione un metodo più elegante e più ordinato per manipolare dati. Ecco quindi di seguito la rielaborazione della pagina JSP che avevamo scritto prima, in questo caso utilizzando le Action JSP.

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<html>
    <head><title>Parametri passati dal questionario</title></head>
    <body>

        <jsp:useBean id="questionario" scope="session" class="
        com.javastaff.corsojsp.BeanQuestionario" /> 
        <jsp:setProperty name="questionario"  property="*" /> 

        Il tuo nome è 
        <jsp:getProperty name='questionario' property="nome" /><br>
        Il tuo cognome è
        <jsp:getProperty name='questionario' property="cognome" /><br>
        La tua email è 
        <jsp:getProperty name='questionario' property="email" /><br>
        Il tuo sesso è 
        <jsp:getProperty name='questionario' property="sesso" /><br>
        Linguaggi conosciuti 
        <br><jsp:getProperty name='questionario' property="lang" /><br>
        <br>
        <img src='imgbottom.gif'>
        <br><br><hr><br>
        <%@include file="copyright.txt"%>
    </body>
</html>

Il codice è molto più pulito e semplice da leggere.

L’action istanzia un bean della classe BeanQuestionario, noi dobbiamo solo passargli il nome con cui ci riferiremo a questo oggetto e il package di appartenenza. In questo momento abbiamo quindi un’istanza di BeanQuestionario che non ha settato alcun valore. L’action permette appunto di settare tutte le variabili del bean. Infatti, in base al bean che passiamo come argomento, questa action analizza prima di tutto le coppie attributi-valore che sono contenute nella request. Per ogni attributo vede se esiste il corrispondente metodo setNomeattributo nel bean che è stato fornito come argomento. Se il metodo esiste viene richiamato, passando come argomento il valore corrispondente.

In questo modo il bean viene inizializzato con tutti i parametri che abbiamo passato nel form. C’è da ricordarsi che se noi non passiamo un parametro relativo al bean, l’action non darà errore. Infatti questa non fà altro che settare tutti e soli i parametri che sono stati passati. Se poi il nostro bean necessita di parametri che noi non passiamo, ce ne accorgeremo soltanto in seguito quando li andremo a richiamare.

Ora abbiamo un bean con tutti i parametri del precedente form. Non rimane che scrivere in output una scheda riassuntiva dei dati inseriti come fatto precedentemente. In questo caso però per richiamare questi valori dobbiamo semplicemente utilizzare l’action indicando il bean e la proprietà che vogliamo stampare.

Pagina d’errore

Per completare il quadro d’insieme sui generici meccanismi di JSP vediamo ora come poter controllare il flusso della nostra applicazione in caso d’errore. Una pagina JSP che ci restituisce un errore è la seguente.

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<html>
    <head><title>Scoppia!!</title></head>
    <body>
    <%
    String nulla=null;
    int a=nulla.indexOf("Err");
     %>
    </body>
</html>

Se effettuate il deploy di questa pagina su Tomcat potrete vedere il classico messaggio d’errore di Tomcat, il quale riporta l’eccezione che è stata generata.

Pagina Default d'errore di Tomcat

Pagina Default d’errore di Tomcat

Le nostre pagine JSP, come il codice in generale, possono essere causa di un errore. Dobbiamo anche pensare che cause esterne al nostro programma possono causare errori, quindi una buona web application deve prevedere una gestione degli errori che possono verificarsi.

Soprattutto dobbiamo renderci conto che noi sviluppatori siamo abituati a vedere Tomcat o la JVM in generale che và in crash. Ma gli utenti di un sito web no, quindi dobbiamo provvedere anche alla personalizzazione della pagina d’errore, per rendere il tutto più professionale.

Se navighiamo su siti famosi possiamo vedere che le pagine d’errore utilizzano la stessa user experience del sito, avvertendo l’utente dell’errore generato. Questo è quello che faremo anche noi con JSP. Prima di tutto dobbiamo indicare nella nostra pagina, tramite la direttiva page, quale sarà la pagina d’errore relativa a questo file JSP.

<%@page errorPage="errorPage.jsp?log=errore.jsp"%>

In questo modo abbiamo detto al Container che la pagina d’errore sarà errorPage.jsp. Inoltre abbiamo passato un parametro alla pagina d’errore, indicando quale sia la pagina che l’ha richiamata. Ora andiamo a scrivere la semplice pagina d’errore.

<%@page contentType="text/html"%>
<%@page pageEncoding="UTF-8"%>
<%@page isErrorPage="true"%>

<html>
    <head>
        <meta http-equiv="Content-Type" 
              content="text/html; charset=UTF-8">
        <title>Error Page</title>
    </head>
    <body>

    <h2>Error Page del nostro sito</h2>
    Pagina di provenienza: <%=request.getParameter("log")%><br>
    <table border=1>
    <tr>
      <td><strong>Messaggio d'errore</strong></td>
      <td><%= exception.getMessage() %></td>
    </tr>     
    <tr>
      <td><strong>toString</strong></td>
      <td><%= exception.toString() %></td>
    </tr>
    <tr>
      <td><strong>Stack Trace</strong></td>
      <td>
    <%
      exception.printStackTrace(new java.io.PrintWriter(out));  
    %>
    </td></tr> 
    </table>

    </body>
</html>

Allora la prima cosa da fare è dichiarare nella direttiva page il fatto che la pagina in questione è una pagina d’errore, settando l’attributo errorPage a true. Solo in questo modo possiamo manipolare senza problemi l’oggetto implicito exception, che rappresenta appunto l’eccezione che è stata generata.

Ora che abbiamo exception possiamo utilizzare tranquillamente i suoi metodi per poter comunicare all’utente l’errore generato e la pagina di provenienza. Chiaramente all’interno di un sito complesso dovremo inserire questa pagina JSP in un template, rispettando elementi grafici che sono sempre presenti nel sito come banner, menu e disclaimer.

Custom error page

Custom error page

Conclusioni

In questo articolo abbiamo approfondito le varie potenzialità che offre JSP. Abbiamo visto quanto sia utile costruirsi un JavaBean per contenere i dati della nostra applicazione ed utilizzare le JSP Action per poi accedere a questo bean. Gli strumenti che JSP mette a nostra disposizione sono chiaramente più di quelli che abbiamo visto e quindi per ogni argomento che abbiamo trattato ci sarebbe chiaramente da approfondire il discorso.

 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.