Guía de asignaciones de manejadores de resortes

1. Introducción

En Spring MVC, DispatcherServlet actúa como controlador frontal: recibe todas las solicitudes HTTP entrantes y las procesa.

En pocas palabras, el procesamiento se produce pasando las solicitudes al componente relevante con la ayuda de asignaciones de controladores .

HandlerMapping es una interfaz que define un mapeo entre las solicitudes y los objetos del controlador. Si bien el marco Spring MVC proporciona algunas implementaciones listas para usar, los desarrolladores pueden implementar la interfaz para proporcionar una estrategia de mapeo personalizada.

Este artículo describe algunas de las implementaciones proporcionadas por Spring MVC a saber BeanNameUrlHandlerMapping , SimpleUrlHandlerMapping , ControllerClassNameHandlerMapping , su configuración, y las diferencias entre ellos.

2. BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping es la implementación de HandlerMapping predeterminada . Los mapas BeanNameUrlHandlerMapping solicitan URL a beans con el mismo nombre.

Este mapeo en particular tiene soporte para la coincidencia directa de nombres y también para la coincidencia de patrones utilizando el patrón "*".

Por ejemplo, una URL entrante "/ foo" se asigna a un bean llamado "/ foo" . Un ejemplo de mapeo de patrones es mapear solicitudes a “/ foo *” a beans con nombres que comienzan con “/ foo” como “/ foo2 /” o “/ fooOne /” .

Configuremos este ejemplo aquí y registremos un controlador de bean que maneja las solicitudes a "/ beanNameUrl" :

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

Este es el equivalente XML de la configuración basada en Java anterior:

Es importante tener en cuenta que en ambas configuraciones, no es necesario definir un bean para BeanNameUrlHandlerMapping, ya que Spring MVC lo proporciona. La eliminación de esta definición de bean no causará problemas y las solicitudes aún se asignarán a sus beans de controlador registrados.

Ahora todas las solicitudes a “/ beanNameUrl” serán reenviadas por DispatcherServlet a “ WelcomeController ”. WelcomeController devuelve un nombre de vista llamado " bienvenido ".

El siguiente código prueba esta configuración y se asegura de que se devuelva el nombre de vista correcto:

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

3. SimpleUrlHandlerMapping

A continuación, SimpleUrlHandlerMapping es la implementación de HandlerMapping más flexible . Permite el mapeo directo y declarativo entre instancias de bean y URL o entre nombres de bean y URL.

Asignemos las solicitudes "/ simpleUrlWelcome" y "/ * / simpleUrlWelcome" al 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(); } }

Alternativamente, aquí está la configuración XML equivalente:

   /simpleUrlWelcome=welcome /*/simpleUrlWelcome=welcome    

Es importante tener en cuenta que en la configuración XML, se debe realizar un mapeo entre la etiqueta “” en un formato aceptado por la clase java.util.Properties y debe seguir la sintaxis: ruta = Handler_Bean_Name .

La URL normalmente debe tener una barra inclinada; sin embargo, si la ruta no comienza con una, Spring MVC la agrega automáticamente.

Una forma diferente de configurar el ejemplo anterior en XML es usar la propiedad "props" en lugar de "value" . Los accesorios tienen una lista de etiquetas "prop" donde cada una define un mapeo donde "clave" se refiere a la URL mapeada y el valor de la etiqueta es el nombre del bean.

   welcome welcome   

El siguiente caso de prueba asegura que las solicitudes a "/ simpleUrlWelcome " sean manejadas por " WelcomeController" que devuelve un nombre de vista llamado "welcome" :

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

4. ControllerClassNameHandlerMapping (eliminado en Spring 5)

El ControllerClassNameHandlerMapping los mapas de URL a un bean registrada controlador (o un controlador anotado con el @Controller anotación) que tiene, o se inicia con el mismo nombre.

Puede ser más conveniente en muchos escenarios, especialmente para implementaciones de controlador simples que manejan un solo tipo de solicitud. La convención utilizada por Spring MVC es usar el nombre de la clase y eliminar el sufijo "Controlador" , luego cambiar el nombre a minúsculas y devolverlo como la asignación con una "/" inicial .

Por ejemplo, "WelcomeController" volvería como una asignación a "/ welcome *" , es decir, a cualquier URL que comience con "welcome" .

Configuremos ControllerClassNameHandlerMapping :

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

Tenga en cuenta que ControllerClassNameHandlerMapping está en desuso de Spring 4.3 a favor de los métodos de manejo controlados por anotaciones.

Otra nota importante es que los nombres de los controladores siempre se devolverán en minúsculas (menos el sufijo "Controlador"). Entonces, si tenemos un controlador llamado " WelcomeBaeldungController ", solo manejará solicitudes a "/ welcomebaeldung" y no a "/ welcomeBaeldung" .

Tanto en la configuración de Java como en la configuración de XML a continuación, definimos el bean ControllerClassNameHandlerMapping y registramos los beans para los controladores que usaremos para manejar las solicitudes. También registramos un bean de tipo "WelcomeController" y ese bean manejará todas las solicitudes que comiencen con "/ welcome" .

Aquí está la configuración XML equivalente:

Cuando se utiliza la configuración anterior, las solicitudes a "/ welcome " serán manejadas por el " WelcomeController ".

El siguiente código asegurará que las solicitudes a "/ welcome *" como "/ welcometest " sean manejadas por "WelcomeController" que devuelve un nombre de vista llamado " welcome ":

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

5. Configurar prioridades

El marco Spring MVC permite más de una implementación de la interfaz HandlerMapping al mismo tiempo.

Creemos una configuración y registremos dos controladores, ambos asignados a la URL "/ welcome", solo usando diferentes mapas y devolviendo diferentes nombres de vista:

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

Sin un mapeador de manejador explícito registrado, se usará un BeanNameHandlerMapping predeterminado . Afirmemos este comportamiento con la prueba:

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

Si registramos explícitamente un mapeador de manejadores diferente, se anulará el mapeador predeterminado. Sin embargo, es interesante ver qué sucede cuando dos mapeadores se registran explícitamente:

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

Para obtener el control sobre qué mapeo se usa, las prioridades se establecen usando el método setOrder (int order) . Este método toma un parámetro int donde un valor más bajo significa una prioridad más alta.

En la configuración XML, puede configurar las prioridades utilizando una propiedad llamada "orden" :

Añadamos orden propiedades de los granos de asignación de controlador, a través siguiente beanNameUrlHandlerMapping.setOrder (1) y simpleUrlHandlerMapping.setOrder (0). El valor más bajo de la propiedad de la orden refleja una precedencia más alta. Afirmemos un nuevo comportamiento con la prueba:

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

Al probar la configuración anterior, verá que las solicitudes a “/ welcome” serán manejadas por el bean SimpleUrlHandlerMapping que llama a SimpleUrlHandlerController y devuelve la vista simple-url-handler-mapping . Podemos configurar fácilmente BeanNameHandlerMapping para que tenga prioridad ajustando en consecuencia los valores de la propiedad order .

6. Conclusión

En este artículo discutimos cómo se maneja el mapeo de URL en el marco Spring MVC explorando las diferentes implementaciones en el marco.

El código que acompaña a este artículo se puede encontrar en GitHub.