Guide des mappages de gestionnaires de printemps

Guide des mappages de gestionnaires de printemps

1. introduction

Dans Spring MVC, leDispatcherServlet agit commefront controller - recevant toutes les requêtes HTTP entrantes et les traitant.

En termes simples, le traitement se produit en passant les requêtes au composant concernéwith the help of handler mappings.

HandlerMapping est une interface qui définit un mappage entre les requêtes et leshandler objects. Bien que la structure Spring MVC offre des implémentations prêtes à l'emploi, l'interface peut être mise en œuvre par les développeurs pour fournir une stratégie de mappage personnalisée.

Cet article décrit certaines des implémentations fournies par Spring MVC, à savoirBeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,ControllerClassNameHandlerMapping, leur configuration et les différences entre elles.

2. BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping est l'implémentation par défaut deHandlerMapping. BeanNameUrlHandlerMapping mappe les URL de requête aux beans avec le même nom.

Ce mappage particulier prend en charge la correspondance directe de noms et également la correspondance de modèles à l'aide du modèle «*».

Par exemple, une URL entrante“/foo” correspond à un bean appelé“/foo”. Un exemple de mappage de modèles est le mappage des requêtes vers“/foo*” vers des beans avec des noms commençant par“/foo” comme“/foo2/” ou“/fooOne/”.

Configurons cet exemple ici et enregistrons un contrôleur de bean qui gère les requêtes adressées à“/beanNameUrl”:

@Configuration
public class BeanNameUrlHandlerMappingConfig {
    @Bean
    BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() {
        return new BeanNameUrlHandlerMapping();
    }

    @Bean("/beanNameUrl")
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

C'est l'équivalent XML de la configuration basée sur Java ci-dessus:


Il est important de noter que dans ces deux configurations,defining a bean for BeanNameUrlHandlerMapping is not required tel qu’il est fourni par Spring MVC. La suppression de cette définition de bean ne posera aucun problème et les demandes seront toujours mappées sur leurs beans de gestionnaire enregistrés.

Désormais, toutes les requêtes adressées à“/beanNameUrl” seront transmises parDispatcherServlet à «WelcomeController». WelcomeController renvoie un nom de vue appelé «welcome».

Le code suivant teste cette configuration et s'assure que le nom de vue correct est renvoyé:

public class BeanNameMappingConfigTest {
    // ...

    @Test
    public void whenBeanNameMapping_thenMappedOK() {
        mockMvc.perform(get("/beanNameUrl"))
          .andExpect(status().isOk())
          .andExpect(view().name("welcome"));
    }
}

3. SimpleUrlHandlerMapping

Ensuite,SimpleUrlHandlerMapping est l'implémentation deHandlerMapping la plus flexible. Il permet un mappage direct et déclaratif entre des instances de beans et des URL ou entre des noms de beans et des URL.

Mappons les requêtes“/simpleUrlWelcome” et“/*/simpleUrlWelcome” au bean“welcome”:

@Configuration
public class SimpleUrlHandlerMappingConfig {

    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping
          = new SimpleUrlHandlerMapping();

        Map urlMap = new HashMap<>();
        urlMap.put("/simpleUrlWelcome", welcome());
        simpleUrlHandlerMapping.setUrlMap(urlMap);

        return simpleUrlHandlerMapping;
    }

    @Bean
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

Sinon, voici la configuration XML équivalente:


    
        
            /simpleUrlWelcome=welcome
            /*/simpleUrlWelcome=welcome
        
    

Il est important de noter que dans la configuration XML, un mappage entre la balise“<value>” doit être effectué sous une forme acceptée par la classejava.util.Properties et doit suivre la syntaxe:path= Handler_Bean_Name.

L'URL doit normalement être précédée d'une barre oblique, cependant, si le chemin ne commence pas par une, Spring MVC l'ajoute automatiquement.

Une autre façon de configurer l'exemple ci-dessus en XML consiste à utiliser la propriété“props” au lieu de“value”. Props ont une liste de balises“prop” où chacune définit un mappage où“key” fait référence à l'URL mappée et la valeur de la balise est le nom du bean.


    
        
            welcome
            welcome
        
    

Le scénario de test suivant garantit que les requêtes adressées à «/simpleUrlWelcome» sont gérées par «WelcomeController” qui renvoie un nom de vue appelé“welcome”:

public class SimpleUrlMappingConfigTest {
    // ...

    @Test
    public void whenSimpleUrlMapping_thenMappedOK() {
        mockMvc.perform(get("/simpleUrlWelcome"))
          .andExpect(status().isOk())
          .andExpect(view().name("welcome"));
    }
}

4. ControllerClassNameHandlerMapping (supprimé au printemps 5)

LeControllerClassNameHandlerMapping mappe l'URL à un bean contrôleur enregistré (ou un contrôleur annoté avec l'annotation@Controller) qui a, ou commence par, le même nom.

Cela peut être plus pratique dans de nombreux scénarios, en particulier pour les implémentations de contrôleurs simples qui gèrent un seul type de requête. La convention utilisée par Spring MVC est d'utiliser le nom de la classe et de supprimer le suffixe“Controller”, puis de changer le nom en minuscules et de le renvoyer en tant que mappage avec un“/” en tête.

Par exemple,“WelcomeController” retournerait en tant que mappage vers“/welcome*”, c'est-à-dire à toute URL commençant par“welcome”.

