CERCA SITEMAP FEED RSS 1280
Ultimo aggiornamento: 30 Agosto 2009

Le Servlet

Una servlet è un programma scritto in java in grado di estendere funzionalità e capacità di un server: sebbene le servlet si prestino all’elaborazione di qualsiasi tipo di richiesta esse sono principalmente utilizzate per implementare web application ovvero applicazioni accessibili tramite browser.
I package javax.servlet e javax.servlet.http definiscono le interfacce e le classi necessarie all’implementazione di servlet: queste devono necessariamente implementare l’interfaccia Servlet che definisce quelli che sono i metodi del ciclo di vita della servlet stessa.
Il ciclo di vita di una servlet è controllato dal web container all’interno del quale la servlet stessa vive; ad ogni richiesta della servlet il container compie le seguenti operazioni:
  • se non esiste alcuna istanza della servlet carica la classe della servlet, ne crea un’istanza, invoca il metodo init() per inizializzare la servlet e quindi invoca il metodo service per processare la richiesta ed ottenere una risposta.
  • se esiste già un’istanza della servlet allora il web container provvede ad invocare direttamente il metodo service.
Quando la servlet deve essere rimossa viene invece invocato il metodo destroy().
Tipicamente quando occorre implementare un servizio generico si crea una servlet che estende la classe GenericServlet (indipendente dal protocollo) se invece si vuole implementare un servizio http-based si estende la classe HttpServlet che fornisce appunto metodi per il processing di richieste http.
I package javax.servlet e javax.servlet.http contengono inoltre le interfacce per l’implementazione di filtri e listener: i primi effettuano operazioni di filtraggio sulle richieste in ingresso alla servlet o sulle risposte prodotte dalla servlet stessa e trovano applicazione in operazioni di autenticazione, compressione dati, logging ... i secondi invece permettono di monitorare gli eventi che si manifestano all’interno di una web application (dagli eventi che coinvolgono le sessioni utente a quelli che coinvolgono la configurazione del Context di una web application).

Interfaccia Servlet

L’interfaccia Servlet sta alla base di tutte le implementazioni di servlet siano queste indipendenti da un protocollo (GenericServlet) che dipendenti da un protocollo di comunicazione (HttpServlet).
Essa definisce i metodi che "scandiscono" quello che è il ciclo di vita di una servlet.

Il metodo init

init(ServletConfig servletconfig) viene invocato dal servlet container per inizializzare la servlet attraverso un oggetto ServletConfig mediante il quale la servlet può recuperare non solo i parametri di configurazione definiti nel Deployment Descriptor della web application ma accedere direttamente al Context della web application.
Generalmente il metodo init viene sovrascritto per far compiere alla servlet una serie di operazioni di inizializzazione e recupero di risorse che potrebbero essere utilizzate durante la fase di processing delle richieste che la servlet riceve.
L’oggetto ServletConfig permette di:
  • recuperare i nomi dei parametri di configurazione della servlet indicati nel Deployment Descriptor mediante il metodo getInitParameterNames()
  • recuperare il valore di un parametro di configurazione noto che sia il nome mediate il metodo getInitParameter(String name)
  • recuperare il ServletContext mediante il metodo getServletContext()
L’oggetto ServletContext definisce una serie di metodi mediante i quali la servlet può comunicare col suo servlet container: generalmente esiste un ServletContext per ogni web application in esecuzione.

Attraverso l’oggetto ServletContext la servlet può:
  • recuperare attributi del servlet container getAttribute(String attribute)
  • settare attributi del servlet container setAttribute(String name, Object object)
  • rimuovere attributi dal servlet container removeAttribute(name attribute)
  • memorizzare messaggi di loggia in un servlet log file log(String message)
  • recuperare il mime type associato ad un determinato file (con una determinata estensione) etMimeType(String file)

Il metodo service

Il metodo service(ServletRequest req, ServletResponse res) viene invocato dal servlet container per permettere alla servlet di processare una richiesta a lei rivolta: tale metodo naturalmente può essere invocato soltanto dopo che la servlet è stata inizializzata ovvero quando il metodo init(ServletConfig servletconfig) ha terminato il suo "lavoro" con successo.
Gli oggetti ServletRequest e ServletResponse costituiscono di fatto due interfacce che rappresentano la richiesta che la servlet deve processare e la risposta che la servlet produce.

