Guide till Spring Handler Mappings

1. Introduktion

Under våren MVC fungerar DispatcherServlet som främre styrenhet - tar emot alla inkommande HTTP-förfrågningar och bearbetar dem.

Enkelt uttryckt sker behandlingen genom att skicka förfrågningarna till relevant komponent med hjälp av hanteringskartläggningar .

HandlerMapping är ett gränssnitt som definierar en mappning mellan förfrågningar och hanterarobjekt. Medan Spring MVC-ramverk ger några färdiga implementeringar, kan gränssnittet implementeras av utvecklare för att tillhandahålla anpassad kartläggningsstrategi.

Den här artikeln diskuterar några av implementeringarna från Spring MVC, nämligen BeanNameUrlHandlerMapping , SimpleUrlHandlerMapping , ControllerClassNameHandlerMapping , deras konfiguration och skillnaderna mellan dem.

2. BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping är standardimporten för HandlerMapping . BeanNameUrlHandlerMapping kartlägger begäran om webbadresser till bönor med samma namn.

Denna speciella kartläggning har stöd för direktmatchning och även för mönstermatchning med "*" -mönstret.

Till exempel kan en inkommande URL “/ foo” mappas till en böna som heter “/ foo” . Ett exempel på mönstermappning är mappningsförfrågningar till “/ foo *” till bönor med namn som börjar med “/ foo” som “/ foo2 /” eller “/ fooOne /” .

Låt oss konfigurera detta exempel här och registrera en bean-controller som hanterar förfrågningar till “/ beanNameUrl” :

@Configuration public class BeanNameUrlHandlerMappingConfig { @Bean BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() { return new BeanNameUrlHandlerMapping(); } @Bean("/beanNameUrl") public WelcomeController welcome() { return new WelcomeController(); } }

Detta är XML-ekvivalenten för ovanstående Java-baserade konfiguration:

Det är viktigt att notera att det i båda dessa konfigurationer inte krävs att definiera en böna för BeanNameUrlHandlerMapping eftersom den tillhandahålls av Spring MVC. Att ta bort den här bönedefinitionen orsakar inga problem och förfrågningar kommer fortfarande att mappas till deras registrerade hanterarbönor.

Nu vidarebefordras alla förfrågningar till “/ beanNameUrl” av DispatcherServlet till “ WelcomeController ”. WelcomeController returnerar ett visningsnamn som heter " välkommen ".

Följande kod testar den här konfigurationen och ser till att rätt vynamn returneras:

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

3. SimpleUrlHandlerMapping

Därefter är SimpleUrlHandlerMapping den mest flexibla implementeringen av HandlerMapping . Det möjliggör direkt och deklarativ mappning mellan antingen böninstanser och URL: er eller mellan bönamn och URL: er.

Låt oss kartlägga förfrågningar "/ simpleUrlWelcome" och "/ * / simpleUrlWelcome" till "välkomst" -bönan:

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

