Leitfaden für Spring-Handler-Zuordnungen

Leitfaden für Spring-Handler-Zuordnungen

1. Einführung

In Spring MVC fungiertDispatcherServlet alsfront controller - empfängt alle eingehenden HTTP-Anforderungen und verarbeitet sie.

Einfach ausgedrückt erfolgt die Verarbeitung durch Übergeben der Anforderungen an die relevante Komponentewith the help of handler mappings.

HandlerMapping ist eine Schnittstelle, die eine Zuordnung zwischen Anforderungen undhandler objects definiert. Während das Spring MVC-Framework einige vorgefertigte Implementierungen bietet, kann die Schnittstelle von Entwicklern implementiert werden, um eine angepasste Zuordnungsstrategie bereitzustellen.

Dieser Artikel beschreibt einige der von Spring MVC bereitgestellten Implementierungen, nämlichBeanNameUrlHandlerMapping,SimpleUrlHandlerMapping,ControllerClassNameHandlerMapping, ihre Konfiguration und die Unterschiede zwischen ihnen.

2. BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping ist die Standardimplementierung vonHandlerMapping. BeanNameUrlHandlerMapping ordnet Anforderungs-URLs Beans mit demselben Namen zu.

Diese spezielle Zuordnung unterstützt den direkten Namensabgleich sowie den Musterabgleich mithilfe des Musters „*“.

Beispielsweise wird eine eingehende URL“/foo” einer Bean mit dem Namen“/foo” zugeordnet. Ein Beispiel für die Musterzuordnung ist die Zuordnung von Anforderungen zu“/foo*” zu Beans mit Namen, die mit“/foo” beginnen, wie“/foo2/” oder“/fooOne/”.

Konfigurieren Sie dieses Beispiel hier und registrieren Sie einen Bean-Controller, der Anforderungen an“/beanNameUrl” verarbeitet:

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

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

Dies ist das XML-Äquivalent der obigen Java-basierten Konfiguration:


Es ist wichtig zu beachten, dass in beiden Konfigurationendefining a bean for BeanNameUrlHandlerMapping is not required wie von Spring MVC bereitgestellt werden. Das Entfernen dieser Bean-Definition verursacht keine Probleme, und Anforderungen werden weiterhin ihren registrierten Handler-Beans zugeordnet.

Jetzt werden alle Anfragen an“/beanNameUrl” vonDispatcherServlet an „WelcomeController“ weitergeleitet. WelcomeController gibt einen Ansichtsnamen mit dem Namen "welcome" zurück.

Der folgende Code testet diese Konfiguration und stellt sicher, dass der richtige Ansichtsname zurückgegeben wird:

public class BeanNameMappingConfigTest {
    // ...

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

3. SimpleUrlHandlerMapping

Als nächstes istSimpleUrlHandlerMapping die flexibelste Implementierung vonHandlerMapping. Es ermöglicht eine direkte und deklarative Zuordnung zwischen Bean-Instanzen und URLs oder zwischen Bean-Namen und URLs.

Ordnen wir die Anforderungen“/simpleUrlWelcome” und“/*/simpleUrlWelcome” der“welcome”-Bean zu:

@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();
    }
}

Alternativ finden Sie hier die entsprechende XML-Konfiguration:


    
        
            /simpleUrlWelcome=welcome
            /*/simpleUrlWelcome=welcome
        
    

Es ist wichtig zu beachten, dass in der XML-Konfiguration eine Zuordnung zwischen dem Tag“<value>”in einer Form erfolgen muss, die von der Klassejava.util.Propertiesakzeptiert wird, und der Syntax folgen sollte:path= Handler_Bean_Name.

Die URL sollte normalerweise mit einem führenden Schrägstrich versehen sein. Wenn der Pfad jedoch nicht mit einem beginnt, fügt Spring MVC ihn automatisch hinzu.

Eine andere Möglichkeit, das obige Beispiel in XML zu konfigurieren, besteht darin, die Eigenschaft“props” anstelle von“value” zu verwenden. Props haben eine Liste von“prop” Tags, wobei jedes eine Zuordnung definiert, wobei“key” auf die zugeordnete URL verweist und der Wert des Tags der Name der Bean ist.


    
        
