1. Algemeen
De PDF van het document is beschikbaar |HIER|.
1.1. Doelstellingen
Hier willen we een ontwikkelingsmethode ontdekken die STRUTS heet. Jakarta Struts is een project van de Apache Software Foundation (www.apache.org) dat tot doel heeft een standaardframework te bieden voor de ontwikkeling van webapplicaties in Java volgens de zogenaamde MVC-architectuur (Model-View-Controller).
1.2. Het MVC-model
Het MVC-model streeft ernaar de presentatie-, verwerkings- en gegevenslaag van elkaar te scheiden. Een webapplicatie die aan dit model voldoet, zal als volgt zijn opgebouwd:
![]() |
Een dergelijke architectuur wordt een drielagige of 3-tier-architectuur genoemd:
- de gebruikersinterface is de V (de weergave)
- de applicatielogica is de C (de controller)
- de gegevensbronnen zijn de M (het model)
De gebruikersinterface is vaak een webbrowser, maar het kan ook een zelfstandige applicatie zijn die via het netwerk verzoeken HTTP naar de webservice stuurt en de resultaten die deze terugstuurt, opmaakt. De applicatielogica bestaat uit scripts die de verzoeken van de gebruiker verwerken. De gegevensbron is vaak een database, maar het kunnen ook eenvoudige platte bestanden zijn, een directory LDAP, een externe webservice, ... De ontwikkelaar doet er goed aan een grote onafhankelijkheid tussen deze drie entiteiten te handhaven, zodat als er één verandert, de andere twee niet of nauwelijks hoeven te veranderen.
Wanneer men dit model wil toepassen met servlets en JSP-pagina’s, ontstaat de volgende architectuur:
![]() |
In het blok [Logique Applicative] onderscheiden we
- de servlet, die de toegangspoort tot de applicatie vormt en ook wel controller wordt genoemd
- het blok [Classes métier], dat de Java-klassen bevat die nodig zijn voor de logica van de applicatie.
- het blok [Classes d'accès aux données], dat de Java-klassen bevat die nodig zijn om de gegevens te verkrijgen die de servlet nodig heeft, vaak persistente gegevens (BD, bestanden, service WEB, ...)
- het blok met pagina's JSP dat de weergaven van de applicatie vormt.
1.3. Een ontwikkelingsaanpak MVC met behulp van servlets en pagina’s JSP
We hebben een aanpak gedefinieerd voor de ontwikkeling van Java-webapplicaties die voldoet aan het voorgaande model MVC. We herhalen deze hier.
- We beginnen met het definiëren van alle weergaven van de applicatie. Dit zijn de webpagina’s die aan de gebruiker worden getoond. We plaatsen ons dus in het perspectief van de gebruiker om de weergaven te ontwerpen. Er worden drie soorten weergaven onderscheiden:
- het invoerformulier, dat bedoeld is om informatie van de gebruiker te verkrijgen. Dit formulier beschikt doorgaans over een knop om de ingevoerde informatie naar de server te verzenden.
- de responspagina, die uitsluitend dient om informatie aan de gebruiker te verstrekken. Deze bevat vaak een link waarmee de gebruiker de applicatie kan voortzetten op een andere pagina.
- de gemengde pagina: de servlet heeft een pagina met door haar gegenereerde informatie naar de client verzonden. Diezelfde pagina zal door de client worden gebruikt om andere informatie aan de servlet te verstrekken.
- Elke weergave leidt tot een pagina JSP. Voor elk van deze pagina’s:
- bepalen we hoe de pagina eruitziet
- bepalen we welke delen ervan dynamisch zijn:
- de informatie voor de gebruiker die door de servlet als parameters aan de weergave JSP moet worden verstrekt
- de invoergegevens die ter verwerking naar de servlet moeten worden verzonden. Deze moeten deel uitmaken van een formulier HTML.
- We kunnen de invoer en uitvoer van elke weergave schematisch weergeven
![]() |
- De invoer bestaat uit de gegevens die de servlet aan de pagina JSP moet leveren, hetzij in de verzoek (request), hetzij in de sessie (session).
- De uitgangen zijn de gegevens die de pagina JSP aan de servlet moet leveren. Ze maken deel uit van een formulier HTML en de servlet haalt ze op via een bewerking van het type request.getparameter(...).
- We zullen de Java/JSP-code voor elke weergave schrijven. Deze zal meestal de volgende vorm hebben:
<%@ page ... %> // meest gebruikte klasse-importen
<%!
// instantievariabelen van de pagina JSP (=globale variabelen)
// alleen nodig als de pagina JSP methoden heeft die variabelen delen (zeldzaam)
...
%>
<%
// ophalen van gegevens die door de servlet zijn verzonden
// hetzij in het verzoek (request), hetzij in de sessie (session)
...
%>
<html>
...
// hier wordt getracht de Java-code te minimaliseren
</html>
- Vervolgens kunnen we overgaan tot de eerste tests. De hieronder beschreven implementatiemethode is specifiek voor de Tomcat-server:
- de applicatiecontext moet worden aangemaakt in het Tomcat-bestand server.xml. We kunnen beginnen met het testen van deze context. Laten we deze context C noemen en de bijbehorende map DC. We maken een statisch bestand test.html aan en plaatsen dit in de map DC. Nadat we Tomcat hebben gestart, roepen we met een browser de pagina URL http://localhost:8080/DC/test.html op.
- Elke pagina JSP kan worden getest. Als een pagina JSP de naam formulaire.jsp heeft, dan vragen we met een browser de pagina URL http://localhost:8080/DC/formulaire.jsp op. De pagina JSP verwacht waarden van de servlet die haar aanroept. Omdat we deze hier rechtstreeks aanroepen, ontvangt de servlet de verwachte parameters niet. Om de tests toch mogelijk te maken, initialiseren we de verwachte parameters zelf in de pagina JSP met behulp van constanten. Met deze eerste tests kunnen we controleren of de pagina's JSP syntactisch correct zijn.
- Vervolgens schrijven we de code van de servlet. Deze heeft twee duidelijk verschillende methoden:
- de methode init, die dient om:
- het ophalen van de configuratieparameters van de applicatie uit het bijbehorende bestand web.xml
- eventueel instanties aan te maken van businessklassen die de servlet later zal gebruiken
- het beheren van een eventuele lijst met initialisatiefouten die aan toekomstige gebruikers van de applicatie zal worden teruggestuurd. Dit foutbeheer kan zelfs zo ver gaan dat er een e-mail naar de beheerder van de applicatie wordt gestuurd om hem te waarschuwen voor een storing
- de methode doGet of doPost, afhankelijk van de manier waarop de servlet haar parameters van haar clients ontvangt. Als de servlet meerdere formulieren verwerkt, is het raadzaam dat elk formulier een stukje informatie verstuurt waarmee het uniek kan worden geïdentificeerd. Dit kan worden gedaan door middel van een verborgen veld in het formulier van het type <input type="hidden" name="action" value="...">. De servlet kan beginnen met het uitlezen van de waarde van deze parameter en vervolgens de verwerking van het verzoek delegeren aan een interne, privé-methode die verantwoordelijk is voor het verwerken van dit soort verzoeken.
- Probeer zo min mogelijk bedrijfslogica in de servlet te plaatsen. Daar is deze niet voor bedoeld. De servlet is een soort teamleider (controller) die verzoeken van zijn klanten (webklanten) ontvangt en deze laat uitvoeren door de meest geschikte personen (de bedrijfsklassen). Bij het schrijven van de servlet wordt de interface van de te schrijven businessklassen bepaald (constructors, methoden). Dit geldt als deze businessklassen nog moeten worden gebouwd. Als ze al bestaan, moet de servlet zich aanpassen aan de bestaande interface.
- De code van de servlet wordt gecompileerd.
- We schrijven het raamwerk van de businessklassen die nodig zijn voor de servlet. Als de servlet bijvoorbeeld gebruikmaakt van een object van het type proxyArticles en deze klasse een methode getCodes moet hebben die een lijst (ArrayList) met tekenreeksen retourneert, volstaat het in eerste instantie om het volgende te schrijven:
public ArrayList getCodes(){
String[] codes= {"code1","code2","code3"};
ArrayList aCodes=new ArrayList();
for(int i=0;i<codes.length;i++){
aCodes.add(codes[i]);
}
return aCodes;
}
- Vervolgens kunnen we overgaan tot het testen van de servlet.
- Het configuratiebestand web.xml van de applicatie moet worden aangemaakt. Dit bestand moet alle informatie bevatten die de init-methode van de servlet verwacht (<init-param>). Daarnaast stellen we de URL in waarmee de hoofd-servlet bereikbaar is (<servlet-mapping>).
- Alle benodigde klassen (servlet, bedrijfsspecifieke klassen) worden in WEB-INF/classes geplaatst.
- Alle benodigde klassenbibliotheken (.jar) worden in WEB-INF/lib geplaatst. Deze bibliotheken kunnen bedrijfsspecifieke klassen, stuurprogramma’s JDBC, enz. bevatten.
- De weergaven JSP worden in de hoofdmap van de applicatie of in een aparte map geplaatst. Hetzelfde geldt voor de overige bronnen (html, afbeeldingen, geluid, video’s, ...)
- Zodra dit is gebeurd, wordt de applicatie getest en worden de eerste fouten verholpen. Aan het einde van deze fase is de architectuur van de applicatie operationeel. Deze testfase kan lastig zijn, aangezien er bij Tomcat geen debugging-tool beschikbaar is. Hiervoor zou Tomcat zelf moeten zijn geïntegreerd in een ontwikkeltool (JBuilder Developer, Sun One Studio, ...). We kunnen gebruikmaken van System.out.println("....")-instructies die in het Tomcat-venster schrijven. Het eerste wat we moeten controleren, is of de methode init alle gegevens uit het bestand web.xml correct ophaalt. Hiervoor kunnen we de waarden ervan in het Tomcat-venster weergeven. Op dezelfde manier controleren we of de methoden doGet en doPost de parameters van de verschillende formulieren HTML van de applicatie correct ophalen.
We schrijven de businessklassen die de servlet nodig heeft. Dit is doorgaans de klassieke ontwikkeling van een Java-klasse, die meestal onafhankelijk is van een webapplicatie. Deze wordt eerst buiten deze omgeving getest, bijvoorbeeld met een console-applicatie. Wanneer een businessklasse is geschreven, kunnen we deze integreren in de implementatiearchitectuur van de webapplicatie en controleren of deze correct is geïntegreerd. Dit proces wordt voor elke businessklasse herhaald.
1.4. De ontwikkelingsaanpak STRUTS
De bedenkers van de STRUTS-methodologie hebben getracht een standaard ontwikkelingsmethode te definiëren die voldoet aan de MVC-architectuur voor in Java geschreven webapplicaties. Het STRUTS-project omvat twee aspecten:
- de ontwikkelingsmethode. We zullen zien dat deze vrij dicht in de buurt komt van de hierboven beschreven methode voor JSP-servlets en -pagina’s
- de hulpmiddelen waarmee we deze ontwikkelingsmethode kunnen toepassen. Dit zijn bibliotheken met Java-klassen die te vinden zijn op de website van de Apache Foundation (www.apache.org).
1.4.1. De ontwikkelingsmethode
De architectuur MVC die door STRUTS wordt gebruikt, is als volgt:
![]() |
- De controller vormt het hart van de applicatie. Alle verzoeken van de client lopen via de controller. Het is een generieke servlet die door STRUTS wordt geleverd. In sommige gevallen kan het nodig zijn om hier een afgeleide van te maken. Voor eenvoudige gevallen is dit niet nodig. Deze generieke servlet haalt de benodigde informatie uit een bestand dat meestal struts-config.xml heet.
- Als het verzoek van de klant formulierparameters bevat, worden deze in een Bean-object geplaatst. Een klasse wordt een Bean-klasse genoemd als deze voldoet aan bepaalde constructieregels die we later zullen bespreken. De Bean-objecten die in de loop van de tijd op deze manier worden aangemaakt, worden opgeslagen in de sessie of het verzoek van de klant. Dit is configureerbaar. Ze hoeven niet opnieuw te worden aangemaakt als ze al bestaan.
- In het configuratiebestand struts-config.html wordt aan elke URL die programmatisch moet worden verwerkt (en dus niet overeenkomt met een weergave JSP die rechtstreeks kan worden opgevraagd) bepaalde informatie gekoppeld:
- de naam van de Action-klasse die verantwoordelijk is voor de verwerking van het verzoek. Ook hier kan het geïnstantieerde Action-object worden bewaard in de sessie of het verzoek.
- als de aangevraagde URL is geconfigureerd (bijvoorbeeld bij het verzenden van een formulier naar de controller), wordt de naam van de bean vermeld die verantwoordelijk is voor het opslaan van de formuliergegevens.
- Op basis van deze informatie uit het configuratiebestand kan de controller bij ontvangst van een URL-verzoek van een client bepalen of er een bean moet worden aangemaakt en welke. Zodra de bean is geïnstantieerd, kan deze controleren of de gegevens die hij heeft opgeslagen en die afkomstig zijn uit het formulier, geldig zijn of niet. Een methode van de bean met de naam `validate` wordt automatisch aangeroepen door de controller. De bean wordt door de ontwikkelaar geïmplementeerd. Deze plaatst dus in de methode `validate` de code die de geldigheid van de formuliergegevens controleert. Als de gegevens ongeldig blijken te zijn, gaat de controller niet verder. Hij draagt het stokje over aan een weergave waarvan hij de naam in zijn configuratiebestand vindt. De uitwisseling is dan voltooid. Opgemerkt moet worden dat de ontwikkelaar kan aangeven dat de geldigheid van het formulier niet moet worden gecontroleerd. Dit doet hij ook in het bestand struts-config.html. In dat geval roept de controller de methode `validate` van de bean niet aan.
- Als de gegevens van de bean correct zijn, of als er geen controle plaatsvindt, of als er geen bean is, draagt de controller het over aan het object van het type Action dat gekoppeld is aan het bestand URL. Dit doet hij door de methode `execute` van dit object aan te roepen, waarbij hij de referentie van de bean doorgeeft die hij eventueel heeft aangemaakt. Hier voert de ontwikkelaar de benodigde bewerkingen uit: hij zal eventueel gebruik moeten maken van businessklassen of klassen voor gegevenstoegang. Aan het einde van de verwerking geeft het Action-object de naam van de weergave terug aan de controller, die deze als antwoord naar de client moet sturen.
- De controller verstuurt dit antwoord. De communicatie met de client is voltooid.
De ontwikkelmethodologie STRUTS begint vorm te krijgen:
- de definitie van de weergaven. Er wordt onderscheid gemaakt tussen weergaven die formulieren zijn en de overige.
- Elke formulierweergave leidt tot een definitie in het bestand struts-config.xml. Daarin worden de volgende gegevens gedefinieerd:
- de naam van de Bean-klasse die de gegevens van het formulier zal bevatten, evenals de aanduiding of de gegevens al dan niet moeten worden gecontroleerd. Als ze moeten worden gecontroleerd en ongeldig blijken te zijn, moet worden aangegeven welke weergave in dat geval als antwoord naar de client moet worden verzonden.
- de naam van de Action-klasse die verantwoordelijk is voor de verwerking van het formulier.
- de naam van alle weergaven die naar de klant kunnen worden verzonden zodra het verzoek is verwerkt. De Action-klasse kiest er een uit, afhankelijk van het resultaat van de verwerking.
- Elke weergave komt overeen met een pagina JSP. We zullen zien dat in de weergaven, met name de formulierweergaven, soms gebruik wordt gemaakt van een bibliotheek met Struts-specifieke tags.
- Elke formulierweergave leidt tot een definitie in het bestand struts-config.xml. Daarin worden de volgende gegevens gedefinieerd:
- het schrijven van de JavaBean-klassen die bij de formulierweergaven horen
- het schrijven van de Action-klassen die verantwoordelijk zijn voor de verwerking van de formulieren
- het schrijven van eventuele bedrijfs- of gegevenstoegangsklassen
1.4.2. De ontwikkeltools van STRUTS
Het project STRUTS is een van de projecten van de Apache Software Foundation. Een aantal van deze projecten is gebundeld onder de naam Jakarta en is beschikbaar op de URL http://jakarta.apache.org:

Het is aan te raden deze pagina te lezen. Veel van deze projecten zijn interessant voor Java-ontwikkelaars. Als we de bovenstaande link naar Struts volgen, komen we op de startpagina van het project terecht:

Ook hier is het raadzaam om de startpagina te lezen. Om de Java-bibliotheken van Struts te downloaden, volgen we de bovenstaande link ‘Binaries’:

Voor Windows gebruiken we de link 1.1.zip en 1.1.tar.gz voor Unix (nov. 2003). Zodra het bestand 1.1.zip is uitgepakt, krijgen we de volgende mapstructuur:

In deze mapstructuur bevinden zich de Java-klassenbibliotheken die nodig zijn voor de ontwikkeling van STRUTS. Deze zijn opgeslagen in .jar- of .war-bestanden, die vergelijkbaar zijn met .zip-bestanden. Ze kunnen met dezelfde hulpprogramma’s worden geopend. De meeste benodigde bibliotheken bevinden zich in de bovenstaande map lib:

Naast de .jar-klassenbibliotheken zijn er ook .dtd-bestanden (Document Type Definition) die geldigheidsregels voor XML-bestanden bevatten. Een XML-bestand kan in zijn inhoud naar een dergelijk DTD-bestand verwijzen. Het programma (de zogenaamde parser) dat de inhoud van het bestand XML analyseert, gebruikt de validiteitsregels uit het bestand DTD waarnaar wordt verwezen om te bepalen of het bestand XML syntactisch correct is. Zo legt het bestand struts-config_1_1.dtd bijvoorbeeld de regels vast voor de opbouw van het configuratiebestand struts-config.xml voor versie 1.1 van Struts.
Laten we nu eens kijken waar de verschillende elementen van de Struts-boomstructuur moeten worden geplaatst om een Struts-applicatie op de Tomcat-server te implementeren.
1.5. Implementatie van een Struts-applicatie
Een Struts-applicatie is een webapplicatie zoals elke andere. Ze volgt dus de implementatieregels van de container waarin ze wordt uitgevoerd. Hier wordt een applicatie, die we strutspersonne zullen noemen, uitgevoerd door een Tomcat-server versie 4.x. In de bijlage vindt u de implementatieprocedure voor Tomcat versie 5.x. We volgen hier de implementatieregels van Tomcat 4.x:
- We definiëren de context strutspersonne in het configuratiebestand server.xml van Tomcat:
Zodra dit is gebeurd, starten we Tomcat eventueel opnieuw op, zodat de nieuwe context wordt overgenomen. We kunnen de geldigheid van de context controleren door de URL http://localhost:8080/strutspersonne op te vragen:

Als we geen foutpagina krijgen, is de context correct.
- We maken in de fysieke map die bij de strutspersonne-context hoort, de submap WEB-INF aan.
- In de map WEB-INF van de applicatie definiëren we het configuratiebestand web.xml van de applicatie:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
- De controllerklasse (servlet) van de applicatie is een vooraf gedefinieerde klasse van Struts, genaamd ActionServlet. Deze bevindt zich in het bestand struts.jar. Om ervoor te zorgen dat Tomcat deze klasse kan vinden, plaatsen we struts.jar in de map <tomcat>\common\lib, een van de mappen die Tomcat doorzoekt wanneer het naar klassen zoekt. We plaatsen daar in feite alle .jar-bestanden die zich in de map <struts>\lib bevinden, waarbij <struts> de hoofdmap van de Struts-structuur is.

- We plaatsen ook de bestanden struts-el.jar en jstl.jar die zich in <struts>\contrib\struts-el\lib bevinden:

- Hier hebben we toegang tot de webserver. Dat is niet altijd het geval. Als we een web-/Java-applicatie implementeren in een webcontainer die we niet zelf beheren, is het beter dat de applicatie alle benodigde bibliotheken zelf meebrengt. Deze moeten dan worden geplaatst in de map WEB-INF/lib, die we moeten aanmaken.
- We hebben aangegeven dat de controller een aantal gegevens nodig heeft die hij normaal gesproken vindt in een bestand struts-config.xml in dezelfde map als web.xml. De naam van dit bestand is echter instelbaar. De parameter config, hierboven, bepaalt deze naam.
- De tag <servlet-mapping> geeft aan dat de controller bereikbaar is via alle URL-bestanden die eindigen op het achtervoegsel .do. Deze koppeling is vereist door Struts. Deze URL-bestanden worden vervolgens gefilterd door de controller, die alleen de URL-bestanden accepteert die in zijn configuratiebestand struts-config.xml zijn opgegeven.
Voorlopig volstaat ons configuratiebestand web.xml.
- We gaan de URL /main.do opvragen bij de strutspersonne-applicatie. Op basis van het vorige bestand web.xml zal dit URL-bestand dus worden doorgegeven aan de servlet org.apache.struts.action. De klasse ActionServlet wordt geïnstantieerd en de methode init wordt aangeroepen. Deze probeert het configuratiebestand te lezen dat is gedefinieerd door de parameter config. Dit bestand moet dus bestaan. We maken het volgende bestand struts-config.xml aan:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
<action-mappings>
<action
path="/main"
parameter="/main.html"
type="org.apache.struts.actions.ForwardAction"
/>
</action-mappings>
</struts-config>
Merk op dat het bestand DTD van struts-config.xml niet hetzelfde is als dat van het bestand web.xml, wat aangeeft dat ze niet dezelfde structuur hebben. Voor elk URL-bestand dat de controller moet verwerken, moeten we een <action>-tag definiëren. Deze dient om de controller aan te geven wat hij moet doen wanneer dit URL-bestand wordt opgevraagd. Hier geven we de volgende elementen aan:
- path="/main": definieert de naam van de URL die door de <action>-tag is geconfigureerd. Het achtervoegsel .do is impliciet.
- type="org.apache.struts.actions.ForwardAction": definieert de naam van de Action-klasse die het verzoek moet verwerken. Hier gebruiken we een vooraf gedefinieerde Action-klasse in Struts. Deze doet op zichzelf niets en stuurt het verzoek van de client door naar de URL die is opgegeven in het parameter-attribuut.
- parameter="/main.html": de naam van de URL waaraan het verzoek moet worden doorgestuurd. In dit geval is het een statisch HTML-bestand.
Kortom, wanneer de gebruiker het URL /main.do opvraagt, krijgt hij het URL /main.html.
- Het bestand main.html ziet er als volgt uit:
<html>
<head>
<title>Application strutspersonne</title>
</head>
<body>
Application strutspersonne active ....
</body>
</html>
Dit bestand wordt in de map strutspersonne/vues van de applicatie geplaatst:

Je kunt dit rechtstreeks aanvragen via de URL-http://localhost:8080/strutspersonne/main.html:

Hier is de Struts-controller van de applicatie niet in actie gekomen, aangezien deze alleen in actie komt als er een verzoek wordt gedaan voor de URL van het type *.do. In dit geval is er echter een verzoek gedaan voor de URL /vues/main.html.
- Het eerder aangemaakte bestand struts-config.xml moet in dezelfde map WEB-INF worden geplaatst als het bestand web.xml:

- We gaan nu controleren of de controller van de strutspersonne-applicatie correct werkt door het bestand URL /main.do op te vragen, nadat we, indien nodig, Tomcat opnieuw hebben opgestart.

Hier is de Struts-controller in actie gekomen, aangezien we een URL van het type *.do hebben opgevraagd. We hebben inderdaad de verwachte pagina ontvangen (main.html). We beschikken dus over de basiselementen voor de werking van onze applicatie: de strutspersonne-context, de configuratiebestanden web.xml en struts-config.xml, en de Struts-bibliotheken.
Wat zou er zijn gebeurd als we een URL van het type /toto.do hadden opgevraagd? Volgens het configuratiebestand web.xml van de strutspersonne-applicatie wordt dan de Struts-controller aangeroepen om deze te verwerken. Deze raadpleegt vervolgens zijn configuratiebestand struts-config.html en vindt geen configuratie voor de URL /toto. Wat doet hij dan? Laten we het eens proberen:

We krijgen een foutpagina te zien, wat normaal lijkt. We kunnen nu beginnen met het schrijven van een applicatie.



