comment Spring Web MVC Fonctionne vraiment

Introduction

ceci est un aperçu en profondeur des fonctionnalités puissantes et du fonctionnement interne de Spring Web MVC, qui fait partie du Framework Spring.

Le code source de cet article est disponible sur GitHub.

configuration du projet

tout au long de cet article, nous utiliserons le dernier et le plus grand Spring Framework 5., Nous nous concentrons ici sur la pile web classique de Spring, disponible depuis les toutes premières versions du framework et qui reste le principal moyen de créer des applications web avec Spring.

pour commencer, pour configurer votre projet de test, vous utiliserez Spring Boot et certaines de ses dépendances de démarrage; vous devrez également définir le parent:

notez que, pour utiliser Spring 5, vous devez également utiliser Spring Boot 2.X. au moment de la rédaction, il s’agit d’une version milestone, disponible dans le référentiel Spring Milestone., Ajoutons ce référentiel à votre projet Maven:

Vous pouvez consulter la version actuelle de Spring Boot sur Maven Central.

exemple de projet

Pour comprendre le fonctionnement de Spring Web MVC, vous implémenterez une application simple avec une page de connexion. Pour afficher la page de connexion, créez une classe @ Controller annotée InternalController avec un mappage GET pour la racine du contexte.

la méthode hello() est sans paramètre. Il renvoie une chaîne qui est interprétée par Spring MVC comme un nom de vue (dans notre cas, la connexion.,html template):

import org.springframework.web.bind.annotation.GetMapping;@GetMapping("/")public String hello() { return "login";}

pour traiter une connexion utilisateur, créez une autre méthode qui gère les requêtes POST avec les données de connexion. Il redirige ensuite l’utilisateur vers la page succès ou échec, en fonction du résultat.,

notez que la méthode login() reçoit un objet domain comme argument et renvoie un objet ModelAndView:

ModelAndView est titulaire de deux objets distincts:

  • Model – une carte clé-valeur des données utilisées pour rendre la page
  • View – un modèle de la page qui est rempli de données du modèle

ceux-ci sont joints pour plus de commodité afin que la méthode controller puisse les renvoyer tous les deux à la fois.

pour rendre votre page HTML, utilisez Thymeleaf comme moteur de modèle de vue, qui a une intégration solide et prête à l’emploi avec Spring.,

Servlets comme base d’une Application Web Java

alors, que se passe-t-il réellement lorsque vous tapez http://localhost:8080/ dans le navigateur, appuyez sur Entrée et la demande atteint le serveur web? Comment obtenez-vous de cette demande à voir un formulaire web dans le navigateur?

étant donné que le projet est une simple application Spring Boot, vous pourrez l’exécuter via Spring5Application.

le Printemps de Démarrage utilise Apache Tomcat par défaut., Par conséquent, en exécutant l’application, vous verrez probablement les informations suivantes dans le journal:

puisque Tomcat est un conteneur de Servlet, naturellement chaque requête HTTP envoyée à un serveur Web Tomcat est traitée par un servlet Java. Ainsi, le point D’entrée de L’application Web Spring est, sans surprise, un servlet.

un servlet est, en termes simples, un composant de base de toute application Web Java; il est de bas niveau et n’impose pas trop de modèles de programmation spécifiques, tels que MVC.

un servlet HTTP ne peut recevoir qu’une requête HTTP, la traiter d’une manière ou d’une autre et renvoyer une réponse.,

et, à partir de L’API Servlet 3.0, vous pouvez maintenant aller au-delà de la configuration XML et commencer à exploiter la configuration Java (avec des restrictions mineures).,

DispatcherServlet en tant que Cœur de Spring MVC

ce que nous voulons vraiment faire en tant que développeurs d’une application web est d’abstraire les tâches fastidieuses et standard suivantes et de nous concentrer sur la logique métier utile:

  • mappage d’une requête HTTP à une certaine méthode de traitement
  • analyse des données li> génération de réponses à partir de DTO, D’objets de domaine, etc.

Le Spring DispatcherServlet fournit exactement cela., C’est le cœur du framework Spring Web MVC; ce composant central reçoit toutes les demandes de votre application.