            welcome
            welcome
        
    

Der folgende Testfall stellt sicher, dass Anforderungen an "/simpleUrlWelcome" von "WelcomeController”" verarbeitet werden, die einen Ansichtsnamen mit dem Namen“welcome” zurückgeben:

public class SimpleUrlMappingConfigTest {
    // ...

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

4. ControllerClassNameHandlerMapping (im Frühjahr 5 entfernt)

DerControllerClassNameHandlerMapping ordnet die URL einer registrierten Controller-Bean zu (oder einem Controller, der mit der Annotation@Controller versehen ist), die denselben Namen hat oder mit diesem beginnt.

Dies kann in vielen Szenarien praktischer sein, insbesondere bei einfachen Controller-Implementierungen, die einen einzelnen Anforderungstyp verarbeiten. Die von Spring MVC verwendete Konvention besteht darin, den Namen der Klasse zu verwenden und das Suffix“Controller” zu entfernen, dann den Namen in Kleinbuchstaben zu ändern und ihn als Zuordnung mit einem führenden“/” zurückzugeben.

Zum Beispiel würde“WelcomeController” als Abbildung auf“/welcome*” zurückkehren, d.h. zu einer beliebigen URL, die mit“welcome” beginnt.

Konfigurieren wirControllerClassNameHandlerMapping:

@Configuration
public class ControllerClassNameHandlerMappingConfig {

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

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

Beachten Sie, dassControllerClassNameHandlerMappingdeprecated from Spring 4.3 zugunsten von annotationsgesteuerten Handlermethoden ist.

Ein weiterer wichtiger Hinweis ist, dass Controller-Namen immer in Kleinbuchstaben (abzüglich des Suffixes „Controller“) zurückgegeben werden. Wenn wir also einen Controller namens "WelcomeexampleController" haben, werden nur Anfragen an“/welcomeexample” und nicht an“/welcomeexample” verarbeitet.

In der folgenden Java-Konfiguration und XML-Konfiguration definieren wirControllerClassNameHandlerMapping Bean und registrieren Beans für die Controller, die wir zur Verarbeitung von Anforderungen verwenden. Wir registrieren auch eine Bean vom Typ“WelcomeController”, und diese Bean verarbeitet alle Anforderungen, die mit“/welcome” beginnen.

Hier ist die entsprechende XML-Konfiguration:


Bei Verwendung der obigen Konfiguration werden Anforderungen an "/welcome" von "WelcomeController" behandelt.

Der folgende Code stellt sicher, dass Anforderungen an "/welcome *" wie "/welcometest" von "WelcomeController" verarbeitet werden, der einen Ansichtsnamen mit dem Namen "welcome" zurückgibt:

public class ControllerClassNameHandlerMappingTest {
    // ...

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

5. Prioritäten konfigurieren

Das Spring MVC-Framework ermöglicht mehr als eine Implementierung derHandlerMapping-Schnittstelle gleichzeitig.

Erstellen Sie eine Konfiguration und registrieren Sie zwei Controller, die beide der URL "/ welcome" zugeordnet sind und nur unterschiedliche Zuordnungen verwenden und unterschiedliche Ansichtsnamen zurückgeben:

@Configuration
public class HandlerMappingDefaultConfig {

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

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

Wenn kein expliziter Handler-Mapper registriert ist, wird ein Standardwert vonBeanNameHandlerMappingverwendet. Lassen Sie uns dieses Verhalten mit dem Test behaupten:

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

Wenn wir explizit einen anderen Handler-Mapper registrieren, wird der Standard-Mapper überschrieben. Es ist jedoch interessant zu sehen, was passiert, wenn zwei Mapper explizit registriert werden:

@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();
    }
}

Um zu steuern, welche Zuordnung verwendet wird, werden die Prioritäten mithilfe der MethodesetOrder(int order)festgelegt. Diese Methode verwendet einenint-Parameter, wobei ein niedrigerer Wert eine höhere Priorität bedeutet.

In der XML-Konfiguration können Sie Prioritäten mithilfe einer Eigenschaft namens“order” konfigurieren:


    

Fügen wir den Handler-Mapping-Beans die Eigenschaften vonorderhinzu, indem wirbeanNameUrlHandlerMapping.setOrder(1) undsimpleUrlHandlerMapping.setOrder(0). folgen. Der niedrigere Wert der Eigenschaftorder spiegelt eine höhere Priorität wider. Lassen Sie uns mit dem Test ein neues Verhalten behaupten:

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

Wenn Sie die obige Konfiguration testen, sehen Sie, dass Anforderungen an“/welcome” vonSimpleUrlHandlerMapping Bean verarbeitet werden, dieSimpleUrlHandlerController aufruft undsimple-url-handler-mapping Ansicht zurückgibt. Wir können dieBeanNameHandlerMapping einfach so konfigurieren, dass sie Vorrang haben, indem wir die Werte derorder-Eigenschaft entsprechend anpassen.

6. Fazit

In diesem Artikel wurde erläutert, wie die URL-Zuordnung im Spring MVC-Framework gehandhabt wird, indem die verschiedenen Implementierungen im Framework untersucht werden.

Der diesem Artikel beigefügte Code befindet sich inover on GitHub.