View Full Version : Variabili di una JSP
Sto leggendo una guida alle JSP e non capisco molto una cosa.
Vengono dichiarate delle variabili come:
<%!
String nome;
%>
Alle quali viene assegnato un valore passato da URL:
<%
nome = request.getParameter("nome");
%>
La guida spiega che questo codice potrebbe avere problemi se la JSP venisse chiamata contemporaneamente da più utenti..
Sinceramente non capisco, la JSP viene trasformata in una classe.. due richieste della stessa servlet non generano quindi due oggetti diversi? e visto che ho guardato il codice della servlet e queste variabili non sono "static", come può essere che vengano "condivise" da più istanze della stessa Servlet?
Grazie
T'ho trovato! Avevo letto la domanda e poi m'è sparito da sotto le dita il thread in un amen. Eddovevai!
E' vero che ogni JSP definisce una servlet ma non è vero che due richieste alla stessa servlet siano affidate a due istanze diverse dell'unica classe servlet prodotta.
"non è vero" va letto come "non è richiesto dalle specifiche Servlet". Se non è richiesto, ecco quello che il web application server è autorizzato a fare.
A Qualcuno richiede il servizio associato alla servlet Pippo.
B Se non esiste un'istanza di Pippo, il contenitore la crea (p)
C il contenitore affida ai metodi di servizio di quell'istanza la richiesta
Arriva un'altra richiesta:
il contenitore affida al metodo di servizio di p, istanza di Pippo prima creata, la richiesta.
E se ne arrivano due in contemporanea. Be', non c'è problema, basta che il server crei per ogni richiesta un thread e lasci che sia quel thread ad eseguire il metodo di servizio di p, unica istanza di Pippo.
Più richieste sono o, meglio, possono essere, più thread che eseguono tutte lo stesso metodo dello stesso oggetto di tipo servlet, unica istanza dell'unica classe Servlet prodotta a partire da quella pagina JSP.
I problemi che sorgono sono quelli derivanti dall'accesso concorrente ad una stessa variabile. A dirla tutta, il codice che hai incollato non ha problemi in sè: l'unico effetto bizzarro che potrebbe verificarsi, stando al modello di memoria del linguaggio di programmazione Java, è che il campo nome non abbia mai altro valore che null, nonostante una ridda di invocazioni al metodo di servizio della servlet. La ragione per cui accade è che manca una relazione happens-before tra la scrittura di un valore in un metodo non sincronizzato ed un eventuale ulteriore lettura di quel valore mentre c'è un happens-before tra l'inizializzazione al valore predefinito di un campo e successive letture del valore di quel campo.
Dunque nome è sempre null (in un contesto concorrente consideri il caso pessimo). Anche se fosse diverso da null, il suo valore potrebbe essere uno qualsiasi dei valori assunti da quella variabile man mano che i vari thread masticano il metodo di servizio, che eseguirà:
nome = request.getParameter("nome");
Io scrivo "Gianni", premo "invia" e la servlet è più che autorizzata a salutarmi con un bel:
"Ciao null!!!" o "Ciao Mario"
se "Mario" è il nome inviato da un altro utente la cui richiesta sia gestita dalla stessa servlet. E' anche possibile che mi risponda "Ciao Gianni" ed è persino possibile che lo faccia sempre...ma solo se hai molto :ciapet:
L'unica garanzia che comunque conservi è che il riferimento nome sarà sempre integro (cioè non punta ad un indirizzo inquinato dall'accavallarsi due scritture concorrenti). Il che, pur non essendo poco, non serve a molto.
T'ho trovato! Avevo letto la domanda e poi m'è sparito da sotto le dita il thread in un amen. Eddovevai!
E' vero che ogni JSP definisce una servlet ma non è vero che due richieste alla stessa servlet siano affidate a due istanze diverse dell'unica classe servlet prodotta.
Grazie con la risposta, effettivamnete ero partito col pressuposto sbagliato che ogni richiesta di una pagina portasse a una creazione di un nuovo oggetto della servlet che gestisce quella pagina, invece considerando problemi di occupazione di memoria per server ultra-stressati, è perfettamente logico che venga mantenuto vivo un solo oggetto della servlet.
Mi domando però, che utilità possono avere questi attributi (non statici) della classe (estesa da Servlet)?
In pratica non possono nè contenere dati relativi a una singola richiesta, visto che potrebbero essere sovrascritti da richieste contemporanee..
E neppure possono contenere ciò che invece contengono i tipici attributi statici, visto che se ad esempio volessi tener conto di quante richieste ci sono in un certo istante di una servlet dovrei usare un attributo static..
Insomma. vorrei capire in che contesto una variabile di questo tipo può avere un'utilità
grazie.
Supponendo che l'inizializzazione del campo sia thread-safe, cioè che esso possieda un valore iniziale diverso da null leggibile da ogni altro thread che acceda a quel campo, credo che un uso generale ammissibile esista in tutti i casi in cui si debba disporre di un ponte d'accesso ad una risorsa esterna o che il valore conservato nel campo sia in sola lettura. Il caso del contatore è emblematico. Se come contatore usi un campo di istanza allora presupponi che esista una sola istanza della classe Servlet.
Immagino che valga la pena chiarire questa faccenda delle istanze. Le specifiche Servlet 2.4 autorizzano tre situazioni (SRV2.2).
La prima è che esista una sola istanza di una certa classe Servlet e che quell'istanza deve essere l'unica usata dal contenitore per consumare le richieste dei client.
Se la classe servlet è marcata SingleThreadModel (che non si dovrebbe più usare) allora il contenitore può creare più istanze. Può ma non deve. Ciò che deve garantire è che un solo Thread alla volta esegua i metodi di servizio della servlet.
Nel caso di applicazione distribuita la cosa si fa anche più complicata. Qui il contenitore è autorizzato ad avere una sola istanza della classe Servlet ma una sola per ogni JVM usata per la distribuzione dei compiti. La cosa è più complicata perchè in presenza di più JVM e, quindi, di più ClassLoader, i campi statici non sono più univoci.
Da ciò si ricava che:
1. se l'applicazione non è distribuita e la servlet non è SingleThreadModel allora il contenitore web esegue ogni richiesta del client ad un indirizzo associato ad un tipo di servlet attraverso una sola istanza di quella classe servlet (puoi usare un campo di istanza come contatore avendo cura di sincronizzare l'accesso in lettura e scrittura al campo del contatore che mantiene il numero di contatti)
2. se l'applicazione non è distribuita e la servlet è SingleThreadModel allora il contenitore web può usare più istanze della classe servlet ma garantisce che un solo thread alla volta soddisfi le richieste tramite i metodi di servizio delle diverse istanze della servlet (puoi usare un campo statico come contatore senza necessità di sincronizzare la lettura e la scrittura). SingleThreadModel è deprecato.
3. se l'applicazione è distribuita, cioè diverse JVM possono farsi carico dell'esecuzione di uno stesso compito, il contenitore usa a conti fatti diverse istanza della servlet e NON puoi contare neppure sull'unicità dei membri statici.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.