MokaByte Numero 11 - Settembre 1997
I Servlet 
 
di
Fabrizio Giudici
Parliamo delle Servlet API indispensabile strumento per la creazione e manutenzione di applicazioni server Web  

 


La diffusione del WWW come standard di distribuzione di dati sia in Internet che nelle Intranet ha portato ad una proliferazione di servizi di rete basati su di esso. Per gli utenti è effettivamente molto facile poter accedere a tutti i dati e servizi di cui hanno bisogno con una procedura unificata e semplice come il browsing con Netscape od Explorer; ma per chi deve progettare (e manutenere) tali servizi il compito è spesso più difficile.
Sun ha dedicato un'intera API, la Server API, per gestire in modo efficiente e standardizzato queste problematiche. In quest'articolo analizziamo uno dei componenti principali della Server API: i Servlet.

 

Introduzione

Progettare un servizio di rete basato sulla tecnologia WWW implica il trasferimento di dati tra un browser ed un server. Nel caso più semplice, si progetta una form HTML che riceve i dati dall'utente e si invoca un programma sul server che legge ed elabora questi dati e produce una risposta. Realizzare una form HTML è un compito molto semplice: basta definire i campi di input necessari e scrivere poche righe di HTML. Se si utilizzano tool visuali, come Microsoft FrontPage, è ancora più semplice. La parte più complessa è l'interfacciamento con il server.

Generalmente, le form HTML vengono processate eseguendo un opportuno programma sul server WWW, programma che riceve i parametri immessi nella form attraverso il ben noto protocollo Common Gateway Interface (CGI). Semplificando al massimo, il programma viene eseguito dal server httpd quando l'utente preme un pulsante di conferma, e si ritrova i dati immessi nella form sotto forma di variabili d'ambiente (ad esempio PARAM=VALUE).

Siccome ogni programma Java deve essere lanciato attraverso l'interprete java, dobbiamo scrivere un piccolo wrapper, per esempio in Unix:

 
#!/bin/sh CLASSPATH=… /opt/jdk1.1.1/bin/java MyService

Questa soluzione è semplice, ma ha dei problemi:

  1. Non è portabile, perché non ci sono linguaggi di script comuni a Unix e Windows (con la possibile eccezione del Perl).
  2. Non è efficiente perché lo script manderebbe in esecuzione una shell per la sua interpretazione: un processo inutile che consumerebbe risorse di sistema operativo e rallenterebbe le operazioni. In ogni caso, lo stesso protocollo CGI è notoriamente inefficiente.
Va anche notato che il processo CGI deve anche generare una pagina HTML "di risposta", cioè una pagina che viene visualizzata dopo che l'utente ha confermato i dati nella form, tipicamente per comunicare se l'operazione è andata a buon fine. Spesso, le pagine di risposta devono visualizzare dati dinamici formattati in stili pre-definiti, e tipicamente ciò si ottiene codificando a mano il codice HTML da generare dentro il processo CGI. È un approccio chiaramente non flessibile, dal momento che semplici cambiamenti di "estetica" (cioè allo stile) richiedono ricodifica del processo CGI, con conseguente ricompilazione.

Ma andiamo per ordine, e ritorniamo al problema dell'efficienza. Oltre alla CGI, sono stati proposti altri protocolli di interfacciamento: tra i più noti il Netscape Server API (NSAPI) di Netscape. NSAPI permette di interfacciare codice Java direttamente con il il server WWW e quindi, non richiedendo alcun programma wrapper, è un approccio portabile. Purtroppo NSAPI è attualmente supportato solo dai server di Netscape (ad esempio FastTrack) e quindi introduce un altro tipo di limitazione alla portabilità.

Java ci offre una soluzione più attraente: i Servlet.

 

La Servlet API

I servlet sono applicazioni Java che vengono eseguite come parti di una pagina HTML, ma a differenza degli applet, essi risiedono sul lato server. Per essere più precisi, la loro definizione generale è "componenti da lato-server per l'estensione di server Java-enabled", cioè un qualcosa di più generale del solo WWW; ma in questo articolo ci concentriamo solo sui cosiddetti "Servlet HTML".

Per scrivere un generico servlet HTML è sufficiente ereditare dalla classe HttpServlet e definire un apposito metodo service() che viene richiamato quando viene richiesto un servizio; esistono speciali metodi per accedere ai parametri che provengono dalla form HTML, ed anche uno stream di output predefinito che ci consente di generare la "pagina di risposta". In pratica, ci bastano pochissime righe di codice per trasformare un qualsiasi programma in un servlet:
 

 
    public class MyService extends HttpServlet{ 
         public void service (HttpServletRequest req, HttpServletResponse res)
       throws ServletException{ 
          res.setContentType("text/html"); 
          res.setHeader("Pragma", "no-cache"); 
          res.writeHeaders(); 
          String param = req.getParameter("param"); 
          // esegui programma di servizio 
          OutputStream out = res.getOutputStream(); 
          // usa out per scrivere sulla pagina di risposta 
       }
    }
 

Grazie alle strutture HttpServletRequest e HttpServletResponse possiamo accedere facilmente ai parametri passati al servlet (con getParameter()) o generare l'output (attraverso uno stream fornitoci da getOutputStream()). Con i metodi setContentType() e setHeader() possiamo stabilire il tipo MIME della pagina di risposta e, nel caso sia HTML, avere un controllo fine su alcuni parametri (nell'esempio settiamo una "pragma no-cache" per impedire al browser che leggerà la pagina di risposta di metterla nella cache). Veloce, semplice ed elegante…

I servlet vengono associati a URL speciali, proprio come avviene per i programmi CGI. Per esempio, potremmo mappare il servlet MyServlet alla URL http://www.mysite.com/servlets/myservice, e mettere questa URL nel campo ACTION della nostra FORM:

 

<FORM METHOD="POST" ACTION="/servlets/myservice"> 
    Enter data: <INPUT TYPE="text" NAME="data"><BR> 
</FORM>

A differenza dei programmi CGI, l'esecuzione di un servlet non richiede la creazione di un nuovo processo, dal momento che server WWW servlet-enabled contengono una Java virtual machine che, semplicemente, carica dinamicamente una nuova classe. In pratica, il servlet diventa parte integrante dello stesso server WWW. Questo è ancora più evidente se si considerano i server WWW interamente scritti in Java, come Jigsaw del W3 Consortium o il Java Server (ex Jeeves) di Sun. Per ottenere tempi di risposta ancora più rapidi, si possono configurare situazioni in cui il codice del servlet viene precaricato all'avvio.

Ci sono molti diffusi server WWW che già oggi supportano i servlet, o che comunque possono essere facilmente adattati per il loro supporto: Netscape Fasttrack, Apache (con il suo derivato commerciale Stronghold) ed il Microsoft Internet Information Server (IIS). E siccome la Servlet API è una Standard Java Extension, molto probabilmente nel futuro prossimo verrà supportata dalla grande maggioranza dei server WWW - esattamente allo stesso modo in cui la grande maggioranza dei browser WWW oggi supportano gli applet.

Affrontiamo ora il problema della generazione di pagine HTML dinamiche, ma in conformità ad uno stile predefinito. Per essere più precisi, la situazione è la seguente: abbiamo un template di pagina HTML in cui solo alcune parti devono essere generate dinamicamente, ed è opportuno mantenere ben separate la definizione del template (con la sua "estetica") da quella del generatore di dati dinamici. Tanto per fare un esempio:

 

<HTML> 
<BODY> 
    <!— aesthetic definitions… --> 
    <p>The reply for your question is $REPLY</p> 
    <!— aesthetic definitions… --> 
</BODY> 
</HTML>