L’interfaccia ServletRequest definisce una serie di metodi che permettono di accedere al contenuto informativo della richiesta stessa; in particolare è possibile:
  • determinare la lunghezza in byte della richiesta getContentLegth()
  • recuperare la codifica dei caratteri utilizzata getCharacterEncoding()
  • recuperare nomi e valori degli attributi associati alla richiesta getAttributeNames() getAttribute(String name)
  • recuperare il mime type del contenuto della richiesta getContentType()
  • recuperare lo strema di input associato alla richiesta getInputStream()
  • recuperare il protocollo utilizzato getProtocol()
  • indirizzo IP del client getRemoteAddr()
  • recuperare nomi e valori dei parametri della richiesta getParameterNames() e getParameterValue(String name)
  • settare e rimuovere attributi associati alla richiesta removeAttribute(String name) setAttribute(String name, Object object)
Allo stesso modo l’interfaccia ServletResponse rappresenta la risposta della servlet e contiene pertanto metodi per settarne il contenuto informativo, la codifica dei caratteri utilizzata, il mime type del contenuto...

Il metodo destroy

Il metodo destroy() infine viene invocato dal servlet container per liberare le risorse in memoria e comunicare alla servlet di interrompere il suo servizio.
E’ opportuno precisare che dal momento che le servlet agiscono quasi sempre in ambienti multi-threading, tale metodo viene invocato soltanto quando tutti i thread all’interno del metodo service escono dallo stesso o superano un periodo di time-out.

HttpServlet

Quando una servlet fornisce un servizio basato su protocollo http è opportuno fare riferimento ad una HttpServlet appartenente al package javax.servlet.http.

Una HttpServlet fornisce dei metodi aggiuntivi rispetto a quelli descritti dall’interfaccia Servlet:
  • doGET viene invocato per rispondere alle richieste http di tipo GET che la servlet riceve
  • doPOST per rispondere alle richieste di tipo POST
  • doPUT per rispondere alle richieste http di tipo PUT
  • doDELETE per le richieste http di tipo DELETE
Il metodo service(HttpServletRequest request, HttpServletResponse response) è definito in maniera tale da invocare il giusto metodo fra quelli elencati a seconda del tipo di richiesta http ricevuta (get, post ...).
Per i metodi init(ServletConfig servletconfig) e destroy() valgono invece le considerazioni viste per l’interfaccia Servlet: occorre cioè sovrascriverli per implementarne la logica di inizializzazione e il rilascio delle risorse.
La richiesta http è rappresentata dall’oggetto HttpServletRequest che costituisce un’implementazione http dell’oggetto ServletRequest e quindi ne implementa tutti i metodi e permette inoltre di:
  • recuperare gli oggetti Cookie inviati dal client con una richiesta getCookies()
  • recuperare i nomi getHeaderNames() ed i valori getHeader(String name) degli header della richiesta http
  • recuperare il method della richiesta http (GET, POST ...)
  • recuperare la sessione associata alla richiesta http ed eventualmente crearne una nuova getSession()
L’oggetto HttpServletResponse rappresenta invece la risposta http prodotta dalla servlet in seguito ad una richiesta, implementa l’interfaccia ServletResponse definendone tutti i metodi fra cui:
  • addCookie(Cookie cookie) aggiunge il cookie indicato alla risposta http
  • addHeader(String name, String value) aggiunge l’header alla risposta http
  • sendError(int sc) invia il codice di errore indicato come parametro
  • sendRedirect(String location) invia un redirect al client verso l’indirizzo indicato come parametro
Il seguente esempio mostra una servlet http che configura una stringa in base al valore di un parametro definito nel Deployment Descriptor e la invia in risposta a tutte le richieste GET che riceve dai client:
<web-app>

   ...

   <servlet>
      <servlet-name>MiaServlet</servlet-name>
      <servlet-class>MiaServlet</servlet-class>
      <init-param>
         <param-name>parametro1</param-name>
         <param-value>Ciao, benvenuto sul mio sito.</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>
   </servlet>

   ...

   <servlet-mapping>
      <servlet-name>MiaServlet</servlet-name>
      <url-pattern>/miaservlet/</url-pattern>
   </servlet-mapping>

   ...

</web-app>
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class MiaServlet extends HttpServlet
{
   String miastringa;

   public void init(ServletConfig config)
   {
      miastringa = config.getInitParameter("parametro1");
   }

   public void doGet(HttpServletRequest req, HttpServletResponse res)
   {
      try
      {
         PrintWriter printwriter = res.getWriter();
         printwriter.print(miastringa);
         printwriter.flush();
      }
      catch(Exception ecc)
      {
      }
   }

   public void destroy()
   {
   }

}

