HandlerAdapters dans Spring MVC

HandlerAdapters in Spring MVC

1. Vue d'ensemble

Dans cet article, nous allons nous concentrer sur les différentes implémentations d'adaptateurs de gestionnaire disponibles dans le framework Spring.

2. Qu'est-ce qu'un Handleradapter?

LeHandlerAdapter est essentiellement une interface qui facilite la gestion des requêtes HTTP de manière très flexible dans Spring MVC.

Il est utilisé conjointement avec lesHandlerMapping, qui mappent une méthode à une URL spécifique.

LeDispatcherServlet utilise alors unHandlerAdapter pour invoquer cette méthode. Le servlet n’invoque pas la méthode directement - il sert essentiellement de pont entre lui-même et les objets du gestionnaire, conduisant à une conception de couplage lâche.

Jetons un coup d'œil aux différentes méthodes disponibles dans cette interface:

public interface HandlerAdapter {
    boolean supports(Object handler);

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

    long getLastModified(HttpServletRequest request, Object handler);
}

L'APIsupports est utilisée pour vérifier si une instance de gestionnaire particulière est prise en charge ou non. Cette méthode doit être appelée avant d'appeler la méthodehandle() de cette interface, afin de s'assurer que l'instance de gestionnaire est prise en charge ou non.

L'APIhandle est utilisée pour gérer une requête HTTP particulière. Cette méthode est responsable de l'appel du gestionnaire en passant les objetsHttpServletRequest etHttpServletResponse comme paramètre. Le gestionnaire exécute ensuite la logique de l'application et renvoie un objetModelAndView, qui est ensuite traité par lesDispatcherServlet.

3. Dépendance Maven

Commençons par la dépendance Maven qui doit être ajoutée àpom.xml:


    org.springframework
    spring-webmvc
    4.3.4.RELEASE

La dernière version de l'artefactspring-webmvc peut être trouvéehere.

4. Types deHandlerAdapter

4.1. SimpleControllerHandlerAdapter

C'est l'adaptateur de gestionnaire par défaut enregistré par Spring MVC. Il traite des classes implémentant l'interfaceController et est utilisé pour transmettre une requête à un objet contrôleur.

Si une application Web utilise uniquement des contrôleurs, nous n'avons pas besoin de configurer deHandlerAdapter car le framework utilise cette classe comme adaptateur par défaut pour traiter une requête.

Définissons une classe de contrôleur simple, en utilisant l'ancien style de contrôleur (implémentant l'interfaceController):

public class SimpleController implements Controller {
    @Override
    public ModelAndView handleRequest(
      HttpServletRequest request,
      HttpServletResponse response) throws Exception {

        ModelAndView model = new ModelAndView("Greeting");
        model.addObject("message", "Dinesh Madhwal");
        return model;
    }
}

La configuration XML similaire:


    
    
        
        
    

La classeBeanNameUrlHandlerMapping est la classe de mappage pour cet adaptateur de gestionnaire.

Note: si un adaptateur de gestionnaire personnalisé est défini dansBeanFactory,, cet adaptateur n'est pas automatiquement enregistré. Nous devons donc le définir explicitement dans le contexte. S'il n'est pas défini et que nous avons défini un adaptateur de gestionnaire personnalisé, nous obtiendrons une exception indiquant qu'aucun adaptateur pour un gestionnaire n'est spécifié.

4.2. SimpleServletHandlerAdapter

Cet adaptateur de gestionnaire permet d'utiliser n'importe quelServlet pour travailler avecDispatcherServlet pour gérer la requête. Il transmet la requête deDispatcherServlet à la classeServlet appropriée en appelant sa méthodeservice().

Les beans qui implémentent l'interfaceServlet sont automatiquement gérés par cet adaptateur. Il n'est pas enregistré par défaut et nous devons l'enregistrer comme n'importe quel autre bean normal dans le fichier de configuration deDispatcherServlet:

4.3. AnnotationMethodHandlerAdapter

Cette classe d'adaptateur est utilisée pour exécuter les méthodes annotées avec l'annotation@RequestMapping. Il est utilisé pour mapper les méthodes en fonction des méthodes HTTP et des chemins HTTP.

La classe de mappage pour cet adaptateur estDefaultAnnotationHandlerMapping, qui est utilisée pour traiter l'annotation@RequestMapping au niveau du type etAnnotationMethodHandlerAdaptor est utilisé pour traiter au niveau de la méthode.

Ces deux classes sont déjà enregistrées par le framework lorsque leDispatcherServlet est initialisé. Cependant, si les autres adaptateurs de gestionnaires sont déjà définis, nous devons également les définir dans le fichier de configuration.

Définissons une classe de contrôleur:

@Controller
public class AnnotationHandler {
    @RequestMapping("/annotedName")
    public ModelAndView getEmployeeName() {
        ModelAndView model = new ModelAndView("Greeting");
        model.addObject("message", "Dinesh");
        return model;
    }
}

L'annotation@Controller indique que cette classe joue le rôle decontroller.