Stiamo supponendo di avere una sorta di "metavariabile" ($REPLY) che dev'essere dinamicamente rimpiazzata da contenuti dinamici. I Servlet permettono questo approccio: oltre al metodo d'invocazione simile alla CGI, essi possono essere eseguiti utilizzando uno speciale tag HTML, SERVLET, come si può vedere in quest'esempio (supponiamo che sia la pagina http://www.mysite.com/service.html):

 

<HTML> 
<BODY> 
    <!— aesthetic definitions… --> 
    <p>The response is: <i> 
    <SERVLET NAME=MyServlet> 
    <PARAM NAME=param1 VALUE=val1> 
    <PARAM NAME=param2 VALUE=val2> 
    </SERVLET> 
    </i></p> 
    <!— aesthetic definitions… --> 
</BODY> 
</HTML>

Quanto questa pagina viene richiesta al server WWW, tutti i tag SERVLET mandano in esecuzione il loro rispettivo servlet, e vengono sostituiti dall'output prodotto da quest'ultimo; è in pratica un raffinamento del "vecchio" concetto di Server Side Include (SSI). Va notato che questo meccanismo non è un'estensione del codice HTML: i browser che richiedono questa pagina non vedranno mai il tag SERVLET, ma del comune codice HTML standard.

Ad ogni servlet possono essere passati parametri "fissi" utilizzando il campo PARAM, ma essi sono in grado di accedere ai tipici parametri inseriti nelle URL come quelli generati dalle form HTML, ad esempio http://www.mysite.com/myservice.html?url=myurl&user=fred.

Questa caratteristica dei servlet ne fa un eccellente strumento per gestire l'input di dati attraverso form HTML, ed è potentissima. Per esempio, possiamo facilmente pensare ad un servlet che, utilizzando la JDBC-API (Java DataBase Connectivity API), permette di integrare interrogazioni SQL in una pagina WWW…

Va tenuto presente che il tempo di vita di un servlet rimane limitato al tempo vita della pagina in cui è integrato; tanto per fare un esempio, il browser dell'utente continua a visualizzare l'indicatore di "operation in progress" fino a quando il servlet termina la sua esecuzione. Questo fatto ci crea dei problemi se dobbiamo far partire un servizio in modalità asincrona (cioè se viene generata una risposta immediata all'utente mentre il programma di servizio continua a girare). Se da un lato si potrebbero tentare strade come la generazione di thread paralleli, dobbiamo comunque ricordarci che il servlet viene eseguito come parte del server WWW, ed un Security Manager limita il suo campo d'azione. Se per ragioni progettuali è necessario implementare il servizio con un programma stand-alone., possiamo fare riferimento all'ormai nota "architettura client/server a tre strati", in cui il servlet agisce solo come interfaccia tra WWW e programma di servizio. La comunicazione tra servlet e programma stand-alone può essere facilmente gestita con la RMI-API (di cui abbiamo parlato in un precedente numero di Mokabyte).

 

Conclusione

Riassumendo: i servlet sono un potente meccanismo per scrivere applicazioni server di Internet o Intranet, che possono avvantaggiarsi dei classici punti di forza di Java, come portabilità, riuso effettivo del codice, robustezza e così via. In particolare è da sottolineare la sicurezza dell'approccio: i servlet vengono controllati da un Security Manager analogo a quello degli applet, e questo dà agli sviluppatori la libertà di scrivere estensioni ai loro server senza aprire pericolosi "buchi" nella sicurezza della propria rete. Vale la pena di ricordare, infatti, che una parte degli attacchi alla sicurezza dei server WWW viene eseguita sfruttando bug presenti nei programmi CGI o, in generale, in estensioni del server.

  

 

MokaByte rivista web su Java

MokaByte ricerca nuovi collaboratori
Chi volesse mettersi in contatto con noi può farlo scrivendo a mokainfo@mokabyte.it