Spring dans l'architecture MVC2 : DispatcherServlet

Distribution des tâches avec un servlet central

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Le point central de l'architecture web MVC sous Spring est DispatcherServlet. Il s'agit d'une sorte de distributeur des tâches. Chaque nouvelle requête HTTP est captée par DispatcherServlet. Ensuite, en analysant les propriétés de la requête (en-tête, URI), il décide quel contrôleur doit se charger de retourner une réponse. DispatcherServlet est un bon exemple d'implémentation d'un dessign pattern appelé front controller.

Qu'est-ce que c'est front controller design pattern ?

Ce design pattern est la réponse à la problématique de gestion centralisée des requêtes. Il consiste à créer un seul point d'entrée pour toutes les requêtes. Contrairement à plusieurs points d'accès, cela facilite la centralisation du code car tous les services, la gestion des vues et de navigation sont gérés par un seul contrôleur.

Front controller design pattern utilise donc un contrôleur en tant que point d'entrée initial pour chaque requête. Ce contrôleur gère la requête, les vues, les erreurs ainsi qu'invoque de divers services (par exemple authorization et authentification pour la sécurité).

Cet unique point d'entrée permet de réduire la quantité du code dupliqué. Il aide donc à maintenir l'application plus facilement. Néanmoins, il ne limite pas le nombre des contrôleurs disponibles dans le système à un seul.

Le design pattern en question evoque également la notion du dispatcher. Il peut être encapsulé dans le contrôleur principal aussi bien qu'être un élément séparé dans l'architecture. Il est l'étape intermédiaire entre le contrôleur principal et la vue.

DispatcherServlet dans Spring

On peut déterminer plusieurs dispatchers pour des patterns différents. Cependant, dans notre application d'exemple on va se limiter à un seul. Il s'agit d'une servlet nommé mainAppServlet qui va traiter toutes les requêtes (pattern appliqué est "/"). Voici comment se présente notre fichier web.xml :

afficher le code

Quelques éléments supplémentaires sont présents dans ce fichier. Tout d'abord, le <param-name /> contextConfigLocation. Il contient la liste des fichiers qui seront chargés et utilisés par l'application.

Concernant un listener, ContextLoaderListener, il a deux rôles :
- attacher le cycle de vie de l'ApplicationContext au cycle de vie du ServletContext
- automatiser la création de l'ApplicationContext

Pour accomplir ces deux tâches, il se base sur la liste des fichiers spécifiés dans le paramètre contextConfigLocation. Si ce paramètre est absent, le listener cherche le fichier de configuration par défaut, placé dans /WEB-INF/applicationContext.xml.

Et finalement, le DispatcherServlet qui charge également un fichier de configuration défini dans <contextConfigLocation />. Pourquoi il faut avoir ces deux endroits de configuration ? Le premier endroit, celui utiliser par ContextLoaderListener, contient une liste des éléments généraux (données de connexion à la base de données, définition des services, sécurité). Le fichier de configuration du DispatcherServlet contient uniquement les informations liées à l'application web (contrôleurs, view resolvers, mapping handlers). Ce fichier peut lire les fichiers définis dans le paramètre général contextConfigLocation. Par contre, le paramètre général contextConfigLocation ne peut pas lire le fichier de configuration propre à DispatcherServlet.

Tout à la fin on précise que DispatcherServlet doit s'appliquer à toutes les requêtes.

Flux d'exécution du DispatcherServlet

Le traitement de chaque requête par DispatcherServlet se fait de manière suivante :

  1. Il cherche WebApplicationContext et l'attache à la requête en tant qu'un attribut. Grâce à cela, contrôleur et d'autres éléments peuvent l'utiliser
  2. LocaleResolver est ensuite attaché à la requête. Grâce à cela, on peut gérer les éléments liés à la traduction de notre application (partie i18n dans Spring), comme les vues ou les informations textuels.
  3. ThemeResolver est attaché à la requête pour déterminer quel thème doit être utilise par les vues.
  4. Si MultipartResolver est spécifié, la requête est alors analysé sous angle de présence des fichiers. Si les fichiers sont trouvés, la requête est envoyée à MultipartHttpServletRequest pour le traitement.
  5. On recherche un handler. S'il est trouvé, on exécute la chaîne lui associée. Cette chaîne se compose du preprocessors, postprocessors et contrôleurs. Elle prépare le modèle de vue ou affiche la vue.
  6. Si le modèle de vue est retourné, la vue est affichée. Sinon, la vue n'est pas affichée, peut-être parce que la requête était déjà réalisée.

Pendant ce processus de traitement, HandlerExceptionResolver peut être appelé à chaque moment où une exception est lancée. Grâce à cela, on peut appliquer le comportement spécifique à de différentes exceptions.

Du DispatcherServlet aux contrôleurs

Les contrôleurs interprètent la demande de l'utilisateur et la transforment en un modèle de vue qui est ensuite affiché sur l'écran.

Dans notre application on utilisera les annotations pour marquer une classe en tant que contrôleur. Plus de détails à ce sujet se trouvent dans la partie contrôleurs dans une application web Spring.

Une question ? Une remarque ?

*

*

Un conseil MySQL

Qu'est-ce que signifie l'attribut UNSIGNED ?

Si notre base stocke uniquement les valeurs supérieures à 0, il faut utiliser un attribut qui aggrandit le nombre des chiffres possibles à sauvegarder. Il s'agit de l'attribut UNSIGNED qu'on peut appliquer aux champs numériques. Prenons l'exemple d'un champ type BIGINT. Normalement il occupe 8 octets et stocke les nombres entiers entre -9 223 372 036 854 775 808 à 9 223 372 036 854 775 807. Cependant, cela s'avère très peu utile lorsqu'on est sûr d'avoir uniquement les entiers positifs. En rajoutant l'attribut UNSIGNED à ce champ on double sa capacité de stockage. Alors il est capable de contenir les chiffres de 0 à 18 446 744 073 709 551 615.