1. введение
В Spring MVC DispatcherServlet действует как передний контроллер – принимает все входящие HTTP-запросы и обрабатывает их.
Проще говоря, обработка происходит путем передачи запросов соответствующему компоненту с помощью сопоставлений обработчиков .
Сопоставление обработчиков – это интерфейс, который определяет сопоставление между запросами и объектами обработчиков . В то время как Spring MVC framework предоставляет некоторые готовые реализации, интерфейс может быть реализован разработчиками для обеспечения индивидуальной стратегии отображения.
В этой статье рассматриваются некоторые реализации, предоставляемые Spring MVC, а именно BeanNameUrlHandlerMapping , SimpleUrlHandlerMapping , ControllerClassNameHandlerMapping , их конфигурация и различия между ними.
2. BeanNameUrlHandlerMapping
BeanNameUrlHandlerMapping является реализацией по умолчанию HandlerMapping . BeanNameUrlHandlerMapping сопоставляет URL-адреса запросов к бобам с тем же именем.
Это конкретное сопоставление поддерживает прямое сопоставление имен, а также сопоставление шаблонов с использованием шаблона”*”.
Например, входящий URL-адрес “/foo” сопоставляется с бобом с именем “/foo” . Примером сопоставления шаблонов является сопоставление запросов к “/foo*” бобам с именами, начинающимися с “/foo” like “/foo2/” или “/food One/” .
Давайте настроим этот пример здесь и зарегистрируем бобовый контроллер, который обрабатывает запросы к “/beannameurlha” :
@Configuration public class BeanNameUrlHandlerMappingConfig { @Bean BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() { return new BeanNameUrlHandlerMapping(); } @Bean("/beanNameUrl") public WelcomeController welcome() { return new WelcomeController(); } }
Это XML-эквивалент вышеупомянутой конфигурации на основе Java:
Важно отметить, что в обеих этих конфигурациях определение компонента для BeanNameUrlHandlerMapping не требуется , как это предусмотрено Spring MVC. Удаление этого определения компонента не вызовет никаких проблем, и запросы по-прежнему будут сопоставляться с их зарегистрированными компонентами обработчика.
Теперь все запросы на “/beannameurlha” будут перенаправляться DispatcherServlet на ” WelcomeController “. WelcomeController возвращает имя представления ” welcome “.
Следующий код проверяет эту конфигурацию и гарантирует, что будет возвращено правильное имя представления:
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-адресами.
Давайте сопоставим запросы “/simple Url Welcome” и “/*/simple Url Welcome” с “welcome” bean:
@Configuration public class SimpleUrlHandlerMappingConfig { @Bean public SimpleUrlHandlerMapping simpleUrlHandlerMapping() { SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping(); MapurlMap = 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.Свойства класс и он должен следовать синтаксису: path= Handler_Bean_Name .
URL-адрес обычно должен быть с ведущей косой чертой, однако, если путь не начинается с нее, Spring MVC добавляет его автоматически.
Другой способ настроить приведенный выше пример в XML-это использовать свойство “props” вместо “value” . Props иметь список “prop” тегов, где каждый определяет сопоставление, где “ключ” ссылается на сопоставленный URL-адрес, а значение тега является именем компонента.
welcome welcome
Следующий тестовый случай гарантирует, что запросы на “/ простой URL-адрес приветствия “обрабатываются” 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-адресом, который начинается с “welcome” .
Давайте настроим ControllerClassNameHandlerMapping :
@Configuration public class ControllerClassNameHandlerMappingConfig { @Bean public ControllerClassNameHandlerMapping controllerClassNameHandlerMapping() { return new ControllerClassNameHandlerMapping(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }
Обратите внимание, что ControllerClassNameHandlerMapping устарел с Spring 4.3 в пользу методов обработчика, управляемых аннотациями.
Еще одно важное замечание заключается в том, что имена контроллеров всегда будут возвращаться в нижнем регистре (за вычетом суффикса “Контроллер”). Поэтому, если у нас есть контроллер под названием ” Welcome Baeldung Controller “, он будет обрабатывать запросы только к “/welcomebaeldung” , а не к “/welcomeBaeldung” .
Как в конфигурации Java, так и в конфигурации XML ниже мы определяем ControllerClassNameHandlerMapping bean и регистрируем бобы для контроллеров, которые мы будем использовать для обработки запросов. Мы также регистрируем компонент типа “WelcomeController” , и этот компонент будет обрабатывать все запросы, начинающиеся с “/welcome” .
Вот эквивалентная конфигурация XML:
При использовании приведенной выше конфигурации запросы на “/ welcome “будут обрабатываться” WelcomeController “.
Следующий код гарантирует, что запросы на “/ welcome *”, такие как “/ welcome test “, обрабатываются “WelcomeController”, который возвращает имя представления ” welcome “:
public class ControllerClassNameHandlerMappingTest { // ... @Test public void whenControllerClassNameMapping_thenMappedOK() { mockMvc.perform(get("/welcometest")) .andExpect(status().isOk()) .andExpect(view().name("welcome")); } }
5. Настройка Приоритетов
Spring MVC framework позволяет одновременно использовать несколько реализаций интерфейса HandlerMapping .
Давайте создадим конфигурацию и зарегистрируем два контроллера, оба из которых сопоставлены с URL-адресом “/welcome”, только используя разные сопоставления и возвращая разные имена представлений:
@Configuration public class HandlerMappingDefaultConfig { @Bean("/welcome") public BeanNameHandlerMappingController beanNameHandlerMapping() { return new BeanNameHandlerMappingController(); } @Bean public WelcomeController welcome() { return new WelcomeController(); } }
Если не зарегистрирован явный сопоставитель обработчиков, будет использоваться сопоставление обработчика имен Bean по умолчанию|/. Давайте подтвердим это поведение с помощью теста:
@Test public void whenConfiguringPriorities_thenMappedOK() { mockMvc.perform(get("/welcome")) .andExpect(status().isOk()) .andExpect(view().name("bean-name-handler-mapping")); }
Если мы явно зарегистрируем другой сопоставитель обработчиков, сопоставитель по умолчанию будет переопределен. Однако интересно посмотреть, что происходит, когда два картографа явно зарегистрированы:
@Configuration public class HandlerMappingPrioritiesConfig { @Bean BeanNameUrlHandlerMapping beanNameUrlHandlerMapping() { BeanNameUrlHandlerMapping beanNameUrlHandlerMapping = new BeanNameUrlHandlerMapping(); return beanNameUrlHandlerMapping; } @Bean public SimpleUrlHandlerMapping simpleUrlHandlerMapping() { SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping(); MapurlMap = 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(); } }
Чтобы получить контроль над тем, какое отображение используется, приоритеты устанавливаются с помощью метода setOrder(int order) . Этот метод принимает один параметр int , где меньшее значение означает более высокий приоритет.
В конфигурации XML вы можете настроить приоритеты с помощью свойства “order” :
Давайте добавим order свойства к компонентам сопоставления обработчиков, следуя BeanNameUrlHandlerMapping.set Order(1) и simpleUrlHandlerMapping.setOrder(0). Меньшее значение свойства order отражает более высокий приоритет. Давайте утвердим новое поведение с помощью теста:
@Test public void whenConfiguringPriorities_thenMappedOK() { mockMvc.perform(get("/welcome")) .andExpect(status().isOk()) .andExpect(view().name("simple-url-handler-mapping")); }
При тестировании приведенной выше конфигурации вы видите, что запросы к “/welcome” будут обрабатываться SimpleUrlHandlerMapping bean, который вызывает SimpleUrlHandlerController и возвращает simple-url-handler-mapping view. Мы можем легко настроить отображение обработчика имен Bean на приоритет, соответствующим образом настроив значения свойства order .
6. Заключение
В этой статье мы обсудили, как сопоставление URL-адресов обрабатывается в Spring MVC framework, изучив различные реализации в рамках.
Код, сопровождающий эту статью, можно найти на GitHub .