Alternativt är här motsvarande XML-konfiguration:

   /simpleUrlWelcome=welcome /*/simpleUrlWelcome=welcome    

Det är viktigt att notera att i XML-konfigurationen måste en mappning mellan "" taggen göras i en form som accepteras av klassen java.util.Properties och den ska följa syntaxen: path = Handler_Bean_Name .

Webbadressen ska normalt ha en ledande snedstreck, men om sökvägen inte börjar med en, lägger Spring MVC till den automatiskt.

Ett annat sätt att konfigurera ovanstående exempel i XML är att använda egenskapen "rekvisita" istället för "värde" . Rekvisita har en lista med "prop" -tagg där var och en definierar en mappning där "nyckel" hänvisas till den mappade URL: n och värdet på taggen är namnet på bönan.

   welcome welcome   

Följande testfall ser till att förfrågningar till "/ simpleUrlWelcome " hanteras av " WelcomeController" som returnerar ett visningsnamn som heter "välkommen" :

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

4. ControllerClassNameHandlerMapping (borttagen våren 5)

Den ControllerClassNameHandlerMapping kartor URL till en registrerad controller böna (eller en regulator kommenterad med @Controller annotation) som har eller börjar med samma namn.

Det kan vara bekvämare i många scenarier, särskilt för enkla kontrollerimplementeringar som hanterar en enskild begäranstyp. Konventionen som används av Spring MVC är att använda klassens namn och ta bort suffixet "Controller" , ändra sedan namnet till gemener och returnera det som mappningen med ett ledande "/" .

Till exempel skulle "WelcomeController" återgå som mappning till "/ welcome *" , dvs till alla webbadresser som börjar med "welcome" .

Låt oss konfigurera ControllerClassNameHandlerMapping :

@Configuration public class ControllerClassNameHandlerMappingConfig { @Bean public ControllerClassNameHandlerMapping controllerClassNameHandlerMapping() { return new ControllerClassNameHandlerMapping(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }

Notera att ControllerClassNameHandlerMapping är föråldrat från Spring 4,3 till förmån för anteckning driven handler metoder.

En annan viktig anmärkning är att styrenhetens namn alltid kommer att returneras i gemener (minus suffixet "Controller"). Så om vi har en styrenhet som heter “ WelcomeBaeldungController ”, hanterar den bara förfrågningar till “/ welcomebaeldung” och inte till “/ welcomeBaeldung” .

I både Java config och XML config nedan definierar vi ControllerClassNameHandlerMapping bönor och registrerar bönor för de styrenheter som vi kommer att använda för att hantera förfrågningar. Vi registrerar också en böna av typen "WelcomeController" och den bönan hanterar alla förfrågningar som börjar med "/ welcome" .

Här är motsvarande XML-konfiguration:

När du använder ovanstående konfiguration hanteras förfrågningar om "/ välkomst " av " WelcomeController ".

Följande kod kommer att se till att förfrågningar till “/ welcome *” som “/ welcometest ” hanteras av “WelcomeController” som returnerar ett visningsnamn som heter “ welcome ”:

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

5. Konfigurera prioriteringar

Spring MVC-ramverk tillåter mer än en implementering av HandlerMapping- gränssnittet samtidigt.

Låt oss skapa en konfiguration och registrera två styrenheter, båda mappade till URL “/ välkommen”, endast med hjälp av olika kartläggning och återgivande av olika visningsnamn:

@Configuration public class HandlerMappingDefaultConfig { @Bean("/welcome") public BeanNameHandlerMappingController beanNameHandlerMapping() { return new BeanNameHandlerMappingController(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }

Med ingen registrerad kartläggare för handläggare används en standard BeanNameHandlerMapping . Låt oss hävda detta beteende med testet:

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

Om vi ​​uttryckligen registrerar en annan hanteringskarta, kommer standardmapparen att åsidosättas. Det är dock intressant att se vad som händer när två kartläggare uttryckligen registreras:

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

För att få kontroll över vilken kartläggning som används ställs prioriteringarna in med metoden setOrder (int order) . Denna metod tar en int- parameter där lägre värde betyder högre prioritet.

I XML-konfiguration kan du konfigurera prioriteringar med hjälp av en egenskap som heter "order" :

Låt oss lägga till beställningsegenskaper till hanteringsmappningbönor, via följande beanNameUrlHandlerMapping.setOrder (1) och simpleUrlHandlerMapping.setOrder (0). Det lägre värdet på order egenskapen återspeglar högre prioritet. Låt oss hävda nytt beteende med testet:

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

När du testar konfigurationen ovan ser du att förfrågningar om "/ välkommen" kommer att hanteras av SimpleUrlHandlerMapping bean som anropar en SimpleUrlHandlerController och returnerar enkel url-handler-mapping- vy. Vi kan enkelt konfigurera BeanNameHandlerMapping så att de har företräde genom att justera värdena för orderegenskapen.

6. Sammanfattning

I den här artikeln diskuterade vi hur URL-mappning hanteras i Spring MVC-ramverk genom att utforska de olika implementeringarna i ramverket.

Koden som följer med den här artikeln finns på GitHub.