2. I fondamenti della programmazione web
Lo scopo principale di questo capitolo è quello di introdurre i principi chiave della programmazione web, che sono indipendenti dalla tecnologia specifica utilizzata per implementarli. Presenta numerosi esempi che vi invitiamo a provare per “assorbire” gradualmente la filosofia dello sviluppo web. I lettori che possiedono già queste conoscenze possono passare direttamente al Capitolo 3.
I componenti di un'applicazione web sono i seguenti:

Numero | Ruolo | Esempi comuni |
1 | Sistema operativo server | Unix, Linux, Windows |
2 | Server Web | Apache (Unix, Linux, Windows) IIS (Windows + piattaforma .NET) Node.js (Unix, Linux, Windows) |
3 | Codice lato server. Può essere eseguito da moduli del server o da programmi esterni al server (CGI). | JAVASCRIPT (Node.js) PHP (Apache, IIS) JAVA (Tomcat, WebSphere, JBoss, WebLogic, ...) C#, VB.NET (IIS) |
4 | Database - Può trovarsi sulla stessa macchina del programma che lo utilizza o su un'altra macchina tramite Internet. | Oracle (Linux, Windows) MySQL (Linux, Windows) Postgres (Linux, Windows) SQL Server (Windows) |
5 | Sistema operativo client | Unix, Linux, Windows |
6 | Browser Web | Chrome, Internet Explorer, Firefox, Opera, Safari, ... |
7 | Script lato client eseguiti all'interno del browser. Questi script non hanno accesso al disco del computer client. | JavaScript (tutti i browser) |
2.1. Scambio di dati in un'applicazione web con un modulo

