2. De basisprincipes van webprogrammering
Dit hoofdstuk heeft als voornaamste doel de belangrijkste principes van webprogrammering te introduceren, die losstaan van de specifieke technologie die wordt gebruikt om ze te implementeren. Het bevat talrijke voorbeelden die u best zelf uitprobeert om de filosofie van webontwikkeling geleidelijk aan onder de knie te krijgen. Lezers die deze kennis al bezitten, kunnen direct doorgaan naar hoofdstuk 3.
De onderdelen van een webapplicatie zijn de volgende:

Nummer | Functie | Veelvoorkomende voorbeelden |
1 | OS Server | Unix, Linux, Windows |
2 | Webserver | Apache (Unix, Linux, Windows) IIS (Windows + .NET-platform) Node.js (Unix, Linux, Windows) |
3 | Codes die aan de serverzijde worden uitgevoerd. Dit kan gebeuren via servermodules of via programma's buiten de server (CGI). | JAVASCRIPT (Node.js) PHP (Apache, IIS) JAVA (Tomcat, Websphere, JBoss, Weblogic, ...) C#, VB.NET (IIS) |
4 | Database – Deze kan zich op dezelfde machine bevinden als het programma dat er gebruik van maakt, of op een andere machine via internet. | Oracle (Linux, Windows) MySQL (Linux, Windows) Postgres (Linux, Windows) SQL Server (Windows) |
5 | OS Client | Unix, Linux, Windows |
6 | Webbrowser | Chrome, Internet Explorer, Firefox, Opera, Safari, ... |
7 | Scripts die aan de clientzijde in de browser worden uitgevoerd. Deze scripts hebben geen toegang tot de schijven van de clientcomputer. | JavaScript (alle browsers) |
2.1. Gegevensuitwisseling in een webapplicatie met een formulier