Condivisione di oggetti

Le web application più complesse sono generalmente costituite da web component che condividono informazioni in diversi modi: mediante oggetti che sono attributi di visibilità pubblica, utilizzando database o invocando altre risorse web.

Gli oggetti condivisi mediante attributi possono avere quattro tipi differenti di visibilità:
  • web context: gli oggetti vengono memorizzati, rimossi e recuperati all’interno del ServletContext associato ad ogni web application mediante i metodi setAttribute(String name, Object oggetto) , removeAttribute(String nome) e getAttribute(String name)
  • session: gli oggetti memorizzati, rimossi e recuperati come attributi di una sessione mediante i metodi setAttribute(String name, Onject object) , removeAttribute(String nome) e getAttribute(String name) dell’oggetto HttpSession possono essere recuperati da qualsiasi richiesta che si svolge all’interno della sessione.
  • request: gli oggetti memorizzati, rimossi e recuperati come attributi di una sessione mediante i metodi setAttribute(String name, Object object) , removeAttribute(String nome) e getAttribute(String name) dell’oggetto ServletRequest e possono essere recuperati dagli oggetti che partecipano al processing della richiesta stessa.
  • page: gli oggetti creati all’interno di una Java Server Page hanno visibilità all’interno della pagina stessa.
La visibilità context viene di solito attribuita a quegli oggetti che devono poter essere recuperati da tutti i web component che costituiscono la web application e che sono importanti nella configurazione della stessa.
La visibilità session viene utilizzata per memorizzare informazioni che riguardano un determinato utente o meglio la sua attività di interazione con la web application stessa.
La visibilità request viene invece utilizzata quando una richiesta http viene processata da più web component prima di restituire una risposta: ad esempio due servlet che compiono due operazioni differenti.

Per inoltrare una richiesta da un web component ad un altro si utilizza l’oggetto RequestDispatcher il quale contiene due metodi:
  • forward(ServletRequest request, ServletResponse response) inoltra la richiesta al web component indicato dal RequestDispatcher
    dispatcher = getServletContext().getRequestDispatcher(url);
    dispatcher.forward(request, response);
    
  • include(ServletRequest request, ServletResponse response) invece include la risorsa web indicata dal RequestDispatcher all’interno della risposta generata dalla servlet
    dispatcher = getServletContext().getRequestDispatcher(url);
    dispatcher.include(request, response);
    

Cookie

La classe Cookie rappresenta una piccola quantità di informazioni che viene inviata dal server al browser web che le memorizza per poi inviarle insieme alle successive richieste: occorre naturalmente che il browser web sia abilitato alla gestione dei cookie.

Un Cookie è costituito da un nome ed un valore ed una serie di attributi aggiuntivi che possono essere impostati mediante i seguenti metodi:
  • setComment(String comment) rappresenta una descrizione testuale del cookie
  • setDomain(String dominio) rappresenta il dominio web al quale il browser web deve presentare questo cookie insieme alle sue richieste http.
  • setMaxAge(int expiry) indica la durata in secondi del cookie
  • setValue(String newValue) assegna un nuovo valore al cookie che è già stato creato
I cookie vengono inviati al browser web mediante il metodo addCookie(Cookie cookie) della classe HttpServletResponse e recuperati da una richiesta http mediante il metodo getCookies() della classe HttpServletRequest.

Implementazione di listener

Un listener permette di registrare gli eventi che si verificano al’interno di una web application e nel corso dell’interazione con l’utente.

Esistono otto diverse classi per l’implementazione di listener di eventi:
  • ServletContextListener notifica gli eventi di inizializzazione e distruzione del ServletContext mediante i metodi:
    • contextInitialized(ServletContextEvent sce)
    • contextDestroyed(ServletContextEvent sce)
  • ServletContextAttributeListener notifica gli eventi relativi all’aggiunta, rimozione e sostituzione degli attributi associati al ServletContext mediante i metodi:
    • attributeAdded(ServletContextAttributeEvent scab)
    • attributeRemoved(ServletContextAttributeEvent scab)
    • attributeReplaced(ServletContextAttributeEvent scab)
  • ServletRequestListener permette di notificare gli eventi di ingresso e uscita di una richiesta http dal processing della web application mediante i metodi:
    • requestInitialized(ServletRequestEvent sre)
    • requestDestroyed(ServletRequestEvent sre)
  • ServletRequestAttributeListener riceve notifica dei cambiamenti agli attributi di una richiesta http finchè non viene elaborata una risposta mediante i metodi:
    • attributeAdded(ServletRequestAttributeEvent srae)
    • attributeRemoved(ServletRequestAttributeEvent srae)
    • attributeReplaced(ServletRequestAttributeEvent srae)
  • HttpSessionListener riceve notifica della creazione o distruzione di sessioni utente attraverso i metodi:
    • sessionCreated(HttpSessionEvent se)
    • sessionDestroyed(HttpSessionEvent se)
  • HttpSessionActivationListener riceve notifica degli eventi di attivazione o disattivazione di sessioni utente tramite:
    • sessionDidActivate(HttpSessionEvent se)
    • sessionWillPassivate(HttpSessionEvent se)
  • HttpSessionAttributeListener riceve notifica degli eventi relativi all’aggiunta, rimozione e sostituzione di attributi relativi alla sessione attraverso i metodi:
    • attributeAdded(HttpSessionBindingEvent se)
    • attributeRemoved(HttpSessionBindingEvent se)
    • attributeReplaced(HttpSessionBindingEvent se)
Per definire un listener occorre implementare una delle precedenti interfacce definendone i metodi e quindi dichiararne la presenza all’interno del Web Application Deployment Descriptor mediante l’elemento <listener>.
<listener>
   <listener-class>MioContextListener</listener-class>
</listener>

Implementazione di filtri

Un filtro è un oggetto che può trasformare l’header e il contenuto di una richiesta o di una risposta.

Un filtro fornisce funzionalità indipendenti dalla risorsa web alla quale è applicato; i suoi usi più comuni riguardano:
  • la compressione dei dati
  • trasformazioni di dati (ad esempio conversioni di formati di immagini)
  • criptazione
  • logging
  • operazioni di autenticazione
Le interfacce coinvolte nell’implementazione di un filtro sono Filter, FilterChaing e FilterConfig.

L’interfaccia Filter contiene tre metodi:
  • init(FilterConfig) viene invocato dal web container all’atto dell’inizializzazione di un filtro ed utilizza un oggetto FilterConfig che immagazzina tutti i parametri di configurazione definiti nel Deployment Descriptor.
  • doFilter(ServletRequest request, ServletResponse response, FilterChain chain) effettua l’operazione di filtraggio vera e propria effettuando le seguenti operazioni:
    • esamina la richiesta
    • effettua opzionali operazioni di filtraggio sul contenuto della richiesta
    • effettua opzionali operazioni di filtraggio sul contenuto della risposta
    • invoca il successivo filtro da applicare mediante il metodo doFilter(ServletRequest request, ServletResponse response) della classe FilterChain (che rappresenta appunta la catena di filtri definiti nel Deployment Descriptor) oppure decide di arrestare il proessing della richiesta
    • esamina l’header della risposta dopo aver invocato il filtro successivo.
    • destroy viene invocato dal web container per liberare le risorse e distruggere il filtro
Per definire un filtro occorre implementarne l’interfaccia Filter definendone opportunamente i metodi e quindi effettuarne il mapping nel Deployment Descriptor utilizzando gli elementi <filter> e <filter-mapping>
<web-app>

   ...

   <filter>
      <filter-name>MioFiltro</filter-name>
      <filter-class>MioFiltroClass </filter-class>
      <init-param>
         <param-name>message</param-name>
         <param-value>Messaggio di prova</param-value>
      </init-param>
   </filter>

   ...

   <filter-mapping>
      <filter-name>MioFiltro</filter-name>
      <url-pattern>/filter.jsp</url-pattern>
   </filter-mapping>

   ...

</web-app>
public final class MioFiltro implements Filter
{
   String messaggiofiltro;

   public void init(FilterConfig filterConfig) throws ServletException
   {
      messaggiofiltro = filterConfig.getInitParameter("message");
   }

   public void destroy()
   {
   }

   public void doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws IOException, ServletException
   {
      if (filterConfig == null)
      return;
      StringWriter sw = new StringWriter();
      PrintWriter writer = new PrintWriter(sw);
      writer.println();
      writer.println(messaggiofiltro);
      writer.flush();

      ...
      chain.doFilter(request, wrapper);
      ...
   }

}