Numero | Ruolo |
1 | Il browser richiede un URL per la prima volta (http://machine/url). Non vengono passati parametri. |
2 | Il server web invia la pagina web corrispondente a quell'URL. Può essere statica o generata dinamicamente da uno script lato server (SA) che potrebbe aver utilizzato contenuti provenienti da database (SB, SC). In questo caso, lo script rileverà che l'URL è stato richiesto senza alcun parametro e genererà la pagina web iniziale. Il browser riceve la pagina e la visualizza (CA). Gli script lato browser (CB) potrebbero aver modificato la pagina iniziale inviata dal server. Quindi, attraverso le interazioni tra l'utente (CD) e gli script (CB), la pagina web verrà modificata. In particolare, verranno compilati i moduli. |
3 | L'utente invia i dati del modulo, che devono quindi essere inviati al server web. Il browser richiede l'URL iniziale o un altro, a seconda dei casi, e contemporaneamente trasmette i valori del modulo al server. A tal fine può utilizzare due metodi: GET e POST. Una volta ricevuta la richiesta del client, il server attiva lo script (SA) associato all'URL richiesto, che rileverà i parametri e li elaborerà. |
4 | Il server fornisce la pagina web generata dal programma (SA, SB, SC). Questo passaggio è identico al precedente passaggio 2. La comunicazione procede ora secondo i passaggi 2 e 3. |
2.2. Pagine web statiche, pagine web dinamiche
Una pagina statica è rappresentata da un file HTML. Una pagina dinamica è una pagina HTML generata "al volo" dal server web.
2.2.1. Pagina HTML (HyperText Markup Language) statica
Creiamo il nostro primo progetto Spring MVC [1-2]:
![]() |
- In [1-2], creiamo un nuovo progetto basato su Spring Boot [http://projects.spring.io/spring-boot/];
![]() |
- le informazioni [3-7] riguardano la configurazione Maven del progetto;
- in [3], il nome del progetto Maven;
- in [4], il gruppo Maven in cui verrà collocato l'output della compilazione del progetto;
- in [5], il nome assegnato all'output della compilazione;
- in [6], una descrizione del progetto;
- in [7], il pacchetto in cui verrà collocata la classe eseguibile del progetto;
- in [8], la natura del progetto. Si tratta di un progetto web con viste Thymeleaf. Qui vediamo tutte le dipendenze Maven pronte all'uso fornite dal progetto Spring Boot;
- in [9], specifichiamo che l'output della build Maven sarà impacchettato in un archivio JAR anziché in un WAR. Il progetto utilizzerà quindi un server Tomcat incorporato, che sarà incluso nelle sue dipendenze;
- in [10], si procede al passo successivo della procedura guidata;
![]() |
- in [11], specifichiamo la directory del progetto;
- in [12], completiamo la procedura guidata;
- In [13], il progetto generato.
Esaminiamo il file [pom.xml] generato:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.springmvc</groupId>
<artifactId>intro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springmvc-intro</name>
<description>Les bases de la programmation web</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.1.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>istia.st.springmvc.Application</start-class>
<java.version>1.7</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Include tutte le informazioni fornite nella procedura guidata. Alle righe 26–30, troviamo una dipendenza di cui non eravamo a conoscenza. Consente l'integrazione dei test unitari JUnit con Spring.
Iniziamo creando una pagina HTML statica in questo progetto. Per impostazione predefinita, dovrebbe essere collocata nella cartella [src/main/resources/static]:
![]() |
- In [1-4], creare un file HTML nella cartella [static];
![]() |
- in [6], assegnare un nome alla pagina;
- in [7], la pagina è stata aggiunta.
Il contenuto della pagina creata è il seguente:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
- righe 2-10: il codice è delimitato dal tag radice <html>;
- righe 3-6: il tag <head> delimita ciò che viene chiamato l'intestazione della pagina;
- righe 7-9: il tag <body> delimita ciò che viene chiamato corpo della pagina.
Modifichiamo questo codice come segue:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>essai 1 : une page statique</title>
</head>
<body>
<h1>Une page statique...</h1>
</body>
</html>
- riga 5: definisce il titolo della pagina – verrà visualizzato come titolo della finestra del browser che mostra la pagina;
- riga 8: testo in caratteri grandi (<h1>).
Eseguiamo l'applicazione [1-3]:
![]() |
quindi, utilizzando un browser, richiediamo l'URL [http://localhost:8080/exemple-01.html]:
![]() |
- in [1], l'URL della pagina visualizzata;
- in [2], il titolo della finestra – fornito dal tag <title> della pagina;
- in [3], il corpo della pagina – fornito dal tag <h1>.
Diamo un'occhiata a [4-5], il codice HTML ricevuto dal browser:
![]() |
- In [5], il browser ha ricevuto la pagina HTML che avevamo creato. L'ha interpretata e l'ha visualizzata come immagine.
2.2.2. Una pagina Thymeleaf dinamica
Ora creiamo una pagina Thymeleaf. Si tratta di una pagina HTML standard con tag arricchiti da attributi [Thymeleaf] [http://www.thymeleaf.org/]. Seguiamo un processo simile a quello della creazione della pagina HTML, ma questa volta la nuova pagina HTML deve essere collocata nella cartella [templates]:
![]() |
La pagina [example-02.html] avrà questo aspetto:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>spring mvc intro</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Il est ' + ${heure}">Voici l'heure</p>
</body>
</html>
- riga 8: il tag <p> è un tag HTML che introduce un paragrafo nella pagina visualizzata. [th:text] è un attributo [Thymeleaf] che ha due scopi diversi a seconda che [Thymeleaf] sia attivo o meno:
- se [Thymeleaf] non analizza la pagina HTML, l'attributo [th:text] verrà ignorato perché sconosciuto in HTML. Il testo visualizzato sarà quindi [Ecco l'ora],
- se [Thymeleaf] analizza la pagina HTML, l'attributo [th:text] verrà valutato e il suo valore sostituirà il testo [Ecco l'ora]. Il suo valore sarà qualcosa del tipo [Sono le 17:11:06];
Vediamo come funziona. Duplicheremo la pagina [templates/example-02.html] nella cartella [static]. Le pagine HTML inserite in questa cartella non vengono interpretate da [Thymeleaf]:
![]() | ![]() | ![]() |
Eseguiamo l'applicazione come abbiamo già fatto diverse volte in precedenza, quindi richiediamo l'URL [http://localhost:8080/exemple-02.html] in un browser:
![]() |
In [1] vediamo che l'attributo [th:text] non è stato interpretato e non ha causato alcun errore. Il codice sorgente della pagina visualizzato in [2] mostra che il browser ha ricevuto correttamente la pagina completa.
Torniamo alla pagina [example-02.html] nella cartella [templates]:
![]() |
Le pagine HTML inserite nella cartella [templates] vengono elaborate da [Thymeleaf]. Torniamo al codice della pagina:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>spring mvc intro</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'Il est ' + ${heure}">Voici l'heure</p>
</body>
</html>
- riga 7: [Thymeleaf] interpreterà l'attributo [th:text] e sostituirà [Ecco l'ora] con il valore dell'espressione:
Questa espressione utilizza la variabile [${time}], dove [time] appartiene al modello di vista [example-02.html]. Dobbiamo quindi creare questo modello. Per farlo, seguiremo l'esempio discusso nella sezione 1.6. Aggiorniamo il progetto come segue:
![]() |
In [1], aggiungiamo il seguente controller:
package istia.st.springmvc;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class MyController {
@RequestMapping("/")
public String heure(Model model) {
// time format
SimpleDateFormat formater = new SimpleDateFormat("HH:MM:ss");
// the hour of the moment
String heure = formater.format(new Date());
// set the time in the view model
model.addAttribute("heure", heure);
// display the [exemple-02.html] view
return "exemple-02";
}
}
- righe 13-14: il metodo [time] gestisce l'URL [/];
- riga 14: [Model model] è un modello vuoto. L'azione [time] deve popolarlo con gli attributi che vuole vedere nel modello. Sappiamo che la vista [example-02.html] si aspetta un attributo chiamato [time];
- righe 19-22: implementiamo ciò che abbiamo appena spiegato. La vista [example-02.html] verrà visualizzata (riga 22) con un attributo denominato [time] nel suo modello (riga 20);
- riga 16: viene creato un formattatore di data. Il formato [HH:MM:ss] utilizzato è un formato [ore:minuti:secondi] in cui le ore sono comprese nell'intervallo [0-24];
- riga 18: utilizzando questo formattatore, formattiamo la data odierna;
- riga 20: l'ora risultante viene assegnata a un attributo denominato [time];
Avviamo l'applicazione e richiediamo l'URL [/]:
![]() |
- [1] mostra la pagina risultante e [2] il suo contenuto HTML. Possiamo notare che il testo iniziale [Here is the time] è completamente scomparso;
Se ora aggiorniamo la pagina [1] (F5), otteniamo una visualizzazione diversa (nuova ora) anche se l'URL non cambia. Questo è l'aspetto dinamico della pagina: il suo contenuto può cambiare nel tempo.
Da quanto sopra, possiamo notare la natura fondamentalmente diversa delle pagine dinamiche e statiche.
2.2.3. Configurazione dell'applicazione Spring Boot
Torniamo all'architettura del progetto Eclipse:
![]() |
Il file [application.properties] viene utilizzato per configurare l'applicazione Spring Boot. Per ora, questo file è vuoto. Può essere utilizzato per configurare l'applicazione in vari modi, come descritto all'URL [http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html]. Useremo il seguente file [application.properties] [2]:
- Riga 1: imposta la porta di servizio dell'applicazione web;
- riga 2: imposta il contesto dell'applicazione web;
Con questa configurazione, la pagina statica [example-01.html] sarà accessibile all'URL [http://localhost:9000/intro/exemple-01.html]:
![]() |
2.3. Script lato browser
Una pagina HTML può contenere script che verranno eseguiti dal browser. Il principale linguaggio di scripting lato browser è attualmente (gennaio 2015) JavaScript. Sono state create centinaia di librerie utilizzando questo linguaggio per semplificare il lavoro degli sviluppatori.
Creiamo una nuova pagina [example-03.html] nella cartella [static] del progetto esistente:
![]() |
Modifica il file [example-03.html] inserendo il seguente contenuto:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>exemple Javascript</title>
<script type="text/javascript">
function réagir() {
alert("Vous avez cliqué sur le bouton !");
}
</script>
</head>
<body>
<input type="button" value="Cliquez-moi" onclick="réagir()" />
</body>
</html>
- Riga 13: definisce un pulsante (attributo type) con il testo "Cliccami" (attributo value). Quando viene cliccato, viene eseguita la funzione JavaScript [react] (attributo onclick);
- righe 6–10: uno script JavaScript;
- righe 7–9: la funzione [react];
- Riga 8: visualizza una finestra di dialogo con il messaggio [Hai cliccato sul pulsante].
Visualizziamo la pagina in un browser:
![]() |
- in [1], la pagina visualizzata;
- in [2], la finestra di dialogo che appare quando si fa clic sul pulsante.
Quando si fa clic sul pulsante, non avviene alcuna comunicazione con il server. Il codice JavaScript viene eseguito dal browser.
Grazie al vasto numero di librerie JavaScript disponibili, ora possiamo incorporare applicazioni complete direttamente nel browser. Ciò porta alle seguenti architetture:
![]() |
- 1-2: il server HTML è un server per pagine statiche HTML5/CSS/JavaScript;
- 3-4: le pagine HTML5/CSS/JavaScript fornite interagiscono direttamente con il server dati. Il server dati fornisce i dati senza markup HTML. JavaScript inserisce questi dati nelle pagine HTML già presenti nel browser.
In questa architettura, il codice JavaScript può diventare piuttosto complesso. Il nostro obiettivo è quindi quello di strutturarlo in livelli, proprio come facciamo con il codice lato server:
![]() |
- il livello [UI] è quello che interagisce con l'utente;
- il livello [DAO] interagisce con il server dei dati;
- il livello [business] contiene procedure aziendali che non interagiscono né con l'utente né con il server dati. Questo livello potrebbe non esistere.
2.4. Comunicazione client-server
Torniamo al nostro diagramma iniziale che illustra i componenti di un'applicazione web:

Qui ci interessano gli scambi tra la macchina client e la macchina server. Questi avvengono su una rete, e vale la pena rivedere la struttura generale degli scambi tra due macchine remote.
2.4.1. Il modello OSI
Il modello di rete aperto noto come OSI (Open Systems Interconnection Reference Model), definito dall'ISO (International Standards Organization), descrive una rete ideale in cui la comunicazione tra macchine può essere rappresentata da un modello a sette livelli:
![]() |
Ogni livello riceve servizi dal livello sottostante e fornisce i propri servizi al livello sovrastante. Supponiamo che due applicazioni situate su macchine diverse A e B vogliano comunicare: lo fanno a livello di Applicazione. Non hanno bisogno di conoscere tutti i dettagli di come funziona la rete: ogni applicazione passa le informazioni che desidera trasmettere al livello sottostante: il livello di Presentazione. L'applicazione deve quindi conoscere solo le regole di interfaccia con il livello di presentazione. Una volta che le informazioni si trovano nel livello di presentazione, vengono trasmesse secondo altre regole al livello di sessione, e così via, fino a quando le informazioni raggiungono il mezzo fisico e vengono trasmesse fisicamente alla macchina di destinazione. Lì, subiranno il processo inverso di quello che hanno subito sulla macchina di invio.
A ogni livello, il processo mittente responsabile dell'invio delle informazioni le invia a un processo ricevente sull'altra macchina appartenente allo stesso livello. Lo fa secondo determinate regole note come protocollo di livello. Abbiamo quindi il seguente diagramma di comunicazione finale:
![]() |
I ruoli dei diversi livelli sono i seguenti:
Fisico | Garantisce la trasmissione di bit su un mezzo fisico. Questo livello include apparecchiature terminali di elaborazione dati (DPTE) quali terminali o computer, nonché apparecchiature di terminazione del circuito dati (DCTE) quali modulatori/demodulatori, multiplexer e concentratori. Le considerazioni chiave a questo livello sono:
|
Collegamento dati | Nasconde le caratteristiche fisiche del livello fisico. Rileva e corregge gli errori di trasmissione. |
Rete | Gestisce il percorso che le informazioni inviate sulla rete devono seguire. Questo processo è chiamato routing: determinare il percorso che le informazioni devono seguire per raggiungere la loro destinazione. |
Trasporto | Consente la comunicazione tra due applicazioni, mentre i livelli precedenti permettevano solo la comunicazione tra macchine. Un servizio fornito da questo livello può essere il multiplexing: il livello di trasporto può utilizzare una singola connessione di rete (da macchina a macchina) per trasmettere dati appartenenti a più applicazioni. |
Sessione | Questo livello fornisce servizi che consentono a un'applicazione di aprire e mantenere una sessione di lavoro su una macchina remota. |
Presentazione | Ha lo scopo di standardizzare la rappresentazione dei dati tra macchine diverse. Pertanto, i dati provenienti dalla macchina A saranno "formattati" dal livello di Presentazione della macchina A secondo un formato standard prima di essere inviati in rete. Una volta raggiunto il livello di Presentazione della macchina di destinazione B, che li riconoscerà grazie al loro formato standard, saranno formattati in modo diverso in modo che l'applicazione sulla macchina B possa riconoscerli. |
Applicazione | A questo livello si trovano applicazioni che sono generalmente vicine all'utente, come la posta elettronica o il trasferimento di file. |
2.4.2. Il modello TCP/IP
Il modello OSI è un modello ideale. La suite di protocolli TCP/IP lo approssima nel modo seguente:
![]() |
- l'interfaccia di rete (la scheda di rete del computer) svolge le funzioni dei livelli 1 e 2 del modello OSI
- il livello IP (Internet Protocol) svolge le funzioni del livello 3 (rete)
- Il livello TCP (Transmission Control Protocol) o UDP (User Datagram Protocol) svolge le funzioni del livello 4 (trasporto). Il protocollo TCP garantisce che i pacchetti di dati scambiati tra macchine in rete raggiungano la loro destinazione. In caso contrario, invia nuovamente i pacchetti persi. Il protocollo UDP non svolge questo compito, quindi spetta allo sviluppatore dell'applicazione farlo. Questo è il motivo per cui, su Internet — che non è una ret e al 100% — il protocollo TCP è il più utilizzato. Si parla in questo caso di rete TCP-IP.
- Il livello Applicazione comprende le funzioni dei livelli da 5 a 7 del modello OSI.
Le applicazioni web risiedono nel livello Applicazione e quindi si basano sui protocolli TCP/IP. I livelli Applicazione delle macchine client e server si scambiano messaggi, che vengono affidati ai livelli da 1 a 4 del modello per essere instradati alla loro destinazione. Per comunicare tra loro, i livelli Applicazione di entrambe le macchine devono "parlare" la stessa lingua o lo stesso protocollo. Il protocollo utilizzato dalle applicazioni Web si chiama HTTP (HyperText Transfer Protocol). Si tratta di un protocollo basato su testo, il che significa che le macchine scambiano righe di testo attraverso la rete per comunicare. Questi scambi sono standardizzati, il che significa che il client dispone di una serie di messaggi per comunicare al server esattamente ciò che desidera, e anche il server dispone di una serie di messaggi per fornire al client la propria risposta. Questo scambio di messaggi assume la seguente forma:

Client --> Server
Quando il client effettua una richiesta al server web, invia
- righe di testo in formato HTTP per indicare ciò che desidera;
- una riga vuota;
- facoltativamente un documento.
Server --> Client
Quando il server risponde al client, invia
- righe di testo in formato HTTP per indicare cosa sta inviando;
- una riga vuota;
- facoltativamente un documento.
Gli scambi seguono quindi lo stesso formato in entrambe le direzioni. In entrambi i casi, può essere inviato un documento, anche se è raro che un client invii un documento al server. Ma il protocollo HTTP lo consente. Questo è ciò che permette, ad esempio, agli abbonati di un ISP di caricare vari documenti sul proprio sito web personale ospitato da quell'ISP. I documenti scambiati possono essere di qualsiasi tipo. Consideriamo un browser che richiede una pagina web contenente immagini:
- il browser si connette al server web e richiede la pagina desiderata. Le risorse richieste sono identificate in modo univoco dagli URL (Uniform Resource Locator). Il browser invia solo le intestazioni HTTP e nessun documento.
- Il server risponde. Innanzitutto invia le intestazioni HTTP indicando il tipo di risposta che sta inviando. Potrebbe trattarsi di un errore se la pagina richiesta non esiste. Se la pagina esiste, il server indicherà nelle intestazioni HTTP della sua risposta che invierà un documento HTML (HyperText Markup Language) a seguire. Questo documento è una sequenza di righe di testo in formato HTML. Il testo HTML contiene tag (indicatori) che forniscono al browser le istruzioni su come visualizzare il testo.
- Il client sa dalle intestazioni HTTP del server che riceverà un documento HTML. Analizzerà questo documento e potrebbe notare che contiene riferimenti a immagini. Queste immagini non sono incluse nel documento HTML. Effettua quindi una nuova richiesta allo stesso server web per richiedere la prima immagine di cui ha bisogno. Questa richiesta è identica a quella effettuata al punto 1, tranne per il fatto che la risorsa richiesta è diversa. Il server elaborerà questa richiesta inviando l'immagine richiesta al client. Questa volta, nella sua risposta, le intestazioni HTTP specificheranno che il documento inviato è un'immagine e non un documento HTML.
- Il client recupera l'immagine inviata. I passaggi 3 e 4 verranno ripetuti fino a quando il client (di solito un browser) non avrà tutti i documenti necessari per visualizzare l'intera pagina.
2.4.3. Il protocollo HTTP
Esploriamo il protocollo HTTP attraverso alcuni esempi. Cosa si scambiano un browser e un server web?
Il servizio web o servizio HTTP è un servizio TCP/IP che opera tipicamente sulla porta 80. Potrebbe operare su una porta diversa. In tal caso, il browser client dovrebbe specificare quella porta nell'URL che richiede. Un URL ha generalmente la seguente forma:
protocollo://macchina[:porta]/percorso/info
dove
protocollo | http per il servizio Web. Un browser può anche fungere da client per FTP, news, Telnet e altri servizi. |
macchina | nome della macchina che ospita il servizio Web |
porta | Porta del servizio Web. Se è 80, il numero di porta può essere omesso. Questo è il caso più comune |
percorso | percorso della risorsa richiesta |
info | informazioni aggiuntive fornite al server per specificare la richiesta del client |
Cosa fa un browser quando un utente richiede il caricamento di un URL?
- Stabilisce una connessione TCP/IP con la macchina e la porta specificate nella parte machine[:port] dell’URL. Stabilire una connessione TCP/IP significa creare un “canale” di comunicazione tra due macchine. Una volta stabilito questo canale, tutte le informazioni scambiate tra le due macchine passeranno attraverso di esso. La creazione di questo canale TCP/IP non coinvolge ancora il protocollo HTTP del Web.
- Una volta stabilita la connessione TCP-IP, il client invia la sua richiesta al server web inviando righe di testo (comandi) in formato HTTP. Invia la parte path/info dell’URL al server
- Il server risponderà allo stesso modo e attraverso la stessa connessione
- Una delle due parti deciderà di chiudere la connessione. Ciò dipende dal protocollo HTTP utilizzato. Con HTTP 1.0, il server chiude la connessione dopo ciascuna delle sue risposte. Ciò costringe un client che deve effettuare più richieste per recuperare i vari documenti che compongono una pagina web ad aprire una nuova connessione per ogni richiesta, il che comporta un costo. Con il protocollo HTTP/1.1, il client può indicare al server di mantenere aperta la connessione fino a quando non gli dirà di chiuderla. Può quindi recuperare tutti i documenti di una pagina web con un'unica connessione e chiudere la connessione una volta ottenuto l'ultimo documento. Il server rileverà questa chiusura e chiuderà a sua volta la connessione.
Per analizzare gli scambi tra un client e un server web, useremo l'estensione [Advanced Rest Client] per il browser Chrome che abbiamo installato nella Sezione 9.6. Ci troveremo nella seguente situazione:

Il server web può essere qualsiasi server. In questo caso, il nostro obiettivo è esaminare gli scambi che avverranno tra il browser e il server web. In precedenza, abbiamo creato la seguente pagina HTML statica:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>essai 1 : une page statique</title>
</head>
<body>
<h1>Une page statique...</h1>
</body>
</html>
che visualizziamo in un browser:
![]() |
Possiamo vedere che l'URL richiesto è: [http://localhost:9000/intro/exemple-01.html]. Il server web è quindi localhost (=macchina locale) sulla porta 9000. Utilizziamo l'applicazione [Advanced Rest Client] per richiedere lo stesso URL:
![]() |
- In [1], avvia l'applicazione (nella scheda [Applicazioni] di una nuova scheda di Chrome);
- in [2], selezionare l'opzione [Richiesta];
- in [3], specificare il server da interrogare: http://localhost:9000;
- in [4], specificare l'URL richiesto: /intro/example-01.html;
- in [5], aggiungi eventuali parametri all'URL. Nessuno in questo caso;
- in [6], specifica il metodo HTTP utilizzato per la richiesta, in questo caso GET.
Ciò genera la seguente richiesta:
![]() |
La richiesta preparata in questo modo [7] viene inviata al server da [8]. La risposta ricevuta è quindi la seguente:
![]() |
Abbiamo accennato in precedenza al fatto che gli scambi client-server assumono la seguente forma:

- In [1] vediamo le intestazioni HTTP inviate dal browser nella sua richiesta. Non aveva alcun documento da inviare;
- in [2], vediamo le intestazioni HTTP inviate dal server in risposta. In [3], vediamo il documento che ha inviato.
In [3], riconosciamo la pagina HTML statica che abbiamo inserito sul server web.
Esaminiamo la richiesta HTTP del browser:
- La riga 1 non è stata visualizzata dall'applicazione;
- Riga 6: il browser si identifica con l'intestazione [User-Agent];
- riga 7: il browser indica che sta inviando un documento di testo (text/plain) in formato UTF-8 al server. In realtà, in questo caso, il browser non ha inviato alcun documento;
- riga 8: il browser indica che accetta qualsiasi tipo di documento in risposta;
- riga 9: il browser specifica i formati di documento accettati;
- riga 10: il browser specifica le lingue che preferisce in ordine di preferenza.
Il server ha risposto inviando le seguenti intestazioni HTTP:
- riga 1: non è stata visualizzata dall'applicazione;
- riga 2: il server si identifica, in questo caso un server Apache-Coyote;
- riga 3: la data dell'ultima modifica del documento;
- riga 4: il tipo di documento inviato dal server. In questo caso, un documento HTML;
- riga 5: la dimensione in byte del documento HTML inviato.
- riga 6: data e ora della risposta;
2.4.4. Conclusione
Abbiamo esaminato la struttura della richiesta di un client web e la risposta del server ad essa utilizzando alcuni esempi. La comunicazione avviene tramite il protocollo HTTP, un insieme di comandi testuali scambiati tra le due parti. La richiesta del client e la risposta del server seguono la stessa struttura:

I due comandi più comuni per richiedere una risorsa sono GET e POST. Il comando GET non è accompagnato da un documento. Il comando POST, invece, è accompagnato da un documento che è un , il più delle volte, una stringa di caratteri contenente tutti i valori inseriti in un modulo. Il comando HEAD consente di richiedere solo le intestazioni HTTP e non è accompagnato da un documento.
In risposta alla richiesta di un client, il server invia una risposta con la stessa struttura. La risorsa richiesta viene trasmessa nella sezione [Document], a meno che il comando del client non fosse HEAD, nel qual caso vengono inviate solo le intestazioni HTTP.
2.5. Nozioni di base sull'HTML
Un browser web può visualizzare vari documenti, il più comune dei quali è il documento HTML (HyperText Markup Language). Si tratta di testo formattato utilizzando tag nella forma <tag>testo</tag>. Pertanto, il testo <B>importante</B> visualizzerà il testo "importante" in grassetto. Esistono tag autonomi come il tag <hr/>, che visualizza una linea orizzontale. Non esamineremo tutti i tag che si possono trovare nel testo HTML. Esistono molti programmi software WYSIWYG che consentono di creare una pagina web senza scrivere una sola riga di codice HTML. Questi strumenti generano automaticamente il codice HTML per un layout creato utilizzando il mouse e controlli predefiniti. È quindi possibile inserire (utilizzando il mouse) una tabella nella pagina e quindi visualizzare il codice HTML generato dal software per scoprire i tag da utilizzare per definire una tabella su una pagina web. È semplicissimo. Inoltre, la conoscenza dell'HTML è essenziale poiché le applicazioni web dinamiche devono generare autonomamente il codice HTML da inviare ai client web. Questo codice viene generato a livello di programmazione e, ovviamente, è necessario sapere cosa generare affinché il client riceva la pagina web desiderata.
Per riassumere, non è necessario conoscere l'intero linguaggio HTML per iniziare a programmare per il web. Tuttavia, questa conoscenza è necessaria e può essere acquisita attraverso l'uso di editor di pagine web WYSIWYG come DreamWeaver e decine di altri. Un altro modo per scoprire le complessità dell'HTML è navigare sul web e visualizzare il codice sorgente delle pagine che presentano elementi interessanti che non avete mai incontrato prima.
2.5.1. Un esempio
Consideriamo il seguente esempio, che presenta alcuni elementi comunemente presenti in un documento web, quali:
- una tabella;
- un'immagine;
- un link.
![]() | ![]() |
Un documento HTML ha generalmente la seguente struttura:
<html> <head> <title>Un titolo</title> ... </head> <attributi del corpo> ... </body></html>
L'intero documento è racchiuso tra i tag <html>...</html>. È composto da due parti:
- <head>...</head>: questa è la parte non visualizzabile del documento. Fornisce informazioni al browser che visualizzerà il documento. Spesso contiene il tag <title>...</title>, che imposta il testo che apparirà nella barra del titolo del browser. Può contenere anche altri tag, in particolare quelli che definiscono le parole chiave del documento, che vengono poi utilizzate dai motori di ricerca. Questa sezione può contenere anche script, solitamente scritti in JavaScript o VBScript, che verranno eseguiti dal browser.
- <attributi del corpo>...</body>: Questa è la sezione che verrà visualizzata dal browser. I tag HTML contenuti in questa sezione indicano al browser l'impaginazione visiva "desiderata" per il documento. Ogni browser interpreta questi tag a modo suo. Di conseguenza, due browser potrebbero visualizzare lo stesso documento web in modo diverso. Questa è generalmente una delle sfide che devono affrontare i web designer.
Il codice HTML del nostro documento di esempio è il seguente:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>balises</title>
</head>
<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
<h1 style="text-align: center">Les balises HTML</h1>
<hr />
<table border="1">
<thead>
<tr>
<th>Colonne 1</th>
<th>Colonne 2</th>
<th>Colonne 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>cellule(1,1)</td>
<td style="width: 150px; text-align: center;">cellule(1,2)</td>
<td>cellule(1,3)</td>
</tr>
<tr>
<td>cellule(2,1)</td>
<td>cellule(2,2)</td>
<td>cellule(2,3</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>Une image</td>
<td><img border="0" src="images/cerisier.jpg" /></td>
</tr>
<tr>
<td>le site de l'ISTIA</td>
<td><a href="http://istia.univ-angers.fr">ici</a></td>
</tr>
</table>
</body>
</html>
HTML | Tag HTML ed esempi |
titolo del documento | <title>tag</title> (riga 5) Il testo "tags" apparirà nella barra del titolo del browser quando il documento viene visualizzato |
barra orizzontale | <hr/>: visualizza una linea orizzontale (riga 10) |
tabella | <attributi tabella>....</table>: per definire la tabella (righe 11, 31) <thead>...</thead>: per definire le intestazioni delle colonne (righe 12, 18) <tbody>...</tbody>: per definire il contenuto della tabella ( , righe 19, 30) <tr attributes>...</tr>: per definire una riga (righe 20, 24) <attributi td>...</td>: per definire una cella (riga 21) esempi: <table border="1">...</table>: l'attributo border definisce lo spessore del bordo della tabella <td style="width: 150px; text-align: center;">cell(1,2)</td>: definisce una cella il cui contenuto sarà cell(1,2). Questo contenuto sarà centrato orizzontalmente (text-align: center). La cella avrà una larghezza di 150 pixel (width: 150px) |
immagine | <img border="0" src="/images/cherrytree.jpg"/> (riga 36): definisce un'immagine senza bordo (border="0") il cui file sorgente è /images/cherrytree.jpg sul server web (src="/images/cherrytree.jpg"). Questo collegamento si trova in un documento web accessibile tramite l'URL http://localhost:port/intro/exemple-04.html. Pertanto, il browser richiederà l'URL http://localhost:port/intro/images/cerisier.jpg per recuperare l'immagine a cui si fa riferimento qui. |
link | <a href="http://istia.univ-angers.fr">qui</a> (riga 40): fa sì che il testo "qui" funga da collegamento all'URL http://istia.univ-angers.fr. |
sfondo della pagina | <body style="height:400px;width:400px;background-image:url(images/standard.jpg)"> (riga 8): specifica che l'immagine da utilizzare come sfondo della pagina si trova all'URL [images/standard.jpg] sul server web. Nel contesto del nostro esempio, il browser richiederà l'URL http://localhost:port/intro/images/standard.jpg per recuperare questa immagine di sfondo. Inoltre, il corpo del documento verrà visualizzato all'interno di un rettangolo alto 400 pixel e largo 400 pixel. |
In questo semplice esempio, possiamo vedere che per visualizzare l'intero documento, il browser deve effettuare tre richieste al server:
- http://localhost:port/intro/exemple-04.html per recuperare il codice sorgente HTML del documento
- http://localhost:port/intro/images/cerisier.jpg per recuperare l'immagine cerisier.jpg
- http://localhost:port/intro/images/standard.jpg per recuperare l'immagine di sfondo standard.jpg
2.5.2. Un modulo HTML
L'esempio seguente mostra un modulo:
![]() | ![]() |
Il codice HTML che genera questa visualizzazione è il seguente:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>formulaire</title>
<script type="text/javascript">
function effacer() {
alert("Vous avez cliqué sur le bouton Effacer");
}
</script>
</head>
<body style="height: 400px; width: 400px; background-image: url(images/standard.jpg)">
<h1 style="text-align: center">Formulaire HTML</h1>
<form method="post" action="postFormulaire">
<table>
<tr>
<td>Etes-vous marié(e)</td>
<td>
<input type="radio" value="Oui" name="R1" />Oui
<input type="radio" name="R1" value="non" checked="checked" />Non
</td>
</tr>
<tr>
<td>Cases à cocher</td>
<td>
<input type="checkbox" name="C1" value="un" />1
<input type="checkbox" name="C2" value="deux" checked="checked" />2
<input type="checkbox" name="C3" value="trois" />3
</td>
</tr>
<tr>
<td>Champ de saisie</td>
<td>
<input type="text" name="txtSaisie" size="20" value="qqs mots" />
</td>
</tr>
<tr>
<td>Mot de passe</td>
<td>
<input type="password" name="txtMdp" size="20" value="unMotDePasse" />
</td>
</tr>
<tr>
<td>Boîte de saisie</td>
<td>
<textarea rows="2" name="areaSaisie" cols="20">
ligne1
ligne2
ligne3
</textarea>
</td>
</tr>
<tr>
<td>combo</td>
<td>
<select size="1" name="cmbValeurs">
<option value="1">choix1</option>
<option selected="selected" value="2">choix2</option>
<option value="3">choix3</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix simple</td>
<td>
<select size="3" name="lst1">
<option selected="selected" value="1">liste1</option>
<option value="2">liste2</option>
<option value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</td>
</tr>
<tr>
<td>liste à choix multiple</td>
<td>
<select size="3" name="lst2" multiple="multiple">
<option value="1" selected="selected">liste1</option>
<option value="2">liste2</option>
<option selected="selected" value="3">liste3</option>
<option value="4">liste4</option>
<option value="5">liste5</option>
</select>
</td>
</tr>
<tr>
<td>bouton</td>
<td>
<input type="button" value="Effacer" name="cmdEffacer" onclick="effacer()" />
</td>
</tr>
<tr>
<td>envoyer</td>
<td>
<input type="submit" value="Envoyer" name="cmdRenvoyer" />
</td>
</tr>
<tr>
<td>rétablir</td>
<td>
<input type="reset" value="Rétablir" name="cmdRétablir" />
</td>
</tr>
</table>
<input type="hidden" name="secret" value="uneValeur" />
</form>
</body>
</html>
L'associazione visiva tra <--> e il tag HTML è la seguente:
Visivo | Tag HTML |
form | <form method="post" action="..."> |
campo di immissione | <input type="text" name="txtInput" size="20" value="alcune parole" /> |
campo di immissione nascosto | <input type="password" name="txtPassword" size="20" value="aPassword" /> |
campo di immissione multilinea | <textarea rows="2" name="inputArea" cols="20"> riga1 riga2 riga3 </textarea> |
pulsanti di opzione | <input type="radio" value="Sì" name="R1" />Sì <input type="radio" name="R1" value="No" checked="checked" />No |
caselle di controllo | <input type="checkbox" name="C1" value="uno" />1 <input type="checkbox" name="C2" value="due" checked="checked" />2 <input type="checkbox" name="C3" value="tre" />3 |
Menu a tendina | <select size="1" name="cmbValues"> <option value="1">opzione1</option> <option selected="selected" value="2">opzione2</option> <option value="3">opzione3</option> </select> |
elenco a selezione singola | <select size="3" name="lst1"> <option selected="selected" value="1">elenco1</option> <option value="2">elenco2</option> <option value="3">elenco3</option> <option value="4">elenco4</option> <option value="5">elenco5</option> </select> |
elenco a selezione multipla | <select size="3" name="lst2" multiple="multiple"> <option value="1">elenco1</option> <option value="2">elenco2</option> <option selected="selected" value="3">elenco3</option> <option value="4">elenco4</option> <option value="5">elenco5</option> </select> |
pulsante di invio | <input type="submit" value="Invia" name="cmdSubmit" /> |
pulsante di ripristino | <input type="reset" value="Reimposta" name="cmdReset" /> |
pulsante | <input type="button" value="Cancella" name="cmdClear" onclick="clear()" /> |
Rivediamo questi diversi tag:
2.5.2.1. Il modulo
form | |
Tag HTML | <form name="..." method="..." action="...">...</form> |
attributi | name="exampleForm": nome del modulo method="..." : metodo utilizzato dal browser per inviare i valori raccolti nel modulo al server web action="..." : URL a cui verranno inviati i valori raccolti nel modulo. Un modulo web è racchiuso tra i tag <form>...</form>. Il modulo può avere un nome (name="xx"). Questo vale per tutti i controlli presenti all'interno di un modulo. Lo scopo di un modulo è quello di raccogliere le informazioni inserite dall'utente tramite la tastiera o il mouse e inviarle a un URL del server web. Quale? Quello indicato nell'attributo action="URL". Se questo attributo manca, le informazioni saranno inviate all'URL del documento in cui si trova il modulo. Un client web può utilizzare due diversi metodi, chiamati POST e GET, per inviare dati a un server web. L'attributo method="method", dove method è impostato su GET o POST, nel tag <form> indica al browser quale metodo utilizzare per inviare le informazioni raccolte nel modulo all'URL specificato dall'attributo action="URL". Quando l'attributo method non è specificato, viene utilizzato per impostazione predefinita il metodo GET. |
2.5.2.2. Campi di immissione testo
campo di immissione | <input type="text" name="txtInput" size="20" value="alcune parole" /> <input type="password" name="txtMdp" size="20" value="aPassword" /> |
![]() |
Tag HTML | <input type="..." name="..." size=".." value=".."/> Il tag input esiste per vari controlli. È l'attributo type che distingue questi diversi controlli l'uno dall'altro. |
attributi | type="text": specifica che si tratta di un campo di immissione testo type="password": i caratteri nel campo di immissione vengono sostituiti da asterischi (*). Questa è l’unica differenza rispetto a un normale campo di immissione. Questo tipo di controllo è adatto per l’immissione di password. size="20": numero di caratteri visibili nel campo — non impedisce l’inserimento di più caratteri name="txtInput": nome del controllo value="alcune parole": testo che verrà visualizzato nel campo di immissione. |
2.5.2.3. Campi di immissione multilinea
campo di immissione multilinea | <textarea rows="2" name="areaSaisie" cols="20"> riga1 riga2 riga3 </textarea> |
![]() |
Tag HTML | <textarea ...>testo</textarea> visualizza un campo di immissione testo multilinea con del testo già all'interno |
attributi | rows="2": numero di righe cols="'20" : numero di colonne name="areaSaisie": nome del controllo |
2.5.2.4. I pulsanti di opzione
pulsanti di opzione | <input type="radio" value="Sì" name="R1" />Sì <input type="radio" name="R1" value="No" checked="checked" />No |
Tag HTML | <input type="radio" attribute2="value2" ..../>testo visualizza un pulsante di opzione con del testo accanto. |
attributi | name="radio": nome del controllo. I pulsanti di opzione con lo stesso nome formano un gruppo di pulsanti mutuamente esclusivi: è possibile selezionarne solo uno. value="value": valore assegnato al pulsante di opzione. Non confondere questo valore con il testo visualizzato accanto al pulsante di opzione. Il testo serve solo a scopo di visualizzazione. checked="checked": se questo attributo è presente, il pulsante di opzione è selezionato; altrimenti, non lo è. |
2.5.2.5. Caselle di controllo
Caselle di controllo | <input type="checkbox" name="C1" value="uno" />1 <input type="checkbox" name="C2" value="due" checked="checked" />2 <input type="checkbox" name="C3" value="tre" />3 |
Tag HTML | <input type="checkbox" attribute2="value2" ....>testo visualizza una casella di controllo con del testo accanto. |
attributi | name="C1": nome del controllo. Le caselle di controllo possono avere o meno lo st . Le caselle di controllo con lo stesso nome formano un gruppo di caselle di controllo associate. value="value": valore assegnato alla casella di controllo. Non confondere questo valore con il testo visualizzato accanto alla casella di controllo. Il testo serve solo a scopo di visualizzazione. checked="checked": se questo attributo è presente, la casella di controllo è selezionata; in caso contrario, non lo è. |
2.5.2.6. L'elenco a discesa (combo)
Combo | <select size="1" name="cmbValues"> <option value="1">scelta1</option> <option selected="selected" value="2">opzione2</option> <option value="3">opzione3</option> </select> |
Tag HTML | <select size=".." name=".."> <option [selected="selected"] value=”v”>...</option> ... </select> visualizza il testo tra i tag <option>...</option> in un elenco |
attributi | name="cmbValeurs": nome del controllo. size="1": numero di voci visibili dell'elenco. size="1" rende l'elenco equivalente a una casella combinata. selected="selected": se questa parola chiave è presente per una voce dell'elenco, tale voce appare selezionata nell'elenco. Nel nostro esempio sopra, la voce dell'elenco choice2 appare come voce selezionata nella casella combinata quando viene visualizzata per la prima volta. value=”v”: se la voce viene selezionata dall’utente, questo valore [v] viene inviato al server. Se questo attributo è assente, il testo visualizzato e selezionato viene inviato al server. |
2.5.2.7. Elenco a selezione singola
elenco a selezione singola | <select size="3" name="lst1"> <option selected="selected" value="1">list1</option> <option value="2">elenco2</option> <option value="3">elenco3</option> <option value="4">elenco4</option> <option value="5">elenco5</option> </select> |
![]() |
Tag HTML | <select size=".." name=".."> <option [selected="selected"]>...</option> ... </select> visualizza il testo tra i tag <option>...</option> in un elenco |
attributi | gli stessi dell'elenco a discesa che visualizza un solo elemento. Questo controllo differisce dal precedente elenco a discesa solo per l'attributo size>1. |
2.5.2.8. Elenco a selezione multipla
elenco a selezione singola | <select size="3" name="lst2" multiple="multiple"> <option value="1" selected="selected">list1</option> <option value="2">elenco2</option> <option selected="selected" value="3">elenco3</option> <option value="4">elenco4</option> <option value="5">list5</option> </select> |
![]() |
Tag HTML | <select size=".." name=".." multiple="multiple"> <option [selected="selected"]>...</option> ... </select> visualizza il testo tra i tag <option>...</option> in un elenco |
attributi | multiple: consente di selezionare più elementi dall'elenco. Nell'esempio sopra, gli elementi list1 e list3 sono entrambi selezionati. |
2.5.2.9. Pulsante
pulsante | <input type="button" value="Cancella" name="cmdClear" onclick="clear()" /> |
Tag HTML | <input type="button" value="..." name="..." onclick="clear()" ..../> |
attributi | type="button": definisce un controllo pulsante. Esistono altri due tipi di pulsanti: submit e reset. value="Clear": il testo visualizzato sul pulsante onclick="function()": consente di definire una funzione da eseguire quando l'utente fa clic sul pulsante. Questa funzione fa parte degli script definiti nel documento web visualizzato. La sintassi sopra riportata è quella di JavaScript. Se gli script sono scritti in VBScript, si scriverà onclick="function" senza le parentesi. La sintassi rimane la stessa se è necessario passare dei parametri alla funzione: onclick="function(val1, val2,...)" Nel nostro esempio, cliccando sul pulsante Cancella si richiama la seguente funzione JavaScript clear: <script type="text/javascript"> function clear() { alert("Hai cliccato sul pulsante Cancella"); } </script> La funzione clear visualizza un messaggio: ![]() |
2.5.2.10. Pulsante Invia
Pulsante Invia | <input type="submit" value="Invia" name="cmdSend" /> |
Tag HTML | <input type="submit" value="Invia" name="cmdRenvoyer" /> |
attributi | type="submit": definisce il pulsante come pulsante per l'invio dei dati del modulo al server web. Quando l'utente fa clic su questo pulsante, il browser invierà i dati del modulo all'URL definito nell'attributo action del tag <form>, utilizzando il metodo definito dall'attributo method dello stesso tag. value="Invia": il testo visualizzato sul pulsante |
2.5.2.11. Pulsante di reset
pulsante di reset | <input type="reset" value="Reset" name="cmdReset" /> |
Tag HTML | <input type="reset" value="Reset" name="cmdReset"/> |
attributi | type="reset": definisce il pulsante come pulsante di reset del modulo. Quando l'utente clicca su questo pulsante, il browser ripristinerà il modulo allo stato in cui è stato ricevuto. value="Reset": il testo visualizzato sul pulsante |
2.5.2.12. Campo nascosto
campo nascosto | <input type="hidden" name="secret" value="aValue" /> |
Tag HTML | <input type="hidden" name="..." value="..."/> |
attributi | type="hidden": specifica che si tratta di un campo nascosto. Un campo nascosto fa parte del modulo ma non viene visualizzato all'utente. Tuttavia, se l'utente chiedesse al proprio browser di visualizzare il codice sorgente, vedrebbe la presenza del tag <input type="hidden" value="..."> e quindi il valore del campo nascosto. value="aValue": valore del campo nascosto. Qual è lo scopo di un campo nascosto? Consente al server web di conservare le informazioni tra una richiesta e l'altra del client. Si consideri un'applicazione di shopping online. Il cliente acquista un primo articolo art1 in quantità q1 nella prima pagina di un catalogo e poi passa a una nuova pagina del catalogo. Per ricordare che il cliente ha acquistato q1 articoli di art1, il server può inserire queste due informazioni in un campo nascosto nel modulo web della nuova pagina. In questa nuova pagina, il cliente acquista q2 unità dell'articolo art2. Quando i dati di questo secondo modulo vengono inviati al server, il server non riceverà solo le informazioni (q2,art2) ma anche (q1,art1), che fanno anch'esse parte del modulo come campo nascosto. Il server web inserirà quindi le informazioni (q1,art1) e (q2,art2) in un nuovo campo nascosto e invierà una nuova pagina del catalogo. E così via. |
2.5.3. Invio dei valori del modulo a un server web da parte di un client web
Nella lezione precedente abbiamo accennato al fatto che il client web dispone di due metodi per inviare i valori di un modulo visualizzato a un server web: i metodi GET e POST. Vediamo un esempio per comprendere la differenza tra i due metodi.
2.5.3.1. Metodo GET
Eseguiamo un test iniziale, in cui nel codice HTML del documento il tag <form> è definito come segue:
<form method="get" action="doNothing">
![]() |
Quando l'utente fa clic sul pulsante [1], i valori inseriti nel modulo verranno inviati al controller Spring [2]. Abbiamo visto che i valori del modulo verrebbero inviati all'URL [doNothing]:
<form method="get" action="doNothing">
L'azione [doNothing] è definita nel controller [MyController] [2] come segue:
// ----------------------- rendre un flux vide [Content-Length=0]
@RequestMapping(value = "/doNothing")
@ResponseBody
public void doNothing() {
}
- riga 1: l'azione gestisce l'URL [/doNothing], che in realtà è [/context/doNothing], dove [context] è il contesto o il nome dell'applicazione web, in questo caso [/intro];
- riga 3: l'annotazione [@ResponseBody] indica che il risultato del metodo annotato deve essere inviato direttamente al client;
- riga 4: il metodo non restituisce nulla. Pertanto, il client riceverà una risposta vuota dal server.
Vogliamo solo sapere come il browser trasmette i valori inseriti al server web. Per farlo, useremo uno strumento di debug disponibile in Chrome. Lo attiviamo premendo CTRL-Shift-I (tasto Shift) [3]:
![]() |
Poiché ci interessa il traffico di rete tra il browser e il server web, apriamo la scheda [Rete] in alto e poi clicchiamo sul pulsante [Invia] nel modulo. Si tratta di un pulsante [submit] all'interno di un tag [form]. Il browser risponde al clic richiedendo l'URL [/intro/doNothing] specificato nell'attributo [action] del tag [form], utilizzando il metodo GET specificato nell'attributo [method]. Otteniamo quindi le seguenti informazioni:
![]() |
La schermata sopra mostra l'URL richiesto dal browser dopo aver cliccato sul pulsante [Invia]. Richiede effettivamente l'URL previsto [/intro/doNothing], ma aggiunge ulteriori informazioni: i valori inseriti nel modulo. Per ottenere maggiori informazioni, clicca sul link sopra:
![]() |
Sopra [1, 2] sono riportate le intestazioni HTTP inviate dal browser. Qui sono state formattate. Per visualizzare il testo grezzo di queste intestazioni, si clicca sul link [Visualizza sorgente] [3, 4]. Il testo completo è il seguente:
Vediamo elementi che abbiamo già incontrato in precedenza. Altri compaiono per la prima volta:
Connection: keep-alive | il client chiede al server di non chiudere la connessione dopo la sua risposta. Ciò consentirà al client di utilizzare la stessa connessione per una richiesta successiva. La connessione non rimane aperta a tempo indeterminato. Il server la chiuderà dopo un periodo prolungato di inattività. |
Referer | L'URL che era visualizzato nel browser quando è stata effettuata la nuova richiesta. |
Il nuovo elemento è la riga 1 nelle informazioni che seguono l'URL. Possiamo vedere che le scelte effettuate nel modulo si riflettono nell'URL. I valori inseriti dall'utente nel modulo sono stati passati nell'URL della richiesta GET?param1=value1¶m2=value2&... HTTP/1.1, dove i parametri sono i nomi (attributo name) dei controlli del modulo web e i valori sono quelli ad essi associati. Di seguito è riportata una tabella a tre colonne:
- Colonna 1: mostra la definizione di un controllo HTML dell'esempio;
- Colonna 2: mostra come questo controllo appare in un browser;
- Colonna 3: mostra il valore inviato al server dal browser per il controllo della Colonna 1 nella forma che assume nella richiesta GET dell'esempio.
Controllo HTML | Valore | Valori restituiti |
<input type="radio" value="Yes" name="R1"/>Yes <input type="radio" name="R1" value="No" checked="checked"/>No | R1=Sì - il valore dell'attributo value del pulsante di opzione selezionato dall'utente. | |
<input type="checkbox" name="C1" value="uno"/>1 <input type="checkbox" name="C2" value="due" checked="checked"/>2 <input type="checkbox" name="C3" value="three"/>3 | C1=uno C2=due - valori degli attributi value delle caselle di controllo selezionate dall'utente | |
<input type="text" name="txtInput" size="20" value="alcune parole"/> | txtInput=programmazione+web - testo digitato dall'utente nel campo di immissione. Gli spazi sono stati sostituiti dal segno + | |
<input type="password" name="txtMdp" size="20" value="aPassword"/> | txtPassword=thisIsSecret - testo digitato dall'utente nel campo di immissione | |
<textarea rows="2" name="inputArea" cols="20"> riga1 riga2 riga3 </textarea> | campo_input=le+nozioni+di+base+del+Web%0D%0A programmazione+web - testo digitato dall'utente nel campo di immissione. %OD%OA è il marcatore di fine riga. Gli spazi sono stati sostituiti dal segno + | |
<select size="1" name="cmbValeurs"> <option value='1'>scelta1</option> <option selected="selected" value='2'>opzione2</option> <option value='3'>opzione3</option> </select> | cmbValues=3 - attributo [value] dell'elemento selezionato dall'utente | |
<select size="3" name="lst1"> <option selected="selected" value='1'>list1</option> <option value='2'>list2</option> <option value='3'>list3</option> <option value='4'>list4</option> <option value='5'>elenco5</option> </select> | ![]() | lst1=3 - attributo [value] dell'elemento selezionato dall'utente |
<select size="3" name="lst2" multiple="multiple"> <option selected="selected" value='1'>list1</option> <option value='2'>list2</option> <option selected="selected" value='3'>list3</option> <option value='4'>list4</option> <option value='5'>list5</option> </select> | lst2=1 lst2=3 - attributi [value] degli elementi selezionati dall'utente | |
<input type="submit" value="Invia" name="cmdSubmit"/> | cmdRenvoyer=Invia - attributi name e value del pulsante utilizzato per inviare i dati del modulo al server | |
<input type="hidden" name="secret" value="aValue"/> | secret=aValue - attributo value del campo nascosto |
2.5.3.2. Metodo POST
Modifichiamo il documento HTML in modo che il browser utilizzi ora il metodo POST per inviare i valori del modulo al server web:
<form method="post" action="doNothing">
Compiliamo il modulo come abbiamo fatto per il metodo GET e inviamo i parametri al server utilizzando il pulsante [Invia]. Come abbiamo fatto nella sezione precedente a pagina 62, possiamo visualizzare le intestazioni HTTP della richiesta inviata dal browser in Chrome:
Nella richiesta HTTP del client compaiono nuovi elementi:
POST HTTP/1.1 | La richiesta GET è stata sostituita da una richiesta POST. I parametri non sono più presenti nella prima riga della richiesta. Possiamo notare che ora sono posizionati (riga 15) dopo la richiesta HTTP, a seguito di una riga vuota. La loro codifica è identica a quella della richiesta GET. |
Content-Length | numero di caratteri "pubblicati", ovvero il numero di caratteri che il server web deve leggere dopo aver ricevuto le intestazioni HTTP per recuperare il documento inviato dal client. Il documento in questione qui è l'elenco dei valori del modulo. |
Content-type | specifica il tipo di documento che il client invierà dopo le intestazioni HTTP. Il tipo [application/x- www-form-urlencoded] indica che si tratta di un documento contenente valori del modulo. |
Esistono due metodi per trasmettere dati a un server web: GET e POST. Uno dei due è migliore dell'altro? Abbiamo visto che se i valori di un modulo venissero inviati dal browser utilizzando il metodo GET, il browser visualizzerebbe l'URL richiesto nella barra degli indirizzi nel formato URL?param1=val1¶m2=val2&.... Questo può essere considerato sia un vantaggio che uno svantaggio:
- un vantaggio se si desidera consentire all'utente di salvare questo URL parametrizzato nei propri segnalibri;
- uno svantaggio se non si desidera che l'utente abbia accesso a determinate informazioni del modulo, come i campi nascosti.
D'ora in poi, useremo quasi esclusivamente il metodo POST nei nostri moduli.
2.6. Conclusione
Questo capitolo ha introdotto vari concetti di base dello sviluppo web:
- comunicazione client-server tramite il protocollo HTTP;
- progettazione di un documento utilizzando l'HTML;
- la progettazione di moduli di input.
Abbiamo visto in un esempio come un client possa inviare informazioni al server web. Non abbiamo trattato il modo in cui il server possa
- recuperare queste informazioni;
- elaborarle;
- inviare al client una risposta dinamica basata sul risultato dell'elaborazione.
Questo è il campo della programmazione web, un argomento che tratteremo nel prossimo capitolo con un'introduzione alla tecnologia Spring MVC.










