Nummer | Rol |
1 | De browser vraagt voor de eerste keer een URL aan: (http://machine/url). Er worden geen parameters doorgegeven. |
2 | De webserver stuurt hem de webpagina van deze URL. Deze kan statisch zijn of dynamisch worden gegenereerd door een serverscript (SA) dat mogelijk gebruik heeft gemaakt van de inhoud van databases (SB, SC). In dit geval detecteert het script dat URL is opgevraagd zonder dat er parameters zijn doorgegeven en genereert het de startpagina. De browser ontvangt de pagina en geeft deze weer (CA). Scripts aan de kant van de browser (CB) hebben de door de server verzonden oorspronkelijke pagina mogelijk gewijzigd. Vervolgens wordt de webpagina gewijzigd door interacties tussen de gebruiker (CD) en de scripts (CB). Met name worden de formulieren ingevuld. |
3 | De gebruiker bevestigt de gegevens in het formulier, die vervolgens naar de webserver moeten worden verzonden. De browser vraagt de oorspronkelijke URL of, afhankelijk van de situatie, een andere pagina opnieuw op en stuurt tegelijkertijd de formulierwaarden naar de server. Hiervoor kan hij gebruikmaken van twee methoden, namelijk GET en POST. Bij ontvangst van het verzoek van de client activeert de server het script (SA) dat gekoppeld is aan de aangevraagde URL; dit script detecteert de parameters en verwerkt deze. |
4 | De server levert de programmatisch gegenereerde webpagina af (SA, SB, SC). Deze stap is identiek aan de vorige stap 2. De uitwisselingen verlopen voortaan volgens de stappen 2 en 3. |
2.2. Statische webpagina’s, dynamische webpagina’s
Een statische pagina wordt weergegeven door een bestand HTML. Een dynamische pagina is een HTML-pagina die „on-the-fly“ door de webserver wordt gegenereerd.
2.2.1. Statische pagina HTML (HyperText Markup Language)
Laten we een eerste Spring-project MVC [1-2] opzetten:
![]() |
- in [1-2] maken we een nieuw project op basis van Spring Boot [http://projects.spring.io/spring-boot/];
![]() |
- de informatie [3-7] is voor de Maven-configuratie van het project;
- in [3], de naam van het Maven-project;
- in [4] staat de Maven-groep waarin het resultaat van de compilatie van het project wordt geplaatst;
- in [5], de naam die aan het compilatieresultaat wordt gegeven;
- in [6], een beschrijving van het project;
- in [7], het pakket waarin de uitvoerbare klasse van het project wordt geplaatst;
- in [8], de aard van het project. Het is een webproject met Thymeleaf-weergaven. Hier zien we alle kant-en-klare Maven-afhankelijkheden die door het Spring Boot-project worden aangeboden;
- in [9] geven we aan dat het resultaat van de Maven-build in een jar-archief zal worden verpakt en niet in een war-archief. Het project zal dan gebruikmaken van een ingebouwde Tomcat-server die in de afhankelijkheden zal staan;
- in [10] gaan we verder met de wizard;
![]() |
- in [11] wordt de projectmap opgegeven;
- in [12] sluit je de wizard af;
- in [13], het gegenereerde project.
Laten we het gegenereerde bestand [pom.xml] eens bekijken:
<?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 /> <!-- opzoekactie naar bovenliggend element uit de 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>
Het bevat alle informatie die in de wizard is opgegeven. In de regels 26-30 vinden we een afhankelijkheid die we nog niet kenden. Deze maakt de integratie van de unit-tests JUnit met Spring mogelijk.
Laten we beginnen met het aanmaken van een statische pagina HTML in dit project. Deze moet standaard in de map [src / main / resources / static] worden geplaatst:
![]() |
- in [1-4] maken we een bestand HTML aan in de map [static];
![]() |
- naar [6], geef de pagina een naam;
- in [7] is de pagina toegevoegd.
De inhoud van de aangemaakte pagina is als volgt:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
</body>
</html>
- regels 2-10: de code wordt begrensd door de root-tag <html>;
- regels 3-6: de tag <head> omvat wat de koptekst van de pagina wordt genoemd;
- regels 7-9: de tag <body> omvat wat de hoofdtekst van de pagina wordt genoemd.
Laten we deze code als volgt aanpassen:
<!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>
- regel 5: definieert de titel van de pagina – wordt weergegeven als titel van het browservenster waarin de pagina wordt weergegeven;
- regel 8: tekst in grote letters (<h1>).
Laten we de applicatie [1-3] uitvoeren:
![]() |
en laten we vervolgens met een browser de URL [http://localhost:8080/exemple-01.html] opvragen:
![]() |
- in [1], de URL van de weergegeven pagina;
- in [2], de titel van het venster – werd geleverd door de tag <title> van de pagina;
- in [3], de hoofdtekst van de pagina – is afkomstig van de tag <h1>.
Laten we eens kijken naar [4-5], de code die de browser heeft ontvangen:
![]() |
- in [5] heeft de browser de pagina HTML ontvangen die we hadden opgebouwd. Hij heeft deze geïnterpreteerd en er een grafische weergave van gemaakt.
2.2.2. Een dynamische Thymeleaf-pagina
Laten we nu een Thymeleaf-pagina maken. Dit is een klassieke HTML-pagina met tags die zijn verrijkt met [Thymeleaf]- en [http://www.thymeleaf.org/]-attributen. We volgen een vergelijkbare werkwijze als bij het aanmaken van de pagina HTML, maar deze keer moet de nieuwe pagina HTML in de map [templates] worden geplaatst:
![]() |
De pagina [exemple-02.html] ziet er als volgt uit:
<!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>
- regel 8: de tag <p> is een HTML-tag die een alinea in de weergegeven pagina inleidt. [th:text] is een attribuut van [Thymeleaf] dat twee verschillende functies heeft, afhankelijk van of [Thymeleaf] actief is of niet:
- als [Thymeleaf] de pagina HTML niet interpreteert, wordt het attribuut [th:text] genegeerd omdat het onbekend is in HTML. De weergegeven tekst is dan [Voici l'heure],
- als [Thymeleaf] de pagina HTML interpreteert, wordt het attribuut [th:text] geëvalueerd en vervangt de waarde ervan de tekst [Voici l'heure]. De waarde ervan zal er ongeveer zo uitzien: [Il est 17:11:06];
Laten we dit eens in de praktijk bekijken. We dupliceren de pagina [templates / exemple-02.html] in de map [static]. De pagina’s HTML die in deze map zijn geplaatst, worden niet geïnterpreteerd door [Thymeleaf]:
![]() | ![]() | ![]() |
We voeren de applicatie uit zoals we dat al meerdere keren hebben gedaan, en vragen vervolgens via een browser de bestanden URL en [http://localhost:8080/exemple-02.html] op:
![]() |
We zien in [1] dat het attribuut [th:text] niet is geïnterpreteerd en ook geen fout heeft veroorzaakt. De broncode van de ontvangen pagina in [2] laat zien dat de browser de volledige pagina inderdaad heeft ontvangen.
Laten we teruggaan naar de pagina [exemple-02.html] in de map [templates]:
![]() |
De pagina’s HTML in de map [templates] worden geïnterpreteerd door [Thymeleaf]. Laten we teruggaan naar de code van de 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>
- regel 7: [Thymeleaf] interpreteert het attribuut [th:text] en vervangt [Voici l'heure] door de waarde van de uitdrukking:
Deze uitdrukking maakt gebruik van de variabele [${heure}], waarbij [heure] behoort tot het model van de weergave [exemple-02.html]. We moeten dit model dus aanmaken. Hiervoor volgen we het voorbeeld dat in paragraaf 1.6 is besproken. We passen het project als volgt aan:
![]() |
In [1] voegen we de volgende controller toe:
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) {
// tijdnotatie
SimpleDateFormat formater = new SimpleDateFormat("HH:MM:ss");
// de huidige tijd
String heure = formater.format(new Date());
// de tijd wordt in het weergavesjabloon geplaatst
model.addAttribute("heure", heure);
// de weergave wordt weergegeven [exemple-02.html]
return "exemple-02";
}
}
- regels 13-14: de methode [heure] verwerkt de URL en [/];
- regel 14: [Model model] is een leeg sjabloon. De actie [heure] moet hierin de attributen plaatsen die zij in het sjabloon wil zien. We weten dat de weergave [exemple-02.html] een attribuut verwacht met de naam [heure];
- regels 19-22: voeren uit wat zojuist is uitgelegd. De weergave [exemple-02.html] wordt weergegeven (regel 22) met in het sjabloon een attribuut met de naam [heure] (regel 20);
- regel 16: er wordt een datumopmaakfunctie aangemaakt. Het gebruikte formaat [HH:MM:ss] is een formaat [heures:minutes:secondes] waarbij de uren binnen het interval [0-24] vallen;
- regel 18: met deze formatter wordt de datum van vandaag opgemaakt;
- regel 20: de verkregen tijd wordt gekoppeld aan een attribuut met de naam [heure];
We starten de applicatie en vragen om de URL [/]:
![]() |
- in [1] de verkregen pagina en in [2] de inhoud ervan HTML. We kunnen vaststellen dat de oorspronkelijke tekst [Voici l'heure] volledig is verdwenen;
Als we nu de pagina [1] (F5) verversen, krijgen we een andere weergave (nieuwe tijd), terwijl de URL niet verandert. Dit is het dynamische aspect van de pagina: de inhoud kan in de loop van de tijd veranderen.
Uit het bovenstaande blijkt dat dynamische en statische pagina’s fundamenteel van elkaar verschillen.
2.2.3. Configuratie van de Spring Boot-applicatie
Laten we terugkeren naar de architectuur van het Eclipse-project:
![]() |
Met het bestand [application.properties] kan de Spring Boot-applicatie worden geconfigureerd. Op dit moment is dit bestand leeg. We kunnen het gebruiken om de applicatie op verschillende manieren te configureren, zoals beschreven in URL en [http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html]. We gaan het volgende bestand [application.properties] gebruiken, zoals beschreven in [2]:
- regel 1: stelt de servicepoort van de webapplicatie in;
- regel 2: stelt de context van de webapplicatie in;
Met deze configuratie wordt de statische pagina [exemple-01.html] verkregen met de URL [http://localhost:9000/intro/exemple-01.html]:
![]() |
2.3. Scripts aan de kant van de browser
Een pagina HTML kan scripts bevatten die door de browser worden uitgevoerd. De belangrijkste scripttaal aan de browserzijde is momenteel (jan. 2015) JavaScript. Er zijn honderden bibliotheken in deze taal ontwikkeld om het leven van de ontwikkelaar te vergemakkelijken.
Laten we een nieuwe pagina [exemple-03.html] aanmaken in de map [static] van het bestaande project:
![]() |
Laten we het bestand [exemple-03.html] bewerken met de volgende inhoud:
<!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>
- regel 13: definieert een knop (attribuut type) met de tekst "Klik hier" (attribuut value). Wanneer je erop klikt, wordt de JavaScript-functie [réagir] uitgevoerd (attribuut onclick);
- regels 6-10: een JavaScript-script;
- regels 7-9: de functie [réagir];
- regel 8: geeft een dialoogvenster weer met de melding [Vous avez cliqué sur le bouton].
Laten we de pagina in een browser bekijken:
![]() |
- in [1], de weergegeven pagina;
- in [2], het dialoogvenster dat verschijnt wanneer je op de knop klikt.
Wanneer je op de knop klikt, vindt er geen communicatie met de server plaats. De JavaScript-code wordt door de browser uitgevoerd.
Met de vele beschikbare JavaScript-bibliotheken is het nu mogelijk om volwaardige applicaties in de browser te integreren. Men neigt dan naar de volgende architecturen:
![]() |
- 1-2: de server HTML is een server voor statische pagina’s HTML5 / CSS / JavaScript;
- 3-4: De gegenereerde pagina’s HTML5 / CSS / JavaScript communiceren rechtstreeks met de gegevensserver. Deze levert uitsluitend gegevens zonder opmaak (HTML). Het is de JavaScript-code die deze gegevens invoegt in HTML-pagina’s die al in de browser aanwezig zijn.
In deze architectuur kan de JavaScript-code omvangrijk worden. Daarom wordt ernaar gestreefd deze in lagen te structureren, net zoals bij de server-side code:
![]() |
- de laag [UI] is de laag die met de gebruiker communiceert;
- de laag [DAO] communiceert met de gegevensserver;
- de laag [métier] bevat de bedrijfsprocedures die noch met de gebruiker, noch met de gegevensserver communiceren. Deze laag hoeft niet te bestaan.
2.4. De communicatie tussen client en server
Laten we terugkeren naar ons oorspronkelijke schema waarin de actoren van een webapplicatie werden geïllustreerd:

We richten ons hier op de communicatie tussen de clientcomputer en de servercomputer. Deze communicatie vindt plaats via een netwerk en het is goed om de algemene structuur van de communicatie tussen twee computers op afstand nog eens in herinnering te brengen.
2.4.1. Het OSI-model
Het open netwerkmodel, OSI (Open Systems Interconnection Reference Model) genaamd, gedefinieerd door de ISO (International Standards Organisation), beschrijft een ideaal netwerk waarin de communicatie tussen computers kan worden weergegeven door een model met zeven lagen:
![]() |
Elke laag ontvangt diensten van de onderliggende laag en biedt haar eigen diensten aan de bovenliggende laag aan. Stel dat twee applicaties op verschillende machines A en B met elkaar willen communiceren: dat doen ze op het niveau van de Application-laag. Ze hoeven niet alle details van de werking van het netwerk te kennen: elke toepassing geeft de informatie die ze wil verzenden door aan de onderliggende laag: de laag Présentation. De toepassing hoeft dus alleen de regels voor de koppeling met de laag Présentation te kennen. Zodra de informatie zich in de laag Présentation bevindt, wordt deze volgens andere regels doorgegeven aan de laag Session en zo verder, totdat de informatie op het fysieke medium terechtkomt en fysiek naar de bestemmingsmachine wordt verzonden. Daar ondergaat de informatie het omgekeerde proces van wat er op de verzendende machine is gebeurd.
Op elke laag stuurt het verzendproces, dat verantwoordelijk is voor het verzenden van de informatie, deze naar een ontvangstproces op de andere machine die tot dezelfde laag behoort. Dit gebeurt volgens bepaalde regels die het protocol van de laag worden genoemd. We krijgen dus het volgende uiteindelijke communicatieschema:
![]() |
De rol van de verschillende lagen is als volgt:
Fysieke laag | Zorgt voor de overdracht van bits via een fysiek medium. In deze laag bevinden zich eindapparatuur voor gegevensverwerking (E.T.T.D.), zoals terminals of computers, evenals apparatuur voor het afsluiten van datacircuits (E.T.C.D.), zoals modulators/demodulators, multiplexers en concentrators. De aandachtspunten op dit niveau zijn:
|
Dataverbinding | Verbergt de fysieke kenmerken van de fysieke laag. Detecteert en corrigeert transmissiefouten. |
Netwerk | Beheert het pad dat de via het netwerk verzonden informatie moet volgen. Dit wordt de routage genoemd: het bepalen van de route die informatie moet volgen om bij de ontvanger aan te komen. |
Transport | Maakt communicatie tussen twee applicaties mogelijk, terwijl de voorgaande lagen alleen communicatie tussen machines toelieten. Een dienst die door deze laag wordt geleverd, kan multiplexing zijn: de transportlaag kan één en dezelfde netwerkverbinding (van machine naar machine) gebruiken om informatie van meerdere applicaties te verzenden. |
Sessie | In deze laag vinden we diensten waarmee een applicatie een werksessie op een externe machine kan openen en in stand houden. |
Presentatie | Deze laag heeft tot doel de weergave van gegevens op de verschillende machines te uniformiseren. Zo worden gegevens afkomstig van machine A door de Présentation-laag van machine A in een standaardformaat 'verpakt' voordat ze over het netwerk worden verzonden. Zodra de gegevens de laag Présentation van de ontvangende machine B bereiken – die ze dankzij hun standaardformaat herkent – worden ze op een andere manier verpakt, zodat de applicatie op machine B ze kan herkennen. |
Toepassing | Op dit niveau bevinden zich de toepassingen die doorgaans dicht bij de gebruiker staan, zoals e-mail of bestandsoverdracht. |
2.4.2. Het model TCP/IP
Het model OSI is een ideaal model. De reeks protocollen TCP/IP komt hier dicht bij in de volgende vorm:
![]() |
- de netwerkinterface (de netwerkkaart van de computer) vervult de functies van de lagen 1 en 2 van het model OSI
- de laag IP (Internet Protocol) vervult de functies van laag 3 (netwerk)
- De laag TCP (Transfer Control Protocol) of UDP (User Datagram Protocol) vervult de functies van laag 4 (transport). Het protocol TCP zorgt ervoor dat de gegevenspakketten die door de computers worden uitgewisseld, daadwerkelijk op hun bestemming aankomen. Als dat niet het geval is, stuurt het de verdwaalde pakketten terug. Het protocol UDP doet dit niet en het is dan aan de applicatieontwikkelaar om dit te doen. Daarom wordt op het internet, dat geen 100% betrouwbaar netwerk is, het protocol TCP het meest gebruikt. We spreken dan van een TCP-IP-netwerk.
- De applicatielaag omvat de functies van de niveaus 5 tot en met 7 van het OSI-model.
Webapplicaties bevinden zich in de Application-laag en zijn dus gebaseerd op de TCP-IP-protocollen. De Application-lagen van de client- en servercomputers wisselen berichten uit die aan de lagen 1 tot en met 4 van het model worden toevertrouwd om naar de bestemming te worden doorgestuurd. Om elkaar te kunnen begrijpen, moeten de applicatielagen van beide computers dezelfde taal of hetzelfde protocol „spreken”. Dat van de webapplicaties heet HTTP (HyperText Transfer Protocol). Het is een tekstprotocol, c.a.d, waarbij de machines tekstregels over het netwerk uitwisselen om elkaar te begrijpen. Deze uitwisselingen zijn gestandaardiseerd, d.w.z. dat de client over een aantal berichten beschikt om de server precies aan te geven wat hij wil, en dat de server eveneens over een aantal berichten beschikt om de client zijn antwoord te geven. Deze berichtenuitwisseling heeft de volgende vorm:

Client --> Server
Wanneer de client een verzoek indient bij de webserver, stuurt hij
- tekstregels in het formaat HTTP om aan te geven wat hij wil;
- een lege regel;
- eventueel een document.
Server --> Client
Wanneer de server zijn antwoord naar de client stuurt, verzendt hij
- tekstregels in het formaat HTTP om aan te geven wat hij verstuurt;
- een lege regel;
- eventueel een document.
De uitwisselingen hebben dus in beide richtingen dezelfde vorm. In beide gevallen kan er een document worden verzonden, ook al komt het zelden voor dat een client een document naar de server stuurt. Maar het protocol HTTP voorziet hierin. Hierdoor kunnen bijvoorbeeld abonnees van een internetprovider diverse documenten uploaden naar hun persoonlijke website die bij deze provider wordt gehost. De uitgewisselde documenten kunnen van welke aard dan ook zijn. Laten we eens kijken naar een browser die een webpagina met afbeeldingen opvraagt:
- de browser maakt verbinding met de webserver en vraagt de gewenste pagina op. De opgevraagde bronnen worden op unieke wijze aangeduid door middel van URL (Uniform Resource Locator). De browser verstuurt alleen HTTP-headers en geen documenten.
- De server antwoordt. Hij stuurt eerst HTTP-headers waarin wordt aangegeven welk type antwoord hij verstuurt. Dit kan een foutmelding zijn als de opgevraagde pagina niet bestaat. Als de pagina wel bestaat, geeft de server in de HTTP-headers van zijn antwoord aan dat hij na deze headers een HTML-document (HyperText Markup Language) zal verzenden. Dit document bestaat uit een reeks tekstregels in het HTML-formaat. Een HTML-tekst bevat tags (markeringen) die de browser aanwijzingen geven over de manier waarop de tekst moet worden weergegeven.
- De client weet aan de hand van de HTTP-headers van de server dat hij een HTML-document zal ontvangen. Hij analyseert dit document en merkt wellicht op dat het verwijzingen naar afbeeldingen bevat. Deze afbeeldingen staan niet in het document HTML. Daarom doet hij een nieuw verzoek aan dezelfde webserver om de eerste afbeelding op te vragen die hij nodig heeft. Dit verzoek is identiek aan dat in stap 1, behalve dat de opgevraagde bron anders is. De server verwerkt dit verzoek door de gevraagde afbeelding naar de client te sturen. Deze keer geven de headers HTTP in het antwoord aan dat het verzonden document een afbeelding is en geen document HTML.
- De client haalt de verzonden afbeelding op. De stappen 3 en 4 worden herhaald totdat de client (meestal een browser) alle documenten heeft ontvangen die nodig zijn om de volledige pagina weer te geven.
2.4.3. Het protocol HTTP
Laten we het protocol HTTP aan de hand van voorbeelden bekijken. Wat wisselen een browser en een webserver uit?
De webservice of HTTP-service is een TCP-IP-service die doorgaans op poort 80 draait. Het kan ook op een andere poort draaien. In dat geval zou de clientbrowser deze poort moeten specificeren in het URL-verzoek dat hij verstuurt. Een URL heeft de volgende algemene vorm:
protocol://[:port]-server/pad/info
waarbij
protocol | http voor de webservice. Een browser kan ook als client fungeren voor ftp-, news-, telnet- en andere diensten. |
machine | naam van de machine waarop de webservice draait |
poort | poort van de webservice. Als dit 80 is, kan het poortnummer worden weggelaten. Dit is het meest voorkomende geval |
pad | pad naar de opgevraagde bron |
info | aanvullende informatie die aan de server wordt verstrekt om het verzoek van de klant te verduidelijken |
Wat doet een browser wanneer een gebruiker vraagt om het laden van een URL?
- hij opent een verbinding TCP-IP met de machine en de poort die zijn aangegeven in het gedeelte machine[:port] van de URL. Het openen van een TCP-IP-verbinding betekent dat er een „communicatiekanaal” tussen twee machines wordt gecreëerd. Zodra dit kanaal is gecreëerd, verloopt alle informatie-uitwisseling tussen de twee machines hierdoorheen. Het aanmaken van deze verbinding TCP-IP houdt nog niet het webprotocol HTTP in.
- Zodra de TCP-IP-verbinding is aangemaakt, zal de client zijn verzoek naar de webserver sturen door tekstregels (commando’s) in het HTTP-formaat te verzenden. Hij zal het pad/informatiegedeelte van de URL naar de server sturen
- De server zal op dezelfde manier en via dezelfde verbinding antwoorden
- een van beide partijen besluit de verbinding te verbreken. Dit hangt af van het gebruikte protocol HTTP. Bij het protocol HTTP 1.0 sluit de server de verbinding na elk van zijn antwoorden. Dit dwingt een client die meerdere verzoeken moet doen om de verschillende documenten te verkrijgen waaruit een webpagina bestaat, om bij elk verzoek een nieuwe verbinding te openen, wat kosten met zich meebrengt. Met het protocol HTTP/1.1 kan de client de server opdragen de verbinding open te houden totdat hij aangeeft deze te sluiten. Hij kan dus alle documenten van een webpagina met één enkele verbinding ophalen en de verbinding zelf sluiten zodra het laatste document is ontvangen. De server detecteert deze sluiting en sluit de verbinding eveneens.
Om de communicatie tussen een client en een webserver te bekijken, gebruiken we de extensie [Advanced Rest Client] voor de Chrome-browser die we in paragraaf 9.6 hebben geïnstalleerd. We bevinden ons in de volgende situatie:

De webserver kan willekeurig zijn. We willen hier nagaan welke gegevensuitwisseling er tussen de browser en de webserver zal plaatsvinden. Eerder hebben we de volgende statische pagina HTML aangemaakt:
<!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>
die we in een browser bekijken:
![]() |
We zien dat de opgevraagde URL: [http://localhost:9000/intro/exemple-01.html] is. De server van de webservice is dus localhost (=lokale server) en poort 9000. Laten we de applicatie [Advanced Rest Client] gebruiken om dezelfde URL op te vragen:
![]() |
- in [1] starten we de applicatie (in het tabblad [Applications] van een nieuw Chrome-tabblad);
- in [2] selecteer je de optie [Request];
- in [3], geef je de server op die je wilt opvragen: http://localhost:9000;
- in [4] geef je de gevraagde URL op: /intro/exemple-01.html;
- in [5] worden eventuele parameters aan de URL toegevoegd. Hier zijn er geen;
- in [6] specificeren we het commando HTTP dat voor de aanvraag wordt gebruikt, in dit geval GET.
Dit levert de volgende query op:
![]() |
De aldus voorbereide aanvraag [7] wordt via [8] naar de server verzonden. Het verkregen antwoord is dan als volgt:
![]() |
We hebben hierboven al vermeld dat de communicatie tussen client en server de volgende vorm heeft:

- in [1] zien we de headers HTTP die door de browser in zijn verzoek zijn verzonden. Er was geen document om te verzenden;
- in [2] zien we de headers HTTP die door de server als antwoord zijn verzonden. In [3] zien we het document dat hij heeft verzonden.
In [3] herkennen we de statische pagina HTML die we op de webserver hebben geplaatst.
Laten we het verzoek HTTP van de browser eens bekijken:
- regel 1 is niet door de applicatie weergegeven;
- regel 6: de browser identificeert zich met de header [User-Agent];
- regel 7: de browser geeft aan dat hij een tekstdocument (text/plain) in het formaat UTF-8 naar de server verstuurt. In feite heeft de browser hier geen document verstuurd;
- regel 8: de browser geeft aan dat hij elk type document als antwoord accepteert;
- regel 9: de browser specificeert de geaccepteerde documentformaten;
- regel 10: de browser specificeert de gewenste talen in volgorde van voorkeur.
De server heeft hierop gereageerd door de volgende HTTP-headers te verzenden:
- regel 1: is niet weergegeven door de applicatie;
- regel 2: de server identificeert zich, in dit geval een Apache-Coyote-server;
- regel 3: de datum waarop het verzonden document voor het laatst is gewijzigd;
- regel 4: het type document dat door de server is verzonden. In dit geval een HTML-document;
- regel 5: de grootte in bytes van het verzonden document HTML.
- regel 6: datum en tijdstip van het antwoord;
2.4.4. Conclusie
Aan de hand van enkele voorbeelden hebben we de structuur van het verzoek van een webclient en die van het antwoord van de webserver hierop onderzocht. De communicatie verloopt via het protocol HTTP, een reeks tekstcommando’s die door beide partijen worden uitgewisseld. Het verzoek van de client en het antwoord van de server hebben beide de volgende structuur:

De twee gebruikelijke commando’s om een bron op te vragen zijn GET en POST. Het commando GET gaat niet vergezeld van een document. Het commando POST gaat daarentegen wel vergezeld van een document, dat meestal een tekenreeks is die alle in een formulier ingevoerde waarden bevat. Met het commando HEAD kunnen alleen de kopteksten HTTP worden opgevraagd; dit commando gaat niet vergezeld van een document.
Op verzoek van een client stuurt de server een antwoord met dezelfde structuur. De opgevraagde bron wordt verzonden in het gedeelte [Document], tenzij het commando van de client HEAD was; in dat geval worden alleen de headers HTTP verzonden.
2.5. De basisprincipes van de taal HTML
Een webbrowser kan verschillende documenten weergeven, waarvan het meest gangbare het HTML-document is (HyperText Markup Language). Dit is een tekst die is opgemaakt met tags in de vorm <balise>texte</balise>. Zo zal de tekst <B>important</B> de belangrijke tekst vetgedrukt weergeven. Er bestaan ook op zichzelf staande tags, zoals de tag <hr/>, die een horizontale lijn weergeeft. We zullen niet ingaan op de tags die in een HTML-tekst kunnen voorkomen. Er bestaat veel WYSIWYG-software waarmee je een webpagina kunt bouwen zonder ook maar één regel HTML-code te schrijven. Deze tools genereren automatisch de HTML-code van een lay-out die met de muis en vooraf gedefinieerde besturingselementen is gemaakt. Zo kun je (met de muis) een tabel in de pagina invoegen en vervolgens de door de software gegenereerde HTML-code bekijken om te ontdekken welke tags je moet gebruiken om een tabel in een webpagina te definiëren. Eenvoudiger kan het niet. Bovendien is kennis van de taal HTML onmisbaar, aangezien dynamische webapplicaties zelf de HTML-code moeten genereren die naar de webclients moet worden verzonden. Deze code wordt programmatisch gegenereerd en men moet natuurlijk weten wat er moet worden gegenereerd, zodat de client de gewenste webpagina te zien krijgt.
Kortom, het is helemaal niet nodig om de volledige taal HTML te beheersen om met webprogrammeren te beginnen. Deze kennis is echter wel noodzakelijk en kan worden opgedaan door het gebruik van WYSIWYG-software voor het bouwen van webpagina’s, zoals DreamWeaver en tientallen andere. Een andere manier om de fijne kneepjes van de taal HTML te ontdekken, is door op het web te surfen en de broncode te bekijken van pagina’s die interessante kenmerken vertonen die je nog niet kent.
2.5.1. Een voorbeeld
Laten we eens kijken naar het volgende voorbeeld, dat enkele elementen laat zien die in een webdocument kunnen voorkomen, zoals:
- een tabel;
- een afbeelding;
- een link.
![]() | ![]() |
Een HTML-document heeft de volgende algemene vorm:
<html>
<head>
<title>Een titel</title>
...
</head>
<body-attributen>
...
</body>
</html>
Het gehele document wordt omgeven door de tags <html>...</html>. Het bestaat uit twee delen:
- <head>...</head>: dit is het niet-weergegeven gedeelte van het document. Het geeft informatie aan de browser die het document gaat weergeven. Hierin staat vaak de tag <title>...</title>, die de tekst vastlegt die in de titelbalk van de browser wordt weergegeven. Er kunnen ook andere tags in staan, met name tags die de trefwoorden van het document definiëren, trefwoorden die vervolgens door zoekmachines worden gebruikt. In dit gedeelte kunnen ook scripts voorkomen, meestal geschreven in JavaScript of VBScript, die door de browser worden uitgevoerd.
- <body attributen>...</body>: dit is het gedeelte dat door de browser wordt weergegeven. De tags HTML in dit gedeelte geven aan de browser aan hoe het document er visueel „uit moet zien”. Elke browser interpreteert deze tags op zijn eigen manier. Twee browsers kunnen hetzelfde webdocument dus op verschillende manieren weergeven. Dit is doorgaans een van de hoofdbrekers voor webontwerpers.
De code HTML van ons voorbeelddocument is als volgt:
<!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>
Element | tags en voorbeelden HTML |
titel van het document | <title>tags</title> (regel 5) de tekst balises verschijnt in de titelbalk van de browser die het document weergeeft |
horizontale balk | <hr/>: geeft een horizontale streep weer (regel 10) |
tabel | <table attributen>....</table>: om de tabel te definiëren (regels 11, 31) <thead>...</thead>: om de kolomkoppen te definiëren (regels 12, 18) <tbody>...</tbody>: om de inhoud van de tabel te definiëren (regel 19, 30) <tr attributen>...</tr>: om een rij te definiëren (regels 20, 24) <td attributen>...</td>: om een cel te definiëren (regel 21) voorbeelden: <table border="1">...</table>: het attribuut border bepaalt de dikte van de rand van de tabel <td style="width: 150px; text-align: center;">cel(1,2)</td>: definieert een cel waarvan de inhoud cel(1,2) is. Deze inhoud wordt horizontaal gecentreerd (text-align: center). De cel heeft een breedte van 150 pixels (width: 150px) |
afbeelding | <img border="0" src="/images/cerisier.jpg"/> (regel 36): definieert een afbeelding zonder rand (border="0") waarvan het bronbestand zich op de webserver bevindt onder /images/cerisier.jpg (src="images/cerisier.jpg"). Deze link staat in een webdocument dat is gegenereerd met de URL http://localhost:port/intro/exemple-04.html. De browser zal dus de URL http://localhost:port/intro/images/cerisier.jpg opvragen om de hier genoemde afbeelding te verkrijgen. |
link | <a href="http://istia.univ-angers.fr">hier</a> (regel 40): zorgt ervoor dat de tekst ici als link fungeert naar de pagina URL http://istia.univ-angers.fr. |
paginavoet | <body style="height:400px;width:400px;background-image:url(images/standard.jpg)"> (regel 8): geeft aan dat de afbeelding die als achtergrond voor de pagina moet dienen, zich op de URL [images/standard.jpg] van de webserver bevindt. In het kader van ons voorbeeld zal de browser het bestand URL http://localhost:port/intro/images/standard.jpg opvragen om deze achtergrondafbeelding op te halen. Bovendien wordt de hoofdtekst van het document weergegeven in een rechthoek met een hoogte van 400 pixels en een breedte van 400 pixels. |
Uit dit eenvoudige voorbeeld blijkt dat de browser, om het volledige document op te bouwen, drie verzoeken naar de server moet sturen:
- http://localhost:port/intro/exemple-04.html om de bron HTML van het document op te halen
- http://localhost:port/intro/images/cerisier.jpg om de afbeelding cerisier.jpg op te halen
- http://localhost:port/intro/images/standard.jpg om de achtergrondafbeelding standard.jpg op te halen
2.5.2. Een formulier HTML
Het volgende voorbeeld toont een formulier:
![]() | ![]() |
De code HTML die deze weergave genereert, is als volgt:
<!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>
De koppeling tussen de visuele weergave en de HTML-tag is als volgt:
Controle | tag HTML |
formulier | <form method="post" action="..."> |
invoerveld | <input type="text" name="txtSaisie" size="20" value="een paar woorden" /> |
verborgen invoerveld | <input type="password" name="txtMdp" size="20" value="unMotDePasse" /> |
invoerveld met meerdere regels | <textarea rows="2" name="areaSaisie" cols="20"> regel1 regel 2 regel 3 </textarea> |
keuzerondjes | <input type="radio" value="Ja" name="R1" />Ja <input type="radio" name="R1" value="nee" checked="checked" />Nee |
selectievakjes | <input type="checkbox" name="C1" value="één" />1 <input type="checkbox" name="C2" value="twee" checked="checked" />2 <input type="checkbox" name="C3" value="drie" />3 |
Keuzelijst | <select size="1" name="cmbValeurs"> <option value="1">keuze1</option> <option selected="selected" value="2">keuze 2</option> <option value="3">keuze 3</option> </select> |
lijst met één selectie | <select size="3" name="lst1"> <option selected="selected" value="1">lijst1</option> <option value="2">lijst2</option> <option value="3">lijst3</option> <option value="4">lijst4</option> <option value="5">lijst5</option> </select> |
lijst met meerdere selecties | <select size="3" name="lst2" multiple="multiple"> <option value="1">lijst1</option> <option value="2">lijst2</option> <option selected="selected" value="3">lijst3</option> <option value="4">lijst4</option> <option value="5">lijst5</option> </select> |
verzendknop | <input type="submit" value="Verzenden" name="cmdRenvoyer" /> |
reset-knop | <input type="reset" value="Terugzetten" name="cmdRétablir" /> |
knop van het type button | <input type="button" value="Wissen" name="cmdEffacer" onclick="effacer()" /> |
Laten we deze verschillende tags eens bekijken:
2.5.2.1. De formulier-
formulier | |
tag HTML | <form name="..." method="..." action="...">...</form> |
attributen | name="frmexemple": naam van het formulier method="..." : methode die door de browser wordt gebruikt om de in het formulier verzamelde waarden naar de webserver te verzenden action="..." : URL waarnaar de in het formulier verzamelde waarden worden verzonden. Een webformulier wordt omsloten door de <form>...</form>-tags. Het formulier kan een naam hebben (name="xx"). Dit geldt voor alle besturingselementen die in een formulier voorkomen. Het doel van een formulier is om informatie te verzamelen die de gebruiker via het toetsenbord of de muis invoert, en deze naar een URL van een webserver te verzenden. Welke? Die waarnaar wordt verwezen in het attribuut action="URL". Als dit attribuut ontbreekt, wordt de informatie verzonden naar de URL van het document waarin het formulier zich bevindt. Een webclient kan twee verschillende methoden gebruiken, namelijk POST en GET, om gegevens naar een webserver te verzenden. Het attribuut method="méthode", waarbij method gelijk is aan GET of POST, van de tag <form> geeft aan de browser aan welke methode moet worden gebruikt om de in het formulier verzamelde informatie te verzenden naar de URL die is opgegeven door het attribuut action="URL". Wanneer het attribuut method niet is opgegeven, wordt standaard de methode GET gebruikt. |
2.5.2.2. De tekstinvoervelden
invoerveld | <input type="text" name="txtSaisie" size="20" value="een paar woorden" /> <input type="password" name="txtMdp" size="20" value="unMotDePasse" /> |
![]() |
tag HTML | <input type="..." name="..." size=".." value=".."/> De input-tag bestaat voor verschillende besturingselementen. Het is het attribuut type waarmee deze verschillende besturingselementen van elkaar kunnen worden onderscheiden. |
attributen | type="text": geeft aan dat het een invoerveld is type="password": de tekens in het invoerveld worden vervangen door *-tekens. Dit is het enige verschil met het normale invoerveld. Dit type besturingselement is geschikt voor het invoeren van wachtwoorden. size="20": aantal zichtbare tekens in het veld – dit belet niet dat er meer tekens worden ingevoerd name="txtSaisie": naam van het invoerveld value="een paar woorden": tekst die in het invoerveld wordt weergegeven. |
2.5.2.3. Invoervelden met meerdere regels
invoerveld met meerdere regels | <textarea rows="2" name="areaSaisie" cols="20"> regel1 regel 2 regel3 </textarea> |
![]() |
tag HTML | <textarea ...>tekst</textarea> geeft een invoerveld voor meerdere regels weer met aanvankelijk tekst erin |
attributen | rows="2": aantal regels cols="'20" : aantal kolommen name="areaSaisie": naam van het besturingselement |
2.5.2.4. De keuzerondjes
keuzerondjes | <input type="radio" value="Ja" name="R1" />Ja <input type="radio" name="R1" value="nee" checked="checked" />Nee |
tag HTML | <input type="radio" attribuut2="waarde2" ..../>tekst toont een keuzerondje met tekst ernaast. |
attributen | name="radio": naam van het besturingselement. Keuzerondjes met dezelfde naam vormen een groep die elkaar uitsluiten: er kan slechts één worden aangevinkt. value="waarde": waarde die aan de keuzeknop wordt toegewezen. Deze waarde mag niet worden verward met de tekst die naast de keuzeknop wordt weergegeven. Deze tekst is uitsluitend bedoeld voor weergave. checked="checked": als dit trefwoord aanwezig is, is de keuzeknop aangevinkt, anders niet. |
2.5.2.5. Selectievakjes
selectievakjes | <input type="checkbox" name="C1" value="één" />1 <input type="checkbox" name="C2" value="twee" checked="checked" />2 <input type="checkbox" name="C3" value="drie" />3 |
tag HTML | <input type="checkbox" attribuut2="waarde2" ....>tekst geeft een selectievakje weer met tekst ernaast. |
attributen | name="C1": naam van het besturingselement. Selectievakjes kunnen al dan niet dezelfde naam hebben. Selectievakjes met dezelfde naam vormen een groep van aan elkaar gekoppelde selectievakjes. value="waarde": waarde die aan het selectievakje is toegewezen. Deze waarde mag niet worden verward met de tekst die naast het selectievakje wordt weergegeven. Deze tekst is uitsluitend bedoeld voor weergave. checked="checked": als dit trefwoord aanwezig is, is het selectievakje aangevinkt, anders niet. |
2.5.2.6. De vervolgkeuzelijst (combo)
Combo | <select size="1" name="cmbValeurs"> <option value="1">keuze1</option> <option selected="selected" value="2">keuze2</option> <option value="3">keuze 3</option> </select> |
tag HTML | <select size=".." name=".."> <option [selected="selected"] value=”v”>...</option> ... </select> geeft de teksten tussen de tags <option>...</option> |
attributen | name="cmbValeurs": naam van het besturingselement. size="1": aantal zichtbare lijstitems. size="1" maakt van de lijst het equivalent van een combobox. selected="selected": als dit trefwoord aanwezig is voor een lijstitem, wordt dit item geselecteerd weergegeven in de lijst. In ons voorbeeld hierboven verschijnt het lijstitem choix2 als het geselecteerde item van de combobox wanneer deze voor het eerst wordt weergegeven. value=”v”: als het element door de gebruiker wordt geselecteerd, wordt deze waarde [v] naar de server verzonden. Als dit attribuut ontbreekt, wordt de weergegeven en geselecteerde tekst naar de server verzonden. |
2.5.2.7. Lijst met één selectie
lijst met één selectie | <select size="3" name="lst1"> <option selected="selected" value="1">lijst1</option> <option value="2">lijst2</option> <option value="3">lijst3</option> <option value="4">lijst4</option> <option value="5">lijst5</option> </select> |
![]() |
tag HTML | <select size=".." name=".."> <option [selected="selected"]>...</option> ... </select> geeft de teksten tussen de tags <option>...</option> |
attributen | dezelfde als voor de vervolgkeuzelijst die slechts één item weergeeft. Dit besturingselement verschilt alleen van de vorige vervolgkeuzelijst door het attribuut size>1. |
2.5.2.8. Lijst met meerdere selecties
lijst met enkele selectie | <select size="3" name="lst2" multiple="multiple"> <option value="1" selected="selected">lijst1</option> <option value="2">lijst2</option> <option selected="selected" value="3">lijst3</option> <option value="4">lijst4</option> <option value="5">lijst5</option> </select> |
![]() |
tag HTML | <select size=".." name=".." multiple="multiple"> <option [selected="selected"]>...</option> ... </select> geeft de teksten tussen de tags <option>...</option> |
attributen | multiple: hiermee kunnen meerdere items uit de lijst worden geselecteerd. In het bovenstaande voorbeeld zijn de items liste1 en liste3 beide geselecteerd. |
2.5.2.9. Knop van het type button
knop van het type button | <input type="button" value="Wissen" name="cmdEffacer" onclick="effacer()" /> |
tag HTML | <input type="button" value="..." name="..." onclick="effacer()" ..../> |
attributen | type="button": definieert een knop. Er zijn nog twee andere soorten knoppen: de typen submit en reset. value="Wissen": de tekst die op de knop wordt weergegeven onclick="functie()": hiermee kan een functie worden gedefinieerd die moet worden uitgevoerd wanneer de gebruiker op de knop klikt. Deze functie maakt deel uit van de scripts die in het weergegeven webdocument zijn gedefinieerd. De bovenstaande syntaxis is een javascript-syntaxis. Als de scripts in VBScript zijn geschreven, moet onclick="functie" zonder de haakjes worden geschreven. De syntaxis blijft hetzelfde als er parameters aan de functie moeten worden doorgegeven: onclick="functie(val1, val2,...)" In ons voorbeeld roept een klik op de knop Effacer de volgende JavaScript-functie effacer aan: <script type="text/javascript"> function effacer() { alert("U hebt op de knop Wissen geklikt"); } </script> De functie effacer geeft een bericht weer: ![]() |
2.5.2.10. Submit-knop
Submit-knop | <input type="submit" value="Verzenden" name="cmdRenvoyer" /> |
tag HTML | <input type="submit" value="Verzenden" name="cmdRenvoyer" /> |
attributen | type="submit": definieert de knop als een knop om de gegevens van het formulier naar de webserver te verzenden. Wanneer de gebruiker op deze knop klikt, verzendt de browser de gegevens van het formulier naar de URL die is gedefinieerd in het attribuut action van de tag <form>, volgens de methode die is gedefinieerd door het attribuut method van diezelfde tag. value="Verzenden": de tekst die op de knop wordt weergegeven |
2.5.2.11. Resetknop
Resetknop | <input type="reset" value="Herstellen" name="cmdRétablir" /> |
tag HTML | <input type="reset" value="Terugzetten" name="cmdRétablir"/> |
attributen | type="reset": definieert de knop als een knop om het formulier te resetten. Wanneer de gebruiker op deze knop klikt, zet de browser het formulier terug in de staat waarin het werd ontvangen. value="Resetten" : de tekst die op de knop wordt weergegeven |
2.5.2.12. Verborgen veld
verborgen veld | <input type="hidden" name="secret" value="uneValeur" /> |
tag HTML | <input type="hidden" name="..." value="..."/> |
attributen | type="hidden": geeft aan dat het een verborgen veld is. Een verborgen veld maakt deel uit van het formulier, maar wordt niet aan de gebruiker getoond. Als de gebruiker echter aan zijn browser zou vragen om de broncode weer te geven, zou hij de tag <input type="hidden" value="..."> zien en dus ook de waarde van het verborgen veld. value="eenWaarde": waarde van het verborgen veld. Wat is het nut van het verborgen veld? Hiermee kan de webserver informatie bijhouden tijdens de verzoeken van een klant. Laten we eens kijken naar een online winkelapplicatie. De klant koopt een eerste artikel art1 in een hoeveelheid van q1 op een eerste pagina van een catalogus en gaat vervolgens naar een nieuwe pagina van de catalogus. Om te onthouden dat de klant q1 artikelen art1 heeft gekocht, kan de server deze twee gegevens in een verborgen veld van het webformulier op de nieuwe pagina plaatsen. Op deze nieuwe pagina koopt de klant de artikelen q2 en art2. Wanneer de gegevens van dit tweede formulier naar de server worden verzonden (submit), ontvangt de server niet alleen de informatie (q2,art2) maar ook (q1,art1), die eveneens als verborgen veld deel uitmaakt van het formulier. De webserver plaatst vervolgens de gegevens (q1,art1) en (q2,art2) in een nieuw verborgen veld en verstuurt een nieuwe cataloguspagina. En zo verder. |
2.5.3. Verzending van formulierwaarden naar een webserver door een webclient
In de vorige studie hebben we gezegd dat de webclient over twee methoden beschikt om de waarden van een formulier dat hij heeft weergegeven naar een webserver te verzenden: de methoden GET en POST. Laten we aan de hand van een voorbeeld het verschil tussen beide methoden bekijken.
2.5.3.1. Methode GET
Laten we een eerste test uitvoeren, waarbij in de code HTML van het document de tag <form> als volgt is gedefinieerd:
<form method="get" action="doNothing">
![]() |
Wanneer de gebruiker op de knop [1] klikt, worden de in het formulier ingevoerde waarden verzonden naar de Spring-controller [2]. We hebben gezien dat de waarden van het formulier naar de URL en [doNothing] worden verzonden:
<form method="get" action="doNothing">
De actie [doNothing] is in de controller [MyController] [2] als volgt gedefinieerd:
// ----------------------- een feed leeg maken [Content-Length=0]
@RequestMapping(value = "/doNothing")
@ResponseBody
public void doNothing() {
}
- regel 1: de actie verwerkt de URL [/doNothing], dus in feite [/context/doNothing], waarbij [context] de context of naam van de webapplicatie is, hier [/intro];
- regel 3: de annotatie [@ResponseBody] geeft aan dat het resultaat van de geannoteerde methode rechtstreeks naar de client moet worden verzonden;
- regel 4: de methode retourneert niets. De client ontvangt dus een leeg antwoord van de server.
We willen alleen weten hoe de browser de ingevoerde waarden naar de webserver doorstuurt. Hiervoor gebruiken we een debug-tool die beschikbaar is in Chrome. We activeren deze door op CTRL-Shift-I (hoofdletter) [3] te drukken:
![]() |
Aangezien we geïnteresseerd zijn in de netwerkcommunicatie tussen de browser en de webserver, openen we hierboven het tabblad [Network] en klikken we vervolgens op de knop [Envoyer] in het formulier. Dit is een knop van het type [submit] binnen een tag [form]. De browser reageert op de klik door de URL [/intro/doNothing] op te vragen die is opgegeven in het attribuut [action] van de tag [form], met de methode GET die is opgegeven in het attribuut [method]. We krijgen dan de volgende informatie:
![]() |
De bovenstaande schermafbeelding toont de URL die door de browser wordt opgevraagd nadat op de knop [envoyer] is geklikt. De browser vraagt inderdaad de verwachte URL ([/intro/doNothing]), maar voegt daarachter informatie toe die bestaat uit de waarden die in het formulier zijn ingevuld. Voor meer informatie klikken we op de bovenstaande link:
![]() |
Boven [1, 2] zien we de headers HTTP die door de browser zijn verzonden. Deze zijn hier opgemaakt. Om de onbewerkte tekst van deze headers te bekijken, volgen we de link [view source] [3, 4]. De volledige tekst luidt als volgt:
We zien hier elementen terug die we eerder al zijn tegengekomen. Andere verschijnen voor het eerst:
Connection: keep-alive | de client vraagt de server om de verbinding niet te verbreken na het antwoord. Hierdoor kan hij dezelfde verbinding gebruiken voor een volgend verzoek. De verbinding blijft niet onbeperkt openstaan. De server verbreekt deze na een te lange periode van inactiviteit. |
Referer | de URL die in de browser werd weergegeven toen het nieuwe verzoek werd gedaan. |
De nieuwe regel is regel 1 in de informatie die volgt op de URL. We zien dat de keuzes die in het formulier zijn gemaakt, terug te vinden zijn in de URL. De waarden die de gebruiker in het formulier heeft ingevoerd, zijn doorgegeven in de opdracht GET URL?param1=waarde1¶m2=waarde2&... HTTP/1.1, waarbij de parami de namen (attribuut name) van de besturingselementen van het webformulier zijn en valeuri de waarden die daaraan zijn gekoppeld. Hieronder vindt u een tabel met drie kolommen:
- kolom 1: bevat de definitie van een besturingselement HTML uit het voorbeeld;
- kolom 2: toont hoe dit besturingselement in een browser wordt weergegeven;
- kolom 3: toont de waarde die door de browser naar de server wordt verzonden voor het besturingselement uit kolom 1, in de vorm zoals deze voorkomt in de GET-verzoek in het voorbeeld.
besturingselement HTML | weergave | teruggestuurde waarde(n) |
<input type="radio" value="Ja" name="R1"/>Ja <input type="radio" name="R1" value="nee" checked="checked"/>Nee | R1=Ja - de waarde van het attribuut value van de door de gebruiker aangevinkte keuzeknop. | |
<input type="checkbox" name="C1" value="één"/>1 <input type="checkbox" name="C2" value="twee" checked="checked"/>2 <input type="checkbox" name="C3" value="drie"/>3 | C1=één C2=twee - waarden van de attributen value van de door de gebruiker aangevinkte selectievakjes | |
<input type="text" name="txtSaisie" size="20" value="enkele woorden"/> | txtSaisie=programmering+Web - tekst die door de gebruiker in het invoerveld is getypt. De spaties zijn vervangen door het teken + | |
<input type="password" name="txtMdp" size="20" value="unMotDePasse"/> | txtMdp=ditisgeheim - tekst die door de gebruiker in het invoerveld is getypt | |
<textarea rows="2" name="areaSaisie" cols="20"> regel1 regel2 regel3 </textarea> | invoergebied=de+basisprincipes+van+de%0D%0A webprogrammering+ - tekst die door de gebruiker in het invoerveld is getypt. %OD%OA is het teken voor het einde van de regel. De spaties zijn vervangen door het teken + | |
<select size="1" name="cmbValeurs"> <option value='1'>keuze1</option> <option selected="selected" value='2'>keuze2</option> <option value='3'>keuze3</option> </select> | cmbWaarden=3 - attribuut [value] van het door de gebruiker geselecteerde element | |
<select size="3" name="lst1"> <option selected="selected" value='1'>lijst1</option> <option value='2'>lijst2</option> <option value='3'>lijst3</option> <option value='4'>lijst4</option> <option value='5'>lijst5</option> </select> | ![]() | lst1=3 - attribuut [value] van het door de gebruiker geselecteerde element |
<select size="3" name="lst2" multiple="multiple"> <option selected="selected" value='1'>lijst1</option> <option value='2'>lijst2</option> <option selected="selected" value='3'>lijst3</option> <option value='4'>lijst4</option> <option value='5'>lijst5</option> </select> | lst2=1 lst2=3 - attributen [value] van de door de gebruiker geselecteerde elementen | |
<input type="submit" value="Verzenden" name="cmdRenvoyer"/> | cmdRenvoyer=Verzenden - naam en attribuut value van de knop waarmee de formuliergegevens naar de server zijn verzonden | |
<input type="hidden" name="secret" value="uneValeur"/> | secret=eenWaarde - attribuut value van het verborgen veld |
2.5.3.2. Methode POST
We passen het document HTML aan, zodat de browser nu de methode POST gebruikt om de formulierwaarden naar de webserver te verzenden:
<form method="post" action="doNothing">
We vullen het formulier in zoals bij de methode GET en verzenden de parameters naar de server met de knop [Envoyer]. Net zoals in de vorige paragraaf op pagina 62 hebben we in Chrome toegang tot de headers HTTP van het verzoek dat door de browser is verzonden:
Er verschijnen nieuwe elementen in het verzoek HTTP van de client:
POST URL HTTP/1.1 | de query GET is vervangen door een query POST. De parameters staan niet meer in deze eerste regel van de aanvraag. We zien dat ze nu (regel 15) na een lege regel achter de aanvraag HTTP staan. Hun codering is identiek aan die in de aanvraag GET. |
Content-Length | aantal "verzonden" tekens, c.a.d. Het aantal tekens dat de webserver moet lezen nadat hij de headers HTTP heeft ontvangen om het document op te halen dat de client naar hem verstuurt. Het document in kwestie is hier de lijst met waarden van het formulier. |
Content-type | geeft het type document aan dat de client na de headers HTTP zal verzenden. Het type [application/x-www-form-urlencoded] geeft aan dat het een document is dat formulierwaarden bevat. |
Er zijn twee methoden om gegevens naar een webserver te verzenden: GET en POST. Is de ene methode beter dan de andere? We hebben gezien dat als de waarden van een formulier door de browser werden verzonden met de methode GET, de browser in het veld Adresse de gevraagde URL weergeeft in de vorm URL?param1=val1¶m2=val2&.... Dit kan als een voordeel of als een nadeel worden gezien:
- een voordeel als men de gebruiker de mogelijkheid wil bieden om deze geconfigureerde URL in zijn favoriete links op te nemen;
- een nadeel als men niet wil dat de gebruiker toegang heeft tot bepaalde informatie in het formulier, zoals bijvoorbeeld verborgen velden.
Vanaf nu zullen we in onze formulieren vrijwel uitsluitend de methode POST gebruiken.
2.6. Conclusion
In dit hoofdstuk zijn verschillende basisconcepten van webontwikkeling behandeld:
- de communicatie tussen client en server via het protocol HTTP;
- het ontwerpen van een document met behulp van de taal HTML;
- het ontwerpen van invoerformulieren.
Aan de hand van een voorbeeld hebben we gezien hoe een client informatie naar de webserver kan verzenden. We hebben niet besproken hoe de server
- deze informatie kan ophalen;
- deze te verwerken;
- de klant een dynamisch antwoord sturen dat afhankelijk is van het resultaat van de verwerking.
Dit is het domein van webprogrammering, een onderwerp dat we in het volgende hoofdstuk behandelen met de presentatie van de Spring-technologie MVC.










