ConfiguronsControllerClassNameHandlerMapping:

@Configuration
public class ControllerClassNameHandlerMappingConfig {

    @Bean
    public ControllerClassNameHandlerMapping controllerClassNameHandlerMapping() {
        return new ControllerClassNameHandlerMapping();
    }

    @Bean
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

Notez queControllerClassNameHandlerMapping estdeprecated from Spring 4.3 en faveur des méthodes de gestion des annotations.

Une autre remarque importante est que les noms de contrôleurs seront toujours retournés en minuscules (moins le suffixe «Controller»). Donc, si nous avons un contrôleur appelé «WelcomeexampleController», il ne traitera que les requêtes vers“/welcomeexample” et non vers“/welcomeexample”.

Dans la configuration Java et la configuration XML ci-dessous, nous définissons le beanControllerClassNameHandlerMapping et enregistrons les beans pour les contrôleurs que nous utiliserons pour gérer les requêtes. Nous enregistrons également un bean de type“WelcomeController” et ce bean gérera toutes les requêtes commençant par“/welcome”.

Voici la configuration XML équivalente:


Lors de l'utilisation de la configuration ci-dessus, les requêtes adressées à «/welcome» seront traitées par les «WelcomeController».

Le code suivant garantira que les requêtes adressées à «/welcome *» telles que «/welcometest» soient gérées par «WelcomeController» qui renvoie un nom de vue appelé «welcome»:

public class ControllerClassNameHandlerMappingTest {
    // ...

    @Test
    public void whenControllerClassNameMapping_thenMappedOK() {
        mockMvc.perform(get("/welcometest"))
          .andExpect(status().isOk())
          .andExpect(view().name("welcome"));
    }
}

5. Configurer les priorités

Le framework Spring MVC permet plus d'une implémentation de l'interfaceHandlerMapping en même temps.

Créons une configuration et enregistrons deux contrôleurs, tous deux mappés sur l'URL «/ welcome», uniquement à l'aide d'un mappage différent et renvoyant des noms de vue différents:

@Configuration
public class HandlerMappingDefaultConfig {

    @Bean("/welcome")
    public BeanNameHandlerMappingController beanNameHandlerMapping() {
        return new BeanNameHandlerMappingController();
    }

    @Bean
    public WelcomeController welcome() {
        return new WelcomeController();
    }
}

En l'absence de mappeur de gestionnaire explicite enregistré, unBeanNameHandlerMapping par défaut sera utilisé. Laissez-nous affirmer ce comportement avec le test:

@Test
public void whenConfiguringPriorities_thenMappedOK() {
    mockMvc.perform(get("/welcome"))
      .andExpect(status().isOk())
      .andExpect(view().name("bean-name-handler-mapping"));
}

Si nous enregistrons explicitement un mappeur de gestionnaire différent, le mappeur par défaut sera remplacé. Cependant, il est intéressant de voir ce qui se passe lorsque deux mappeurs sont explicitement enregistrés:

@Configuration
public class HandlerMappingPrioritiesConfig {

    @Bean
    BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() {
        BeanNameUrlHandlerMapping beanNameUrlHandlerMapping
          = new BeanNameUrlHandlerMapping();
        return beanNameUrlHandlerMapping;
    }

    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping() {
        SimpleUrlHandlerMapping simpleUrlHandlerMapping
          = new SimpleUrlHandlerMapping();
        Map urlMap = new HashMap<>();
        urlMap.put("/welcome", simpleUrlMapping());
        simpleUrlHandlerMapping.setUrlMap(urlMap);
        return simpleUrlHandlerMapping;
    }

    @Bean
    public SimpleUrlMappingController simpleUrlMapping() {
        return new SimpleUrlMappingController();
    }

    @Bean("/welcome")
    public BeanNameHandlerMappingController beanNameHandlerMapping() {
        return new BeanNameHandlerMappingController();
    }
}

Pour obtenir le contrôle sur le mappage utilisé, les priorités sont définies à l'aide de la méthodesetOrder(int order). Cette méthode prend un paramètreint où une valeur inférieure signifie une priorité plus élevée.

Dans la configuration XML, vous pouvez configurer les priorités en utilisant une propriété appelée“order”:


    

Ajoutons les propriétésorder aux beans de mappage de gestionnaire, via lesbeanNameUrlHandlerMapping.setOrder(1) etsimpleUrlHandlerMapping.setOrder(0). suivants. La valeur inférieure de la propriétéorder reflète une priorité plus élevée. Laissez-nous affirmer un nouveau comportement avec le test:

@Test
public void whenConfiguringPriorities_thenMappedOK() {
    mockMvc.perform(get("/welcome"))
      .andExpect(status().isOk())
      .andExpect(view().name("simple-url-handler-mapping"));
}

Lors du test de la configuration ci-dessus, vous voyez que les requêtes adressées à“/welcome” seront gérées par le beanSimpleUrlHandlerMapping qui appelle unSimpleUrlHandlerController et renvoie la vuesimple-url-handler-mapping. Nous pouvons facilement configurer leBeanNameHandlerMapping pour qu'il prenne la priorité en ajustant en conséquence les valeurs de la propriétéorder.

6. Conclusion

Dans cet article, nous avons expliqué comment le mappage des URL est géré dans le framework Spring MVC en explorant les différentes implémentations du framework.

Le code accompagnant cet article se trouveover on GitHub.