Servlet
Una Servlet è un piccolo programma in java che viene eseguito in un Web
Server. Le Servlet ricevono e rispondono alle richieste dei Web Clients
(Browsers), di solito attraverso HTTP (Hyper Text Transfer Protocol).
Le Servlet sono il cuore di ogni applicazione web, l’unica classe che svolge il
lavoro di rispondere alle richieste o delegare il lavoro a qualche altra parte
dell’applicazione.
Le Servlet gestiscono le JSP, la visualizzazione di elenchi di directory (se
abilitati) e l’accesso a risorse statiche, come pagine HTML.
javax.servlet.http.HttpServlet
Metodi
recupera la risorsa allo specifico URL
- GET: tipicamente utilizzato per l'invio di moduli web
- POST: identico a GET, tranne che vengono accettate solo le intestazioni
- HEAD:
(headers)
- PUT
- DELETE
- OPTIONS
- TRACE
Init
Init viene chiamato dopo che la servlet è stata costruita ma prima di poter
rispondere alla prima richiesta.
A differenza di quando viene chiamato il costruttore, quando viene chiamato
init tutte le proprietà sono state impostate sulla Servlet, dando accesso agli
oggetti ServletConfig e javax.servlet.ServletContext.
So, you may use this method to read a properties file or connect to a
database using JDBC, for example.
Destroy
Allo stesso modo, destroy viene chiamato immediatamente dopo che il
Servlet non può più accettare alcuna richiesta. Ciò si verifica in genere
quando l'applicazione Web viene arrestata o scaricata o quando il Web
Container si spegne.
Dovresti sempre utilizzare il metodo destroy per ripulire le risorse detenute
dal tuo servlet tra le richieste.
Mapping the Servlet to a URL
Web.xml
<servlet> <servlet-name>Esempio</servlet-name> // istanza servlet
<servlet-class>com.EsemioServlet</servlet-class> // percorso
</servlet>
<servlet-mapping>
<servlet-name>Esempio</servlet-name>
<url-pattern>/test</url-pattern>
</servlet-mapping>
Perché non puoi mappare l'URL direttamente alla classe Servlet? Bene, cosa
succede se hai due diversi Servlet del negozio in un'applicazione per lo
shopping online, ad esempio? Tali archivi potrebbero avere una logica
identica ma connettersi a database diversi. Ciò può essere ottenuto
semplicemente:
<servlet>
<servlet-name> oddsStore </servlet-name>
<servlet-class> com.wrox.StoreServlet </servlet-class>
</servlet>
<servlet>
<servlet-name> endsStore </servlet-name>
<servlet-class> com.wrox.StoreServlet </servlet-class>
</servlet>
<servlet-mapping>
<servlet-name> oddsStore </servlet-name>
<url-pattern> / odds </url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name> endsStore </servlet-name>
<url-pattern> / ends </url-pattern>
</servlet-mapping>
Ora hai due istanze della stessa classe Servlet, ma hanno nomi diversi e
sono mappate su URL diversi. In questo esempio hai due diverse istanze di
Servlet. Potresti chiederti come le due diverse istanze sappiano quali negozi
sono. Una rapida chiamata a this.getServletName () da qualsiasi punto del
codice servlet restituisce "oddsStore" o "endsStore "a seconda dell'istanza.
HttpServletRequest
L’interfaccia HttpServletRequest è un’estensione di ServletRequest che
fornisce ulteriori specifiche informazioni riguardanti la richiesta HTTP
ricevuta. Implementa dozzine di metodi che possono essere usati per
ottenere dettagli riguardanti la richiesta HTTP. Permette inoltre di impostare
attributi nella richiesta.
Request Parameters
La più importante capacità dell’HttpServletRequest è quella di recuperare i
parametri della richiesta inviati dal client.
I parametri della richiesta arrivano in due diverse modalità: attraverso
l’intestazione (parametri query) o nel corpo della richiesta (form).
1. GET /index.jsp?productId=9781118656464&category=Books HTTP/1.1
2. POST /index.jsp?returnTo=productPage HTTP/1.1
Host: www.example.com Content-Length: 48 Content-Type:
application/x-www-form-urlencoded
addToCart&productId=9781118656464&category=Books
Metodi ritorna l’intero URL che il client ha usato per fare la
getRequestURL:
richiesta, incluso il protocollo (http o https), il nome del server, il numero della
porta, e il server path ma senza includere la query string.
Quindi, nella richiesta http://www.example.org/application/index .jsp?
category=Books,
getRequestURL ritorna http://www.example.org/application/index.jsp.
questo è leggermente differente da getRequestURL, in
getRequestURI:
questo viene restituito solo il server path del URL; usando l’esempio
precedente, il risultato sarebbe /application/index.jsp.
Similar to getRequestURI, this returns even less of the
getServletPath:
URL. If the request is /hello-world/greeting?foo=world, the application is
deployed as /hello-world on Tomcat, and the servlet-mappings are
/greeting, /salutation,and /wazzup, getServletPath returns only the part of the
URL used to match the servlet mapping: /greeting.
Returns the value of a header with the given name. The case
getHeader:
of the header does not have to match the case of the string passed into the
" "
method, so getHeader( content- type ) can match the Content-Type header.
If there are multiple headers with the same name, this returns only the first
value. In such cases, you would want to use the method to
getHeaders
return an enumeration of all the values.
Returns an enumeration of the names of all the
getHeaderNames:
headers in the request — a great way to iterate over the available headers.
If you have a particular header that you know is always a
getIntHeader:
number, you can call this to return the value already converted to a number. It
throws a NumberFormatException if the header cannot be converted to an
integer. You can call this to return the (millisecond) Unix
getDateHeader:
timestamp- equivalent of a header value that represents a valid timestamp. It
throws an IllegalArgumentException if the header value is not recognized as
a date.
HttpServletResponse
L’interfaccia HttpServletResponse estende ServletResponse e fornisce
l'accesso alle proprietà specifiche del protocollo HTTP di una risposta.
L'oggetto risposta viene utilizzato per eseguire operazioni quali :
- impostare le intestazioni della risposta,
- scrivere nel corpo della risposta,
- reindirizzare la richiesta,
- impostare il codice di stato HTTP e
- inviare i cookie al client.
Scrivere nel corpo della risposta
Il metodo getOutputStream, che ritorna un javax.servlet.ServletOutputStream,
e il metodo getWriter, che ritorna un java.io.PrintWriter, permettono entrambi
di scrivere nella risposta.
Impostare le intestazioni della risposta
Fungendo da controparti ai metodi in HttpServletRequest, puoi chiamare
e per impostare quasi tutti
setHeader, setIntHeader setDateHeader
i valori di intestazione desiderati. Se le intestazioni di risposta esistenti
includono già un'intestazione con il nome che stai impostando, il valore di tale
intestazione verrà sovrascritto. Per evitare ciò, puoi invece usare
o Queste versioni non
addHeader, addIntHeader, addDateHeader.
sovrascrivono i valori di intestazione esistenti, ma invece
aggiungere valori aggiuntivi per le intestazioni fornite. Puoi anche chiamare
e
getHeader, getHeaders getHeaderNames containsHeader
per esaminare quali intestazioni sono già state impostate nella risposta.
Inoltre puoi usare:
per impostare il codice di stato della risposta HTTP
setStatus: per determinare qual è lo stato corrente della risposta
getStatus: per impostare il codice di stato, indicare un messaggio di errore
sendError:
opzionale da scrivere nei dati di risposta, indirizzare il web container per
fornire una pagina di errore al client e cancellare il buffer
per reindirizzare il client a un URL diverso
sendRedirect:
Servlet Context Init Parameters
Per dichiarare parametri di inizializzazione si utilizza il tag <context-param>
nel file web.xml.
<context-param>
<param-name>var</param-name>
<param-value>one</param-value>
</context-param>
Ogni servlet nell’applicazione condivide questi parametri di inizializzazione e i
loro valori sono gli stessi in tutti le servlet. Potrebbero tuttavia verificarsi casi
in cui è necessaria un'impostazione che si applica a una sola Servlet. A
questo scopo usereste i parametri di inizializzazione di Servlet.
Servlet Config Init Parameters
Il tag <init-param> crea un parametro di inizializzazione specifico per una
Servlet.
<servlet>
<servlet-name>servletParameterServlet</servlet-name>
<servlet-class>com.wrox.ServletParameterServlet</servlet-class>
<init-param>
<param-name>database</param-name>
<param-value>CustomerSupport</param-value>
</init-param>
<init-param>
<param-name>server</param-name>
<param-value>10.0.12.5</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servletParameterServlet</servlet-name>
<url-pattern>/servletParameters</url-pattern>
</servlet-mapping>
Gli svantaggi del Config
Come accennato in precedenza, ci sono vantaggi e svantaggi nell'usare la
configurazione basata sull'annotazione (spesso chiamata semplicemente
@Config) in un’applicazione web. Il vantaggio principale è la mancanza di
XML e il linguaggio di annotazione diretto e conciso utilizzato per configurare
l'applicazione. Tuttavia, ci sono anche numerosi inconvenienti in questo
approccio.
Un esempio di ciò è l'incapacità di creare più istanze di una singola classe
Servlet. Hai visto in precedenza nel capitolo come potrebbe essere usato un
tale schema*. Ciò è impossibile utilizzando le annotazioni e può essere
ottenuto solo utilizzando la configurazione XML o la configurazione Java
programmatic.
Nel Capitolo 9, imparerai a conoscere i filtri e perché è importante costruire
attentamente l'ordine in cui vengono eseguiti i filtri. Puoi fare in modo che i
filtri vengano eseguiti in un ordine specifico quando li dichiari utilizzando la
configurazione XML o la configurazione Java programmatic. Se dichiari i tuoi
filtri usando @ javax.servlet.annotation.WebFilter, tuttavia, è impossibile farli
eseguire in un ordine specifico (qualcosa che molti ritengono sia una svista
lampante nelle specifiche Servlet 3.0 e 3.1). A meno che la tua applicazione
non abbia un solo filtro, @WebFilter è praticamente inutile.
Ci sono molte cose più piccole che richiedono ancora il descrittore di
distribuzione XML
per eseguire, come la definizione di pagine di gestione degli errori, la
configurazione delle impostazioni JSP e la fornitura di un elenco di pagine di
benvenuto. Per fortuna, puoi combinare XML, annotazioni e Java
programmatic e configurazione, in modo da poterli utilizzare quando è più
conveniente. In questo libro, utilizzi tutte e tre le tecniche.
*
<servlet>
<servlet-name>oddsStore</servlet-name>
<servlet-class>com.wrox.StoreServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>endsStore</servlet-name>
<servlet-class>com.wrox.StoreServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>oddsStore</servlet-name>
<url-pattern>/odds</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>endsStore</servlet-name>
<url-pattern>/ends</url-pattern>
</servlet-mapping>
Now you have two instances of the same Servlet class, but they have
different names and are mapped to different URLs. Two examples ago, you
had three URLs all pointing to the same Servlet instance. However, in this
example you have two different Servlet instances. You might wonder how the
two different instances know which stores they are. A quick call to
this.getServletName() from anywhere in the servlet code returns either
“oddsStore” or “endsStore” depending on which instance it is.
Multithreading
Ogni Web Container è, ovviamente, leggermente differente. Ma nel mondo
Java EE, generalmente parlando, un web container contiene alcuni tipi di
thread pool, possibilmente chiamati connector pool (o executor pool).
Quando il container riceve una richiesta, cerca un thread disponibile nella
pool. Se nessun thread è disponibile e la tread pool ha già raggiunto la sua
taglia massima, la richiesta entra in una coda -fifo- in attesa di un thread
disponibile.
Una volta che un thread è disponibile, il contenitore prende in prestito il
thread dal pool e passa la richiesta affinché venga gestita dal thread. A
questo punto, il thread non è più disponibile per altre richieste in arrivo. In una
richiesta normale, il thread e la request saranno collegati per tutta la durata
della richiesta. Finché la richiesta viene elaborata dal codice, quel thread sarà
dedicato alla richiesta. Solo quando la richiesta è stata completata e il
contenuto della risposta è inviato al client, il thread sarà libero dalla richiesta
e tornerà al pool per soddisfare un'altra richiesta.
La thread pool ha una taglia configurabile che determina quante connessioni
può servire alla volta.
Proteggere le risorse condivise
- volatile
- synchronized
Da usare con variabili di istanza.
private volatile int TICKET_ID_SEQUENCE = 1;
synchronized(this) {
id = this.TICKET_ID_SEQUENCE++;
this.ticketDatabase.put(id, ticket);
}
La parola chiave volatile viene utilizzata per contrassegnare una variabile
Java come "archiviata nella memoria principale". Più precisamente questo
significa che ogni lettura di una variabile volatile verrà fatta dalla memoria
principale del computer, e non dalla cache della CPU, e che ogni scrittura su
una variabile volatile verrà fatta nella memoria principale, e non solo nella
cache della CPU.
La parola chiave "synchronized" è ampiamente utilizzata per ottenere
l'esclusione reciproca tra i thread. Ciò significa che utilizzando synchronized
abbiamo la possibilità di limitare l'accesso di un particolare blocco di codice o
di un metodo a un solo thread per volta.
Uno stesso client (browser) può avere più richieste con lo stesso ID
NOTE:
di sessione all’applicazione web (per esempio due finestre aperte sulla stessa
pagina con lo stesso token di sessione oppure più browser aperti sulla stessa
pagina con lo stesso token di sessione) per questo l’attributo session
non è Thread Safe.
E’ necessario inserire l’istanza di sessione in un blocco synchronized.
JSP
Sono una tipologia di servlet.
Codice HTML + codice java
In aggiunta ai vari HTML e tag JSP una JSP contiene alcune uniche strutture
che definiscono una sorta di linguaggio JSP.
Sono:
- direttive
- dichiarazioni
- scriptlets
- espressioni
Rispettivamente:
<%@ this is a directive %>
<%! This is a declaration %>
<% this is a scriptlet %>
<%= this is an expression %>
Direttive
Le direttive vengono utilizzate per indicare all'interprete JSP di eseguire
un'azione (come l'impostazione del tipo di contenuto) o fare un'ipotesi sul file
(come il linguaggio di scripting che utilizza), per importare una classe, per
includere qualche altro JSP al momento della traduzione o per includere una
libreria di tag JSP.
Dichiarazioni
Si utilizzano le dichiarazioni per dichiarare qualcosa nell'ambito della propria
classe JSP Servlet. Ad esempio, è possibile definire variabili di istanza,
metodi o classi all'interno di un tag di dichiarazione. È necessario ricordare
che queste dichiarazioni sono tutte effettuate all'interno della classe JSP
Servlet generata, quindi tutte le classi definite sono in realtà classi interne
della classe JSP Servlet.
Scriptlet
Come una dichiarazione, anche uno scriptlet contiene codice Java. Tuttavia,
gli scriptlet hanno un ambito diverso. Sebbene il codice all'interno di una
dichiarazione venga copiato nel corpo della classe JSP Servlet al momento
della traduzione e debba quindi essere utilizzato per dichiarare un campo, un
tipo o un metodo, gli scriptlet vengono copiati nel corpo del metodo
_jspService esaminato in precedenza. Qualsiasi variabile locale che si trova
nell'ambito dell'esecuzione di questo metodo sarà nell'ambito degli scriptlet e
qualsiasi codice che sia legale all'interno del corpo di un metodo è legale
all'interno di uno scriptlet. Quindi, puoi definire variabili locali, ma non campi
di istanza. Puoi usare istruzioni condizionali, manipolare oggetti ed eseguire
operazioni aritmetiche, tutte cose che non puoi fare all'interno di una
dichiarazione. È anche possibile definire classi (per quanto strano possa
sembrare, ma in Java è legale avere definizioni di classe all'interno di un
metodo), ma le classi non hanno ambito al di fuori del metodo _jspService.
Una classe, un metodo o una variabile definita all'interno di una dichiarazione
può essere utilizzata all'interno di uno scriptlet, ma una classe o una variabile
definita all'interno di uno scriptlet non può essere utilizzata all'interno di una
dichiarazione.
Espressioni
Le espressioni contengono un semplice codice Java che restituisce qualcosa
che può essere scritto nell'output del client e le espressioni restituiscono la
va
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.