Comme vous le verrez, DispatcherServlet est très extensible.,les moteurs de placage, XML, XSLT ou toute autre technologie de vue (implémentations de L’interface ViewResolver)

  • analysez les requêtes multipart en utilisant L’implémentation de téléchargement de fichier Apache Commons par défaut ou en écrivant votre propre multipartresolver
  • résolvez les paramètres régionaux avec n’importe quelle implémentation LocaleResolver, y compris cookie, session, Accept HTTP header, ou tout autre moyen tracez le traitement des requêtes HTTP simples vers une méthode de votre couche Controller et retournez au navigateur/client.,

    Le DispatcherServlet a une longue hiérarchie d’héritage; il vaut la peine de comprendre ces aspects individuels un par un, de haut en bas. Les méthodes de traitement des demandes nous intéresseront le plus.

    comprendre la requête HTTP, à la fois localement pendant le développement standard, ainsi qu’à distance, est un élément essentiel de la compréhension de l’architecture MVC.

    GenericServlet

    GenericServlet fait partie de la spécification de Servlet qui n’est pas directement centrée sur HTTP. Il définit la méthode service () qui reçoit les demandes entrantes et produit les réponses.,

    notez que les arguments des méthodes ServletRequest et ServletResponse ne sont pas liés au protocole HTTP:

    public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;

    c’est la méthode qui est finalement appelée sur n’importe quelle requête au serveur, y compris une simple requête GET.

    HttpServlet

    La classe HttpServlet est, comme son nom l’indique, l’implémentation de Servlet HTTP, également définie par la spécification.,

    en termes plus pratiques, HttpServlet est une classe abstraite avec une implémentation de méthode service() qui divise les requêtes par le type de méthode HTTP et ressemble à peu près à ceci:

    HttpServletBean

    ensuite, HttpServletBean est la première classe Spring-aware dans la hiérarchie. Il injecte les propriétés du bean en utilisant les valeurs de servlet init-param reçues du web.xml ou à partir de WebApplicationInitializer.

    dans le cas des requêtes à votre application, les méthodes doGet(), doPost(), etc. sont appelées pour ces requêtes HTTP spécifiques.,

    FrameworkServlet

    FrameworkServlet intègre la fonctionnalité de Servlet avec un contexte d’application web, implémentant L’interface ApplicationContextAware. Mais il est également capable de créer seul un contexte d’application web.

    comme vous l’avez déjà vu, la superclasse HttpServletBean injecte init-params en tant que propriétés de bean. Ainsi, si un nom de classe context est fourni dans contextClass init-param de la servlet, alors une instance de cette classe sera créée en tant que contexte d’application. Sinon, une classe xmlwebapplicationcontext par défaut sera utilisée.,

    comme la configuration XML est hors de style de nos jours, Spring Boot configure DispatcherServlet avec AnnotationConfigWebApplicationContext par défaut. Mais vous pourriez changer cela facilement.

    par exemple, si vous devez configurer votre application Spring Web MVC avec un contexte d’application basé sur Groovy, vous pouvez utiliser la configuration suivante de DispatcherServlet dans le web.fichier xml:

     dispatcherServlet org.springframework.web.servlet.DispatcherServlet contextClass org.springframework.web.context.support.GroovyWebApplicationContext 

    la même configuration peut être effectuée d’une manière plus moderne basée sur Java en utilisant la classe WebApplicationInitializer.,

    DispatcherServlet: unifier le traitement des requêtes

    Le HttpServlet.l’implémentation de service (), qui achemine les requêtes par le type de verbe HTTP, est parfaitement logique dans le contexte des servlets de bas niveau. Cependant, au niveau D’abstraction Spring MVC, le type de méthode n’est qu’un des paramètres pouvant être utilisés pour mapper la demande à son gestionnaire.,

    et ainsi, l’autre fonction principale de la classe FrameworkServlet est de réintégrer la logique de gestion dans une seule méthode processRequest (), qui à son tour appelle la méthode doService ():

    @Overrideprotected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response);}@Overrideprotected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { processRequest(request, response);}// …

    DispatcherServlet: enrichir la requête

    enfin, le DispatcherServlet implémente la méthode doService (). Ici, il ajoute à la demande des objets utiles qui peuvent être utiles dans le pipeline de traitement: contexte d’application web, résolveur de paramètres régionaux, résolveur de thème, source de thème, etc.:

    de plus, la méthode doService() prépare les cartes flash d’entrée et de sortie., Flash map est essentiellement un modèle pour passer des paramètres d’une requête à une autre requête qui suit immédiatement. Cela peut être très utile lors des redirections (comme montrer à l’utilisateur un message d’information one-shot après la redirection):

    ensuite, la méthode doService () appelle la méthode doDispatch () responsable de la répartition des demandes.

    DispatcherServlet: Dispatching the Request

    le but principal de la méthode dispatch() est de trouver un gestionnaire approprié pour la requête et de lui fournir les paramètres de requête / réponse., Le gestionnaire est fondamentalement n’importe quel type d’objet et ne se limite pas à une interface spécifique. Cela signifie également que Spring doit trouver un adaptateur pour ce gestionnaire qui sait comment « parler” au gestionnaire.

    pour trouver le gestionnaire qui correspond à la requête, Spring passe par les implémentations enregistrées de L’interface HandlerMapping. Il existe de nombreuses implémentations différentes qui pourraient répondre à vos besoins.

    SimpleUrlHandlerMapping permet de mapper une requête par son URL à un certain bean de traitement. Par exemple, il peut être configuré en injectant sa propriété mappings avec un java.util.,Instance de propriétés similaire à ceci:

    /welcome.html=ticketController/show.html=ticketController

    La classe la plus utilisée pour le mappage de gestionnaire est probablement RequestMappingHandlerMapping, qui mappe une requête à une méthode @RequestMapping-annotated d’une classe @Controller. C’est exactement le mappage qui relie le répartiteur aux méthodes hello() et login() de votre contrôleur.

    notez que vos méthodes Spring-aware sont annotées avec @GetMapping et @PostMapping en conséquence. Ces annotations, à leur tour, sont marquées avec la méta-annotation @ RequestMapping.,

    la méthode dispatch() prend également en charge d’autres tâches spécifiques à HTTP:

    • traitement en court-circuit de la requête GET au cas où la ressource n’aurait pas été modifiée
    • application du résolveur multipartite pour les requêtes correspondantes
    • traitement en court-circuit de la requête si le gestionnaire a choisi de et l’adaptateur pour le Gestionnaire, il est temps de gérer enfin la demande. Voici la signature du Gestionnaire.méthode handle ()., Il est important de noter que le gestionnaire a le choix de gérer la requête:
      • écrivez les données dans l’objet de réponse par lui-même et renvoyez null

      renvoyez un objet ModelAndView à rendre par le DispatcherServlet

      @NullableModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

      Il existe plusieurs types de gestionnaires fournis. Voici comment SimpleControllerHandlerAdapter traite une instance de contrôleur Spring MVC (ne la confondez pas avec un POJO @Controller-annoté).,

      remarquez comment le gestionnaire de contrôleur renvoie L’objet ModelAndView et ne rend pas la vue par lui-même:

      public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response);}

      Le second est SimpleServletHandlerAdapter, qui adapte un Servlet ordinaire en tant que gestionnaire de requête.

      un Servlet ne sait rien de ModelAndView et gère simplement la requête par lui-même, rendant le résultat dans l’objet de réponse., Donc, cet adaptateur renvoie simplement null au lieu de ModelAndView:

      dans votre cas, un contrôleur est un POJO avec plusieurs annotations @RequestMapping, donc tout gestionnaire est essentiellement une méthode de cette classe enveloppée dans une instance HandlerMethod. Pour s’adapter à ce type de gestionnaire, Spring utilise la classe RequestMappingHandlerAdapter.,

      Arguments de traitement et valeurs de retour des méthodes du Gestionnaire

      notez que les méthodes du contrôleur ne prennent généralement pas les arguments HttpServletRequest et HttpServletResponse, mais reçoivent et renvoient de nombreux types de données, tels que des objets de domaine, des paramètres de chemin, etc.

      notez également que vous n’êtes pas obligé de renvoyer une instance ModelAndView à partir d’une méthode controller. Vous pouvez renvoyer un nom de vue,ou une ResponseEntity ou un POJO qui sera converti en une réponse JSON, etc.,

      RequestMappingHandlerAdapter s’assure que les arguments de la méthode sont résolus à partir de HttpServletRequest. En outre, il crée L’objet ModelAndView à partir de la valeur de retour de la méthode.

      Il y a un morceau de code important dans RequestMappingHandlerAdapter qui s’assure que toute cette magie de conversion a lieu:

      ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);if (this.argumentResolvers != null) { invocableMethod.setHandlerMethodArgumentResolvers( this.argumentResolvers);}if (this.returnValueHandlers != null) { invocableMethod.setHandlerMethodReturnValueHandlers( this.returnValueHandlers);}

      l’objet argumentResolvers est un composite de différentes instances HandlerMethodArgumentResolver.

      Il existe plus de 30 implémentations de résolveurs d’arguments différentes., Ils permettent d’extraire tout type d’information de la demande et de la fournir en tant qu’arguments de méthode. Cela inclut les variables de chemin D’URL, les paramètres de corps de demande, les en-têtes de demande, les cookies, les données de session, etc.

      l’objet returnValueHandlers est un composite d’objets HandlerMethodReturnValueHandler. Il existe également de nombreux gestionnaires de valeurs différents qui peuvent traiter le résultat de votre méthode pour créer L’objet ModelAndView attendu par l’adaptateur.

      par exemple, lorsque vous renvoyez une chaîne de la méthode hello (), le ViewNameMethodReturnValueHandler traite la valeur., Mais lorsque vous renvoyez un modelandview prêt à partir de la méthode login (), Spring utilise le ModelAndViewMethodReturnValueHandler.

      rendu de la vue

      à présent, Spring a traité la requête HTTP et reçu un objet ModelAndView, il doit donc rendre la page HTML que l’utilisateur verra dans le navigateur. Il le fait en fonction du modèle et de la vue sélectionnée encapsulée dans L’objet ModelAndView.

      notez également que vous pouvez rendre un objet JSON, ou XML, ou tout autre format de données pouvant être transféré via le protocole HTTP., Nous aborderons plus à ce sujet dans la prochaine section axée sur le repos ici.

      revenons au DispatcherServlet. La méthode render () définit d’abord les paramètres régionaux de la réponse à l’aide de L’instance LocaleResolver fournie. Supposons que votre navigateur moderne définit correctement L’en-tête Accept et que AcceptHeaderLocaleResolver est utilisé par défaut.

      pendant le rendu, L’objet ModelAndView pouvait déjà contenir une référence à une vue sélectionnée, ou simplement un nom de vue, ou rien du tout si le contrôleur s’appuyait sur une vue par défaut.,

      étant donné que les méthodes hello() et login() spécifient la vue souhaitée sous forme de nom de chaîne, elle doit être recherchée par ce nom. C’est donc ici que la liste viewResolvers entre en jeu:

      Il s’agit d’une liste d’instances ViewResolver, y compris notre ThymeleafViewResolver fourni par la bibliothèque d’intégration thymeleaf-spring5. Ce résolveur sait où rechercher les vues et fournit les instances de vue correspondantes.,

      Après avoir appelé la méthode render() de la vue, Spring termine enfin le traitement de la requête en envoyant la page HTML au navigateur de l’utilisateur:

      support REST

      Au-delà du scénario MVC typique, nous pouvons également utiliser le framework pour créer des services web REST.

      en termes simples, vous pouvez accepter une ressource en entrée, spécifier un POJO comme argument de méthode et l’annoter avec @RequestBody., Vous pouvez également annoter la méthode elle-même avec @ResponseBody pour spécifier que son résultat doit être transformé directement en une réponse HTTP:

      cela est également possible grâce à L’extensibilité de Spring MVC.

      pour transférer les DTO internes à une représentation REST, le framework utilise L’infrastructure HttpMessageConverter. Par exemple, L’une des implémentations est MappingJackson2HttpMessageConverter, qui est capable de convertir des objets de modèle vers et depuis JSON à l’aide de la bibliothèque Jackson.,

      et pour simplifier davantage la création d’une API REST, Spring introduit l’annotation @RestController. C’est pratique pour assumer la sémantique @ResponseBody par défaut et éviter de la définir explicitement sur chaque contrôleur REST:

      Conclusion

      dans cet article, vous avez examiné en détail le traitement d’une requête dans le framework Spring MVC. Vous avez vu comment différentes extensions du framework fonctionnent ensemble pour fournir toute la magie et vous épargner la nécessité de gérer les parties difficiles du protocole HTTP.,

      améliorez continuellement vos applications Java en utilisant Stackify Retrace, l’outil de gestion des performances des applications du cycle de vie complet. De l’essayer.

  • Author: admin

    Laisser un commentaire

    Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *