Java Servlet API
• package javax.servlet: include classi e interfacce
di gestione di servlet indipendenti da protocollo di
comunicazione
• package javax.servlet.http: include classi e
interfacce specifiche per uso di servlet con
protocollo HTTP
• alcune classi e interfacce di javax.servlet.http
estendono le rispettive di javax.servlet
Laboratorio di Servizi Web - servlet Ardissono
1
Porzione di gerarchia delle classi - servlet
interface javax.servlet.Servlet
•init(ServletConfig c)
•service(ServletRequest req,
ServleResponse res)
•destroy(), … altri metodi ...
interface
javax.servlet.ServletConfig
mantiene dati di
configurazione di servlet
abstract class javax.servlet.GenericServlet
implements Servlet, ServletConfig, Serializable
offre implementazione di interfaccia Servlet indipendente
da protocollo di comunicazione (HTTP, …)
abstract class javax.servlet.http.HttpServlet
extends GenericServlet implements Serializable
offre implementazione di interfaccia Servlet specifica per HTTP
Laboratorio di Servizi Web - servlet Ardissono
2
javax.Servlet - Interface ServletConfig
specifica metodi per accedere a parametri di
configurazione di Servlet (es. database driver, costanti
globali della Servlet, …)
– public String getInitParameter(String name)
• restituisce valore di parametro di inizializzazione “name”,
se esiste. Null altrimenti
– public Enumeration getInitParameterNames()
• restituisce enumerazione di nomi dei parametri di
inizializzazione della Servlet
– public String getServletName()
– ...
Laboratorio di Servizi Web - servlet Ardissono
3
javax.Servlet - Interface Servlet - I
specifica metodi di gestione della Servlet
– public void init(ServletConfig c) throws ServletException
• invocato da Web Container dopo aver istanziato Servlet
• inizializza variabili di servlet (prima di accettare HTTP requests). Es:
leggere dati di configurazione, registrare database driver, …
– public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
• invocato da Web Container ad ogni HTTP request (oggetto req
contiene dati di richiesta, res contiene risposta)
– public void destroy()
• invocato da Web Container prima di rimuovere istanza di Servlet (es:
prima di shut down di web server, o se serve spazio di memoria, …)
Laboratorio di Servizi Web - servlet Ardissono
4
javax.Servlet - Interface Servlet - II
Offre anche metodi per accedere a informazioni generiche
su Servlet e a oggetto ServletConfig
(questi metodi sono usati nel codice delle classi da noi
implementate che estendono le Servlet)
– ServletConfig getServletConfig()
• restituisce oggetto ServletConfig di una Servlet
– String getServletInfo()
• restituisce informazioni generali su Servlet (autore, data di
creazione, ...)
Laboratorio di Servizi Web - servlet Ardissono
5
javax.Servlet.http - abstract class HttpServlet - I
– public void service(ServletRequest req,
ServleResponse res)
• implementa metodo service di GenericServlet. Fa cast di
ServletRequest/ServletResponse ad
HttpServiceRequest/HttpServiceResponse e invoca
metodo service protected.
• Non ridefinire!!
– protected void service(HttpServletRequest req,
HttpServleResponse res)
• invoca req.getMethod per sapere se è GET, POST, HEAD,
… e delega gestione a metodo doXXX specifico….
• Non ridefinire!!!
Laboratorio di Servizi Web - servlet Ardissono
6
javax.Servlet.http - abstract class HttpServlet - II
– protected void doGet(HttpServletRequest req,
HttpServleResponse res)
• gestisce HTTP request di tipo GET. Ridefinibile
– protected void doPost(HttpServletRequest req,
HttpServleResponse res)
• gestisce HTTP request di tipo POST. Ridefinibile
– protected void doHead(HttpServletRequest req,
HttpServleResponse res)
• gestisce HTTP request di tipo HEAD. Ridefinibile
– ...
Laboratorio di Servizi Web - servlet Ardissono
7
Invocazione di servlet
Invoca metodo
pubblico service di Servlet
Web container
Web
server
POST
HTTP
Web
browser
service(req, res)
service (protected)
fa cast di parametri
e invoca
doXXX(req, res)
doXXX gestisce
richiesta
HttpServlet
NB: metodo
service
eseguito
in thread di
processo
principale
gestione
parallela di
richieste,
ma leggera
Ridefinendo metodi doXXX
integriamo logica applicativa
in funzionalità offerte da web server
Laboratorio di Servizi Web - servlet Ardissono
8
Porzione di gerarchia delle classi - Request
Interface javax.servlet.ServletRequest
offre
• metodi per accedere a connessione client
• input stream associata a connessione
supporta lettura di dati da input stream
InputStream
ServiceInputStream
interface javax.servlet.http.HttpServletRequest
offre implementazione di ServletRequest specifica per HTTP
Laboratorio di Servizi Web - servlet Ardissono
9
Porzione di gerarchia delle classi - Response
Interface javax.servlet.ServletResponse
offre
• metodi per accedere a connessione client
• output stream associata a connessione
supporta scrittura dati per client
OutputStream
ServiceOutputStream
interface javax.servlet.http.HttpServletResponse
offre implementazione di ServletResponse specifica per HTTP
Laboratorio di Servizi Web - servlet Ardissono
10
Metodi per comunicazione con client - I
• javax.http.HttpRequest
– String getParameter(String parameterName)
• parsifica contenuto di request HTTP ed estrae valore di
parametro “parName”
• Es:
– String tipoInfo = req.getParameter("tipoInfo");
– String loginName = req.getParameter("login");
FORM HTML
...
<input type="text" name="login"
align="left" size="25">
<input type="password" name="passwd"
align="left” size=“25”>
Laboratorio di Servizi Web - servlet Ardissono
11
Metodi per comunicazione con client - II
• HttpResponse
– void setContentType(String mimeType)
• specifica formato MIME di output
– PrintWriter getWriter()
• restituisce oggetto PrintWriter costruito da Web
Container a partire da OutputStream associato a
connessione client
Laboratorio di Servizi Web - servlet Ardissono
12
Struttura standard di applicazione web
• Directory pubblica
swebi/
– contiene pagine HTML e JSP
• WEB-INF/web.xml
– file che descrive parametri di configurazione della
Servlet e varie proprietà
• WEB-INF/classes/
– contiene classi compilate delle Servlet e altre classi di
utilità, eventualmente organizzate in package
• WEB-INF/lib/
– contiene eventuali JAR file di librerie usate da
applicazione
Laboratorio di Servizi Web - servlet Ardissono
13
Esempio di prova (Hello)
/usr/home/studenti/labgroup/labsweb/swebi/
– file HTML: pagina.html
Applicazione di prova che
avete usato è in package
– WEB-INF
“application”.
• classes
Servlets separate da altre
classi per comodità ...
– application
» servlets: application.servlets.Hello.java
» other: altre classi di utilità
(application.other.InterrogaDB.java, …)
• web.xml: non specificato NB: se non si descrive servlet
in deployment descriptor si
– src (albero dei sorgenti)
rinuncia a usare configuration
parameters etc.
Laboratorio di Servizi Web - servlet Ardissono
14
Deployment descriptor - web.xml
• Un descrittore per ogni applicazione web
• file web.xml (associato a contesto di applicazione
- swebi)
• usato da Web Container per
– inizializzare applicazione web
– identificare applicazione invocata da HTTP request
• specifica
– parametri di inizializzazione di Servlet e applicazione
(es: URL di database usato da applicazione, …)
– definizione di servlets e JSPs di applicazione
– ….
Laboratorio di Servizi Web - servlet Ardissono
15
Altro esempio
Estendiamo applicazione swebi, che
inizialmente faceva solo il saluto,
aggiungendo un altro tipo di servizio:
richiesta informazioni personali
Implementiamo una nuova servlet
(Informazioni.java), in aggiunta ad
Hello.java, che invocheremo da una
pagina HTML
Laboratorio di Servizi Web - servlet Ardissono
16
Nota bene
• NB: anche se le due servlet sono parte della
stessa applicazione, non comunicano tra loro
• In generale, le servlet di un’applicazione
dovrebbero cooperare e bisognerebbe definire
applicazioni diverse, se si offrono servizi
indipendenti
• Tuttavia, ciascun gruppo di laboratorio
corrisponde, per questioni di configurazione del
web server, ad una diversa applicazione
usiamo applicazione per sviluppare tutte le
servlet che vogliamo (indipendentemente dal
fatto che c’entrino l’una con l’altra …)
Laboratorio di Servizi Web - servlet Ardissono
17
Gestione informazioni personali
• /usr/home/studenti/labgroup/labsweb/swebi/
– file HTML: richiesta.html
– WEB-INF
• classes
– application
» servlets: application.servlets.Informazioni.java
» other: nessuna classe di utilità
• web.xml
– src (albero dei sorgenti da compilare)
Laboratorio di Servizi Web - servlet Ardissono
18
swebi - web.xml - preambolo
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
DTD di web.xml
Descrizione applicazione web
<web-app>
<display-name>Web Application sweb40 </display-name>
<description> descrizione dell'applicazione... </description>
….
Laboratorio di Servizi Web - servlet Ardissono
19
swebi - web.xml - context parameters
<!-- Context parameters definiscono costanti di tipo String condivise tra più
servlet e JSP dell’applicazione. Questi parametri possono essere definiti dal
system administrator che istalla l’applicazione.
Da una servlet (o JSP) si accede ai valori assegnati ai parametri invocando
il seguente metodo:
String value = getServletContext().getInitParameter("name");
dove “name” corrisponde al nome dato
Parametri di
al parametro usando <param-name>
inizializzazione usati
-->
in tutta l’applicazione
<context-param>
web sono memorizzati
<param-name>contextPar</param-name>
nel contesto di
applicazione
<param-value>Questo parametro e’ generale
di applicazione </param-value>
<description> ... </description>
</context-param>
Laboratorio di Servizi Web - servlet Ardissono
20
swebi - web.xml - descrizione servlet
Descrizione di servlet
gestita da web container
<servlet>
<servlet-name>info</servlet-name>
Alias per
invocazione servlet
<description> Servlet che fornisce informazioni personali </description>
Nome della
classe servlet
<servlet-class>application.servlets.Informazioni</servlet-class>
<init-param>
<param-name>saluto</param-name>
<param-value>CIAO!! </param-value>
</init-param>
Laboratorio di Servizi Web - servlet Ardissono
Parametri di
inizializzazione di
servlet info
21
swebi - web-xml - ultima parte
<init-param>
<param-name>DB-URL</param-name>
<param-value>
jdbc:idb:/usr/home/studenti/labgroup/labsweb/sweb40/localDB/properties.prp
</param-value>
</init-param>
<!-- Load this servlet at server startup time -->
<load-on-startup>5</load-on-startup>
</servlet>
<servlet>
…… definizione di altra servlet ….
</servlet>
…...
</web-app>
Laboratorio di Servizi Web - servlet Ardissono
Specifico che
servlet deve essere
caricata (per quinta)
appena web server
viene lanciato
NON FATELO!!!!
22
Pagina web: richiesta.html - I
<HEAD>
<TITLE>RICHIESTA INFORMAZIONI</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF"
LINK="#CC33CC" VLINK="#970097" ALINK="#B300B3">
NB: posso invocare la
<h1> Richiesta di informazioni </h1>
servlet con nome di classe
<hr>
o con alias (alias più
<br>
robusto e flessibile)
<center>
<FORM ACTION="servlet/info" METHOD="POST" >
<!-<FORM ACTION="servlet/application.servlets.Informazioni"
METHOD="POST" >
-->
…..
Laboratorio di Servizi Web - servlet Ardissono
23
Pagina web: richiesta.html - II
<table align="center" width="100%" cellspacing="2" cellpadding="2">
<tr>
<td align="right">Login:</td>
<td> <input type="text" name="login" align="left" size="25"> </td>
</tr>
<tr>
<td align="right">Password:</td>
<td><input type="password" name="passwd" align="left”
size="25"></td>
...
Laboratorio di Servizi Web - servlet Ardissono
24
Pagina web: richiesta.html - III
<tr>
<td align="right">Tipo di informazioni:</td>
<td>
<select name="tipoInfo" SIZE="1">
<option value="no">Nessuna informazione</option>
<option value="nomi">Nomi persone</option>
<option value="cc">Conti correnti bancari</option>
</select>
</td>
</tr>
</table>
<CENTER>
<INPUT TYPE="Submit" NAME="btnSubmit" VALUE="Submit request">
</CENTER>
</FORM>
</BODY>
</HTML>
Laboratorio di Servizi Web - servlet Ardissono
25
Servlet Informazioni.java - I
package application.servlets;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.sql.*;
public class Informazioni extends HttpServlet {
String cheers;
String url;
Connection con;
public Informazioni() {
cheers = "";
url = “”;
con = null;
}
Costruttore classe
(usato da Web Container
per istanziare la servlet)
Laboratorio di Servizi Web - servlet Ardissono
26
Servlet Informazioni.java - II
public void init(ServletConfig config) throws ServletException {
super.init(config);
Prima di istruzioni di inizializzazione
specifiche eseguo metodo init di base!!
Chiedo a ServletConfig
object i valori dei parametri
di inizializzazione di servlet
cheers = config.getInitParameter("saluto");
url = config.getInitParameter("DB-URL");
try {
Class.forName("org.enhydra.instantdb.jdbc.idbDriver");
} catch (ClassNotFoundException e)
Carico Driver JDBC e
{ System.err.println(e);
catturo eccezioni forzando
throw new ServletException(e);}
ServletException...
}
Laboratorio di Servizi Web - servlet Ardissono
27
Servlet Informazioni.java - III
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/html");
Specifico contenuto
MIME di risposta
String tipoInfo = req.getParameter("tipoInfo");
String loginName = req.getParameter("login");
Estraggo parametri
da HTTPRequest
String contextP = getServletContext().getInitParameter(“contextPar”);
Prendo riferimento a oggetto
ServletContext (per recuperare
parametri generali
di applicazione)
Chiedo a oggetto ServletContext
valore di parametro generale
“contextPar” - vd web.xml
Laboratorio di Servizi Web - servlet Ardissono
28
Servlet Informazioni.java - IV
PrintWriter out = res.getWriter();
Inizio costruzione risposta
(pagina HTML
generata dinamicamente)
Chiedo a riferimento a oggetto
PrintWriter (da usare per
produrre output da inviare a
web server - HTTP response)
out.println("<HTML> <HEAD> <TITLE>Informazioni”
+ “</TITLE></HEAD>");
out.println("<BODY><CENTER><H1>" + cheers +
" Ecco le informazioni che desideri, "+loginName+
“</H1></CENTER> <BR>“);
out.println(contextP);
NB: In generale, i parametri
di applicazione sono par di
configurazione (qui lo uso
solo per fare una stampa…)
Laboratorio di Servizi Web - servlet Ardissono
29
Servlet Informazioni.java - V
… se tipoInfo è “no” stampo su out “no info”
altrimenti, se tipoInfo è “nomi” {
try { apro connessione a database;
eseguo query SQL e salvo risultati in Hashtable valori;
chiudo connessione;
Forzo
} catch (SQLException e)
ServletException
{ System.err.println(e);
throw new ServletException(e);}
if (valori==null) out.println("****** RISULTATO NULL");
else {
scorro ResultSer con cursore per estrarre informazioni;
stampo informazioni su oggetto PrintWriter (out);
}}
else out.println("Tipo di informazione non accessibile");
out.println(“</BODY></HTML>");
Chiudo PrintWriter
out.close(); }
Laboratorio di Servizi Web - servlet Ardissono
30
Ciclo di vita di una servlet
Servlet
inesistente
Istanziazione a startup
del container o in
seguito a HTTP request
Servlet
istanziata
inizializzazione
Garbage
collection
Destroyed
Unavailable
Servlet
Inizializz
inizializzata e/o
fallita
pronta per richieste
Fallimento
temporaneo
o permanente
HTTP request(s)
Fine
da client(s)
thread
service
Service
shut-down di web container
Laboratorio di Servizi Web - servlet Ardissono
31
Esecuzione metodo service
• Ad ogni HTTP request Web Container crea thread
per esecuzione richiesta
• richieste di client diversi gestite in parallelo
nell’ambito del processo principale, con poco spreco
di risorse computazionali
• MA: attenti agli accessi alle risorse in mutua
esclusione. Es:
– variabili globali di servlet, da non modificare in
parallelo
– accessi a DB che non garantiscono modifiche in
mutual esclusione (es: Microsoft Access)
Laboratorio di Servizi Web - servlet Ardissono
32
Deployment di applicazione - ant
• Usiamo tool ANT, che permette di effettuare molte
operazioni
– eliminazione e ricostruzione di directory
dell’applicazione sotto l’area di deployment (WEBINF/classes), per accertarsi che le classi compilate vecchie
vengano rimosse e ad ogni ricompilazione l’applicazione
sia completamente rinnovata
– compilazione classi java in directory di deployment
(WEB-INF/classes)
– installazione applicazione in web container (tomcat) (ant
install)
– eliminazione di installazione da web container (ant
remove)
– ….
Laboratorio di Servizi Web - servlet Ardissono
33
Deployment di applicazione – build - I
• ANT usa file di build passato come parametro, che
specifica operazioni di deployment (task eseguibili)
• vd alias definito in catEnv.sh
– alias ant '$JWSDP_HOME/jakarta-ant-1.5.1/bin/ant buildfile build.xml’
• ant install: task di installazione di applicazione
(rinnova directory, compila, installa)
• ant remove: rimuove installazione di applicazione
da web container
Laboratorio di Servizi Web - servlet Ardissono
34
Deployment di applicazione – build - II
• File di build da usare per deployment delle vostre
applicazioni in ambiente unix
• Versione da voi scaricata è la base
• Consideriamo versione estesa per vedere come
utilizzare anche classi generate da JAXB in
deployment di applicazione
• Vediamo alcune parti del file di build esteso:
definizione di properties (variabili), di task,
esecuzione task, ... Le parti relative a JAXB sono in
viola
Laboratorio di Servizi Web - servlet Ardissono
35
Deployment di applicazione – build - III
webapps
clean: rimuovo file
sweb01
sweb40
WEB-INF
prepare: ricreo directories
src
codice
sorgente
XMLSchema
classes
classi
Schemi
XML
bindXMLSchema: genero
compilate
coffee1
e classi
classi da schema XML (xjc)
first
application
generate
build: compilo classi
mettendo compilati
sotto classes
coffeeOrder.xsd
coffee1
CoffeeOrderType.java, …
Laboratorio di Servizi Web - servlet Ardissono
36
build.xml - I
<project name="helloWorld-example" default="build" basedir=".">
<target name="init">
Definizione properties usate
<tstamp/>
come variabili nel resto del file
</target>
<property name="jwsdp.path" value="/usr/NFS/Solaris/jwsdp-1.1" />
<property name="context.path”
value="/usr/home/studenti/labgroup/labsweb/sweb40" />
<property name="WEB-INF.path" value="${context.path}/WEB-INF" />
<property name="user.path”
value="/usr/home/studenti/labgroup/labsweb/sweb40" />
<property name="src.application.home" value="application" />
<property name="path" value="/sweb40"/>
<property name="deployed.application.path" value= "${WEBINF.path}/classes/${src.application.home}"/>
<property name="XSD.path" value="${user.path}/src/XMLSchema/" />
<property name="deployed.JAXBClasses.path"
value= "${WEB-INF.path}/classes/coffee1"/>
…...
Laboratorio di Servizi Web - servlet Ardissono
37
build.xml - II
Login e password
<property name="username" value=“sweb" />
per installare
<property name="password" value=“sweb" />
applicazioni in web
<property name="myPath" value=".:/${user.path}" /> container tomcat
<!-- Configure properties to access the Manager application -->
<property name="url"
URL per connettersi
value="http://130.192.241.1:10000/manager"/>
a tomcat durante
<property file="build.properties"/>
<property file="${context.path}/build.properties"/> installazione applicaz
<!-- Configure the custom Ant tasks for the Manager application -->
<path id="classpath">
Carico librerie
<fileset dir="${jwsdp.path}/common/lib">
JWSDP da classpath
<include name="*.jar"/>
</fileset>
</path>
Laboratorio di Servizi Web - servlet Ardissono
38
build.xml - III
<taskdef name="list" classname="org.apache.catalina.ant.ListTask"/>
<taskdef name="install" classname="org.apache.catalina.ant.InstallTask"/>
<taskdef name="reload" classname="org.apache.catalina.ant.ReloadTask"/>
<taskdef name="remove"
Definizione task
classname="org.apache.catalina.ant.RemoveTask"/>
di ant di base
<!-- per usare xjc dentro la build: JAXB -->
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask"/>
<target name="clean">
Task di invocazione
<delete dir="${deployed.application.path}"/> di codice esterno (jaxb)
<delete dir="${deployed.JAXBClasses.path}"/>
</target>
Rimozione directory
applicaz in area
di deployment
Laboratorio di Servizi Web - servlet Ardissono
39
build.xml - IV
<target name="prepare" depends="init"
description="Create build directories.">
<mkdir dir="${deployed.application.path}" />
<mkdir dir="${deployed.JAXBClasses.path}" />
</target>
Creazione
directory di
build: richiama
init task...
init
prepare
<!-- Executable Targets -->
<target name="list" description="List web applications" >
<list url="${url}" username="${username}"
password="${password}" />
</target>
ant install ...
<target name="install” description="Install web application"
depends="build">
<install url="${url}" username="${username}"
password="${password}"
build
path="${path}" war="file:${context.path}"/>
</target>
Laboratorio di Servizi Web - servlet Ardissono
install
40
build.xml - V
….
<target name="remove" description="Remove web application">
<remove url="${url}" username="${username}”
Ant remove ...
password="${password}"
path="${path}"/>
</target>
Laboratorio di Servizi Web - servlet Ardissono
41
build.xml - VI
<target name="build" depends="clean, prepare, bindXMLSchema"
description="Compile app Java files and copy HTML and JSP pages" >
<javac srcdir="${user.path}/src"
destdir="${WEB-INF.path}/classes"
Clean
debug="on"
classpath="${classpath}:${myPath}:">
<include name="**/*.java" />
</javac>
Prepare
<!-- copio i file di properties etc. delle classi JAXB -->
<copy todir="${deployed.JAXBClasses.path}">
<fileset dir="${XSD.path}/coffee1">
</fileset>
bindXMLSchema
</copy>
<copy todir="${WEB-INF.path}">
<fileset dir="${user.path}/src">
build
</fileset>
</copy>
</target>
Laboratorio di Servizi Web - servlet Ardissono
42
build.xml - VII
<!-- per usare xjc dentro la build: JAXB -->
<target name="bindXMLSchema"
description="Expand all XML schema files and place generated
classes in SOURCE package" >
Invoca xjc per generare
<xjc target="${XSD.path}"
classi da XML schema
package="coffee1">
<schema dir="${XSD.path}" includes="*.xsd" />
</xjc>
</target>
</project>
Laboratorio di Servizi Web - servlet Ardissono
43