L'annotation@RequestMapping mappe la méthodegetEmployeeName() à l'URL/name.

Il existe deux manières différentes de configurer cet adaptateur, selon que l'application utilise une configuration basée sur Java ou une configuration basée sur XML. Voyons le premier moyen d’utiliser la configuration Java:

@ComponentScan("com.example.spring.controller")
@Configuration
@EnableWebMvc
public class ApplicationConfiguration implements WebMvcConfigurer {
    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/");
        bean.setSuffix(".jsp");
        return bean;
    }
}

Si l'application utilise la configuration XML, il existe deux approches différentes pour configurer cet adaptateur de gestionnaire dans le contexte XML d'application Web. Jetons un œil à la première approche définie dans le fichierspring-servlet_AnnotationMethodHandlerAdapter.xml:


    
    
    
    
        
        
    

La balise<context:component-scan /> est utilisée pour spécifier le package à analyser pour les classescontroller.

Jetons un coup d'oeil à la deuxième approche:


    
    
    
        
        
    

La balise<mvc:annotation-driven> enregistrera automatiquement ces deux classes avec spring MVC. Cet adaptateur était obsolète dans Spring 3.2 et un nouvel adaptateur de gestionnaire appeléRequestMappingHandlerAdapter a été introduit dans Spring 3.1.

4.4. RequestMappingHandlerAdapter

Cette classe d'adaptateur a été introduite dans Spring 3.1, rendant obsolète l'adaptateur de gestionnaireAnnotationMethodHandlerAdaptor dans Spring 3.2.

Il est utilisé avec la classeRequestMappingHandlerMapping, quiexecutes methods annotated with @RequestMapping.

LeRequestMappingHandlerMapping est utilisé pour maintenir le mappage de l'URI de la demande vers le gestionnaire. Une fois le gestionnaire obtenu, leDispatcherServlet distribue la requête à l'adaptateur de gestionnaire approprié, qui appelle ensuite lehandlerMethod().

Les mappages au niveau type et au niveau méthode ont été traités à deux étapes différentes dans la version Spring avant la version 3.1.

La première étape consistait à sélectionner le contrôleur parDefaultAnnotationHandlerMapping et la deuxième étape consistait à invoquer la méthode réelle parAnnotationMethodHandlerAdapter.

A partir de la version 3.1 de Spring, il n’ya qu’une étape, qui consiste à identifier le contrôleur ainsi que la méthode à utiliser pour traiter la demande.

Définissons une classe de contrôleur simple:

@Controller
public class RequestMappingHandler {

    @RequestMapping("/requestName")
    public ModelAndView getEmployeeName() {
        ModelAndView model = new ModelAndView("Greeting");
        model.addObject("message", "Madhwal");
        return model;
    }
}

Il existe deux manières différentes de configurer cet adaptateur, selon que l'application utilise une configuration basée sur Java ou une configuration basée sur XML.

Examinons la première façon d'utiliser la configuration Java:

@ComponentScan("com.example.spring.controller")
@Configuration
@EnableWebMvc
public class ServletConfig implements WebMvcConfigurer {
    @Bean
    public InternalResourceViewResolver jspViewResolver() {
        InternalResourceViewResolver bean = new InternalResourceViewResolver();
        bean.setPrefix("/WEB-INF/");
        bean.setSuffix(".jsp");
        return bean;
    }
}

Si l'application utilise la configuration XML, il existe deux approches différentes pour configurer cet adaptateur de gestionnaire dans le contexte XML d'application Web. Jetons un œil à la première approche définie dans le fichierspring-servlet_RequestMappingHandlerAdapter.xml:


    

    

    

    
        
        
    

Et voici la deuxième approche:


    

    

    
        
        
    

Cette balise enregistrera automatiquement ces deux classes avec Spring MVC.

Si nous devons personnaliser lesRequestMappingHandlerMapping,, nous devons supprimer cette balise du XML de contexte d'application et la configurer manuellement dans le XML de contexte d'application.

4.5. HttpRequestHandlerAdapter

Cet adaptateur de gestionnaire est utilisé pour les gestionnaires qui traitentHttpRequests. Il implémente l'interfaceHttpRequestHandler, qui contient une seule méthodehandleRequest() pour traiter la requête et générer la réponse.

Le type de retour de cette méthode est void et ne génère pas de type de retourModelAndView tel que produit par d’autres adaptateurs de gestionnaire. Il est essentiellement utilisé pour générer des réponses binaires et ne génère pas de vue à afficher.

5. Lancer l'application

Si l'application est déployée surlocalhost avec le numéro de port8082 et la racine de contexte estspring-mvc-handlers:

http://localhost:8082/spring-mvc-handlers/

6. Conclusion

Dans cet article, nous avons abordé différents types d’adaptateurs de gestionnaires disponibles dans Spring Framework.

La plupart des développeurs s'en tiendront probablement aux valeurs par défaut, mais il vaut la peine de comprendre à quel point le cadre est flexible lorsque nous devons aller au-delà des bases.

Le code source de ce tutoriel se trouve dans le fichierGitHub project.