1. Въведение
В Spring MVC DispatcherServlet действа като преден контролер - приема всички входящи HTTP заявки и ги обработва.
Най-просто казано, обработката се извършва чрез предаване на заявките към съответния компонент с помощта на манипулатори на манипулатори .
HandlerMapping е интерфейс, който дефинира картографиране между заявки и обекти на манипулатора. Докато Spring MVC рамката предоставя някои готови реализации, интерфейсът може да бъде внедрен от разработчиците, за да предостави персонализирана стратегия за картографиране.
Тази статия разглежда някои от внедренията, предоставени от Spring MVC, а именно BeanNameUrlHandlerMapping , SimpleUrlHandlerMapping , ControllerClassNameHandlerMapping , тяхната конфигурация и разликите между тях.
2. BeanNameUrlHandlerMapping
BeanNameUrlHandlerMapping е по подразбиране HandlerMapping изпълнението. BeanNameUrlHandlerMapping картографира URL адреси на заявки към зърна със същото име.
Това конкретно картографиране има поддръжка за директно съвпадение на имена, както и за съвпадение на шаблони, използвайки модела “*”.
Например, входящ URL адрес „/ foo“ се преобразува в боб, наречен „/ foo“ . Пример за картографиране на шаблони е картографиране на заявки към „/ foo *“ към зърна с имена, започващи с „/ foo“ като „/ foo2 /“ или „/ fooOne /“ .
Нека да конфигурираме този пример тук и да регистрираме bean контролер, който обработва заявки към “/ beanNameUrl” :
@Configuration public class BeanNameUrlHandlerMappingConfig { @Bean BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() { return new BeanNameUrlHandlerMapping(); } @Bean("/beanNameUrl") public WelcomeController welcome() { return new WelcomeController(); } }
Това е XML еквивалент на горната конфигурация, базирана на Java:
Важно е да се отбележи, че и в двете конфигурации дефинирането на боб за BeanNameUrlHandlerMapping не се изисква, тъй като се предоставя от Spring MVC. Премахването на тази дефиниция на боб няма да доведе до проблеми и заявките все още ще бъдат картографирани в регистрираните им обработващи зърна.
Сега всички заявки към „/ beanNameUrl“ ще бъдат препратени от DispatcherServlet към „ WelcomeController “. WelcomeController връща име на изглед, наречен „ добре дошъл “.
Следният код тества тази конфигурация и се уверява, че е върнато правилното име на изгледа:
public class BeanNameMappingConfigTest { // ... @Test public void whenBeanNameMapping_thenMappedOK() { mockMvc.perform(get("/beanNameUrl")) .andExpect(status().isOk()) .andExpect(view().name("welcome")); } }
3. SimpleUrlHandlerMapping
След това SimpleUrlHandlerMapping е най-гъвкавото изпълнение на HandlerMapping . Той позволява директно и декларативно картографиране между екземпляри на боб и URL адреси или между имена на боб и URL адреси.
Нека картографираме заявките „/ simpleUrlWelcome“ и „/ * / simpleUrlWelcome“ към боб „добре дошли“ :
@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(); } }
Алтернативно, ето еквивалентната XML конфигурация:
/simpleUrlWelcome=welcome /*/simpleUrlWelcome=welcome
Важно е да се отбележи, че в XML конфигурацията, съпоставянето между таг “” трябва да се извърши във форма, приета от клас java.util.Properties и трябва да следва синтаксиса: path = Handler_Bean_Name .
URL адресът обикновено трябва да бъде с водеща наклонена черта, но ако пътят не започва с такъв, Spring MVC го добавя автоматично.
По-различен начин за конфигуриране на горния пример в XML е използването на свойството “props” вместо “value” . Реквизитите имат списък с “prop” таг, където всеки дефинира картографиране, където “ключ” се отнася до картографирания URL адрес, а стойността на маркера е името на боб.
welcome welcome
Следният тестов случай гарантира, че заявките за “/ simpleUrlWelcome ” се обработват от “ WelcomeController”, който връща име на изглед, наречен “добре дошли” :
public class SimpleUrlMappingConfigTest { // ... @Test public void whenSimpleUrlMapping_thenMappedOK() { mockMvc.perform(get("/simpleUrlWelcome")) .andExpect(status().isOk()) .andExpect(view().name("welcome")); } }
4. ControllerClassNameHandlerMapping (премахнато през пролетта 5)
В ControllerClassNameHandlerMapping карти URL на регистриран администратор боб (или контролер отбелязва с @Controller анотация), който има, или започва с, със същото име.
Може да бъде по-удобно в много сценарии, особено за прости реализации на контролер, които обработват един тип заявка. Конвенцията, използвана от Spring MVC, е да се използва името на класа и да се премахне суфиксът „Controller“ , след което да се промени името с малки букви и да се върне като картографиране с водеща „/“ .
Например “WelcomeController” ще се върне като преобразуване в “/ welcome *” , т.е. към всеки URL, който започва с “добре дошли” .
Нека конфигурираме ControllerClassNameHandlerMapping :
@Configuration public class ControllerClassNameHandlerMappingConfig { @Bean public ControllerClassNameHandlerMapping controllerClassNameHandlerMapping() { return new ControllerClassNameHandlerMapping(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }
Обърнете внимание, че ControllerClassNameHandlerMapping е оттеглено от Spring 4.3 в полза на методите за обработка, управлявани от анотации.
Друга важна бележка е, че имената на контролерите винаги ще се връщат с малки букви (минус суфиксът „Controller“). Така че, ако имаме контролер, наречен „ WelcomeBaeldungController “, той ще обработва заявки само към „/ welcomebaeldung“, а не към „/ welcomeBaeldung“ .
Както в Java config, така и в XML config по-долу, дефинираме ControllerClassNameHandlerMapping bean и регистрираме зърна за контролерите, които ще използваме за обработка на заявки. Също така регистрираме боб от тип “WelcomeController” и този боб ще обработва всички заявки, които започват с “/ добре дошли” .
Ето еквивалентната XML конфигурация:
Когато използвате горната конфигурация, заявките за „/ добре дошли “ ще бъдат обработвани от „ WelcomeController “.
Следващият код ще гарантира, че заявките за „/ добре дошли *”, като „/ добре дошли ”, се обработват от „WelcomeController”, който връща име на изглед, наречен „ добре дошъл ”:
public class ControllerClassNameHandlerMappingTest { // ... @Test public void whenControllerClassNameMapping_thenMappedOK() { mockMvc.perform(get("/welcometest")) .andExpect(status().isOk()) .andExpect(view().name("welcome")); } }
5. Конфигуриране на приоритети
Spring MVC framework allows more than one implementation of HandlerMapping interface at the same time.
Let us create a configuration and register two controllers, both mapped to URL “/welcome”, only using different mapping and returning different view names:
@Configuration public class HandlerMappingDefaultConfig { @Bean("/welcome") public BeanNameHandlerMappingController beanNameHandlerMapping() { return new BeanNameHandlerMappingController(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }
With no explicit handler mapper registered, a default BeanNameHandlerMapping will be used. Let us assert this behaviour with the test:
@Test public void whenConfiguringPriorities_thenMappedOK() { mockMvc.perform(get("/welcome")) .andExpect(status().isOk()) .andExpect(view().name("bean-name-handler-mapping")); }
If we explicitly register a different handler mapper, the default mapper will be overridden. However, it is interesting to see what happens when two mappers are explicitly registered:
@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(); } }
To get the control over which mapping is used, the priorities are set using setOrder(int order) method. This method takes one int parameter where lower value mean higher priority.
In XML configuration you can configure priorities by using a property called “order”:
Let us add order properties to handler mapping beans, via following beanNameUrlHandlerMapping.setOrder(1) and simpleUrlHandlerMapping.setOrder(0). The lower value of the order property reflects higher precedence. Let us assert new behaviour with the test:
@Test public void whenConfiguringPriorities_thenMappedOK() { mockMvc.perform(get("/welcome")) .andExpect(status().isOk()) .andExpect(view().name("simple-url-handler-mapping")); }
Когато тествате горната конфигурация, виждате, че заявките за “/ добре дошли” ще бъдат обработвани от Bean SimpleUrlHandlerMapping, който извиква SimpleUrlHandlerController и връща изглед за картографиране на simple-url-handler-mapping . Можем лесно да конфигурираме BeanNameHandlerMapping да има приоритет, като коригираме съответно стойностите на свойството order .
6. Заключение
В тази статия обсъдихме как се извършва обработването на URL адреси в Spring MVC framework чрез проучване на различните реализации в рамката.
Кодът, придружаващ тази статия, може да бъде намерен в GitHub.