Fonctionnement de base de <include>
L'action <include> dans les JSP permet d'intégrer dynamiquement le contenu d'une autre ressource, comme une autre page JSP, un fichier HTML ou un Servlet, au sein de la page courante lors du traitement d'une requête. Cette approche favorise la modularité du code en réuitlisant des fragments communs tels que des en-têtes ou des pieds de page.
Syntaxe typique :
<jsp:include page="chemin/vers/la/ressource" />
Par exemple, dans une page principale accueil.jsp, on peut inclure un en-tête réutilisable :
<html>
<body>
<jsp:include page="entete.jsp" />
<h1>Bienvenue</h1>
<jsp:include page="pied.jsp" />
</body>
</html>
Lors de l'exécution, le conteneur web traite la page principale et, en rencontrant le tag d'inclusion, déclenche une sous-requête vers la ressource cible. Le résultat de cette requête est ensuite inséré à la position spécifiée dans le flux de sortie de la page principale.
Différences entre inclusion dynamique et statique
Il existe deux mécanismes d'inclusion dans les JSP : <include> (dynamique) et la directive <%@ include %> (statique). Leurs différences fondamentales reposent sur le timing et l'implémentation.
Inclusion statique : Elle a lieu lors de la phase de traduction de la JSP en code source Servlet. Le contenu du fichier inclus est directement copié-collé dans la JSP principale, formant ainsi un seul fichier fusionné. Ce fichier unique est ensuite compilé en une classe Servlet. Les variables et le contexte sont partagés au niveau de la compilation.
Inclusion dynamique : Elle survient pendant le traitement de la requête. La page principale et la page incluse sont traduites en Servlets séparés. L'inclusion se fait via un appel interne à RequestDispatcher.include(), permettant de conserver les objets request et response partagés. Cette méthode offre plus de flexibilité, car le chemin d'inclusion peut être déterminé de manière conditionnelle à l'exécution.
En résumé, l'inclusion statique agit comme une macro de préprocesseur, tandis que l'inclusion dynamique ressemble à un appel de fonction lors de l'exécution.
Relation avec RequestDispatcher
L'action <include> est implémentée en coulisses via la méthode include() de l'interface RequestDispatcher du Servlet API. Le code généré par le conteneur pour un tag d'inclusion ressemble à :
// Dans la méthode _jspService du Servlet généré
RequestDispatcher disp = request.getRequestDispatcher("cible.jsp");
if (disp != null) {
disp.include(request, response);
}
Cette méthode permet à la ressource incluse de contribuer au contenu de la réponse tout en partageant les mêmes objets de requête et de réponse. Ainsi, les attributs de requête définis dans la page prinicpale sont accessibles dans la page incluse, et vice-versa.
Comparaison avec <forward>
Bien que tous deux utilisent RequestDispatcher, ils servent des objectifs distincts :
<include> : Inclut le contenu d'une autre ressource dans la sortie actuelle. La page principale continue son exécution après l'inclusion, et le résultat final est la concaténation des sorties des deux pages.
<forward> : Transfère complètement la gestion de la requête à une autre ressource. Une fois le forward exécuté, aucun code supplémentaire dans la page d'origine n'est traité ; la réponse est entièrement produite par la ressource cible.
Cette distinction est cruciale dans les architectures MVC, où le forward est souvent utilisé par un contrôleur pour rediriger vers une vue, tandis que l'inclusion sert à assembler des composants d'interface.
Évolution dans les frameworks modernes
Bien que les JSP soient moins utilisées dans les développements récents, le concept d'inclusion dynamique demeure pertinent et se manifeste sous des formes avancées.
Dans les frameworks frontend comme React ou Vue.js, l'utilisation de composants personnalisés (ex: <MonEnTete />) permet une réutilisation similaire mais avec une granularité plus fine et une meilleure intégration côté client.
Côté serveur, des moteurs de templates tels que Thymeleaf proposent des fonctions d'inclusion comme th:insert ou th:replace, offrant des capacités d'héritage de layout et de composition plus puissantes que les JSP.
Ainsi, les principes sous-jacents de réutilisation de code et de séparation des préoccupations restent au cœur du développement web contemporain.