Tú Puede usar la anotación @RequestMapping para asignar solicitudes a métodos de controlador. Tiene varios atributos para hacer coincidir por URL, método HTTP, parámetros de solicitud, encabezados, encabezados y tipos de datos. Puede usarlo a nivel de clase para expresar asignaciones generales o a nivel de método para limitarlo a una asignación de punto final específica.

También hay opciones específicas del método HTTP para acortar el @RequestMapping anotación:

  • @GetMapping

  • @PostMapping

  • @PutMapping

  • @DeleteMapping

  • @PatchMapping

Las abreviaturas son anotaciones personalizadas que se especifican porque, quizás, la mayoría de los métodos del controlador deben asignarse a un método HTTP específico en lugar de utilizar la anotación @RequestMapping, que se asigna a todos los métodos HTTP de forma predeterminada. Para expresar asignaciones comunes a nivel de clase aún se requiere @RequestMapping.

El siguiente ejemplo tiene asignaciones a nivel de tipo y método:

Java

@RestController
@RequestMapping("/persons")
class PersonController {
    @GetMapping("/{id}")
    public Person getPerson(@PathVariable Long id) {
        // ...
    }
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void add(@RequestBody Person person) {
        // ...
    }
}
Kotlin
 
@RestController
@RequestMapping("/persons")
class PersonController {
    @GetMapping("/{id}")
    fun getPerson(@PathVariable id: Long): Person {
        // ...
    }
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    fun add(@RequestBody person: Person) {
        // ...
    }
}

Patrones URI

Métodos anotado con @RequestMapping se puede asignar utilizando patrones de URL. Hay dos alternativas:

  • PathPattern: un patrón previamente analizado asignado a una ruta URL, también analizado previamente como un PathContainer. Diseñada para su uso en el entorno de Internet, esta solución funciona eficientemente con codificación y parámetros de ruta y proporciona una coincidencia eficiente.

  • AntPathMatcher - plantillas de coincidencia de cadenas con cadena camino. Esta solución original también se utiliza en la configuración de Spring para seleccionar recursos en el classpath, en el sistema de archivos y otros lugares. Es menos eficiente y ingresar una ruta de cadena dificulta el manejo efectivo de la codificación y otros problemas de URL.

PathPattern es la solución recomendada para las aplicaciones web, y esta es la única opción cuando se trabaja en Spring WebFlux. Antes de la versión 5.3, AntPathMatcher era la única opción cuando se trabajaba en Spring MVC y sigue siendo la predeterminada. Sin embargo, PathPattern se puede activar en una configuración MVC.

PathPattern admite la misma sintaxis de patrón que AntPathMatcher. Además, también admite un patrón de captura como {*spring} para hacer coincidir 0 o más segmentos de ruta al final de una ruta. PathPattern también restringe el uso del carácter ** para que coincida con múltiples segmentos de ruta, de modo que solo se permita al final del patrón. Esto evita la ambigüedad al elegir el mejor patrón de coincidencia para una consulta determinada. La sintaxis completa del patrón se proporciona en las secciones en PathPattern y AntPathMatcher.

Algunos ejemplos de plantillas:

  • "/resources/ima?e.png " - coincide con un carácter en el segmento de ruta

  • "/resources/*.png" - coincide con cero o más caracteres en segmento de ruta

  • "/resources/**" – coincide con múltiples segmentos de ruta

  • "/projects/{project}/versions" – coincide con el segmento de ruta y lo escribe como una variable

  • "/projects/{ proyecto:[a-z]+}/versions" – emparejar y capturar una variable usando una expresión regular

Se puede acceder a las variables URI capturadas usando una anotación @PathVariable. Por ejemplo:

Java

@GetMapping("/owners/{ownerId}/pets/{petId}")
public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
    // ...
}
Kotlin

@GetMapping("/owners/{ownerId}/pets/{petId}")
fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
    // ...
}

Puede declarar variables URI a nivel de clase y método, como se muestra en el siguiente ejemplo:

Java

@Controller
@RequestMapping("/owners/{ownerId}")
public class OwnerController {
    @GetMapping("/pets/{petId}")
    public Pet findPet(@PathVariable Long ownerId, @PathVariable Long petId) {
        // ...
    }
}
Kotlin

@Controller
@RequestMapping("/owners/{ownerId}")
class OwnerController {
    @GetMapping("/pets/{petId}")
    fun findPet(@PathVariable ownerId: Long, @PathVariable petId: Long): Pet {
        // ...
    }
}

Las variables URI son se convierte automáticamente al tipo apropiado o se lanza una TypeMismatchException. Los tipos simples (int, long, Date, etc.) se admiten de forma predeterminada, pero se puede registrar compatibilidad con cualquier otro tipo de datos. Consulte Conversión de tipos y DataBinder.

Puede nombrar explícitamente variables URI (por ejemplo, @PathVariable("customId")), pero también puede omita esta información si los nombres son los mismos y su código se compila utilizando información de depuración o con el indicador del compilador -parameters en Java 8.

Sintaxis {varName:regex} declara una variable URI usando una expresión regular, que tiene la sintaxis {varName:regex}. Por ejemplo, si se proporciona la URL "/spring-web-3.0.5.jar", el siguiente método recupera el nombre del archivo, la versión y la extensión:

Java

@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
public void handle(@PathVariable String name, @PathVariable String version, @PathVariable String ext) {
    // ...
}
Kotlin

@GetMapping("/{name:[a-z-]+}-{version:\\d\\.\\d\\.\\d}{ext:\\.[a-z]+}")
fun handle(@PathVariable name: String, @PathVariable version: String, @PathVariable ext: String) {
    // ...
}

Las plantillas de ruta de URI también pueden contener marcadores de posición integrados ${...}, que se reconocen cuando se ejecutan usando PropertySourcesPlaceholderConfigurer en el sistema local. fuentes de propiedades, entorno de fuentes de propiedades, etc. Puede utilizar esto, por ejemplo, para parametrizar una URL base en función de alguna configuración externa.

Comparación de plantillas

Si varios patrones coinciden con una URL, es necesario seleccionar el más adecuado. Esto se hace de una de las siguientes maneras, dependiendo de si se permite o no el uso del PathPattern analizado sintácticamente:

Ambos ayudan a ordenar las plantillas, con las más específicas en la parte superior. Un patrón es menos específico si tiene menos URI variables (cuenta como 1), comodines simples (cuenta como 1) y comodines dobles (cuenta como 2). Si los indicadores son iguales, se selecciona la plantilla más larga. Dadas las mismas métricas y longitud, se selecciona el patrón que tiene más URI variables que comodines.

El patrón de visualización predeterminado (/**) se excluye del recuento y siempre se ordenado al final. Además, los patrones con prefijos (como /public/**) se consideran menos específicos que otros patrones que no contienen comodines dobles.

Para obtener información completa, siga estos Consulte el enlaces anteriores para obtener descripciones de comparadores de patrones.

Coincidencia de sufijos

A partir de la versión 5.3, Spring MVC ya no utiliza de forma predeterminada la coincidencia de patrones con los sufijos .* si El controlador asignado a /person también está implícitamente asignado a /person.*. Como consecuencia, las extensiones de ruta ya no se utilizan para interpretar el tipo de contenido solicitado para la respuesta; por ejemplo, /person.pdf, /person.xml, etc. .

El uso de extensiones de archivo de esta manera era necesario cuando los navegadores enviaban encabezados Aceptar que eran difíciles de interpretar de manera consistente. Esto ya no es necesario hoy en día, y usar el encabezado Aceptar debería ser la opción preferida.

Con el tiempo, el uso de extensiones de nombre de archivo ha resultado problemático por diversas razones. Esto puede causar ambigüedad al superponer usando URI variables, parámetros de ruta y codificación de URI. Defender la autorización y la seguridad basadas en URL (consulte la siguiente sección para obtener más detalles) también se vuelve más complejo.

Para deshabilitar completamente el uso de extensiones de ruta en versiones anteriores a la 5.3, configure lo siguiente:

  • useSuffixPatternMatching(false)

  • favorPathExtension(false)

Tener una forma de solicitar tipos de contenido distintos del encabezado "Aceptar" puede ser útil, por ejemplo, al ingresar una URL en un navegador. Una alternativa segura a la expansión de rutas es utilizar la estrategia de parámetros de consulta. Si debe utilizar extensiones de archivo, considere restringirlas a una lista de extensiones registradas explícitamente a través de la propiedad mediaTypes de ContentNegotiationConfigurer.

Coincidencia de sufijos y RFD

Los ataques de descarga de archivos reflejados por vectores (RFD) son similares a XSS en que se basan en que la entrada de la solicitud (como un parámetro de solicitud y una variable URI) se refleja en la respuesta. Sin embargo, en lugar de insertar JavaScript en HTML, el vector de ataque RFD se basa en cambiar el navegador para realizar la descarga y tratar la respuesta como un script ejecutable cuando luego hace doble clic en él.

En Spring MVC, los métodos marcados con la anotación @ResponseBody y ResponseEntity están en riesgo porque pueden representar diferentes tipos de contenido que los clientes pueden solicitar a través de extensiones de ruta URL. Deshabilitar la coincidencia de patrones de sufijos y usar extensiones de ruta para hacer coincidir el contenido reduce el riesgo, pero no es suficiente para prevenir ataques RFD.

Para evitar ataques RFD, Spring MVC agrega un encabezado Content-Disposition:inline;filename=f.txt antes de representar el cuerpo de respuesta para ofrecer un archivo de descarga fijo y seguro. Esto solo se hace si la ruta URL contiene una extensión de archivo que no se considera segura y no se ha registrado explícitamente para la negociación de contenido. Sin embargo, esto puede tener efectos secundarios si las URL se ingresan directamente en el navegador.

Muchas extensiones de ruta comunes se permiten como seguras de forma predeterminada. Las aplicaciones con implementaciones personalizadas de HttpMessageConverter pueden registrar explícitamente extensiones de archivos para la negociación de contenido para evitar agregar un encabezado Content-Disposition para estas extensiones.

Consideraciones adicionales relacionadas con RFD, consulte "CVE-2015-5211".

Consumido Tipos de datos

Puede limitar la visualización de la consulta según la consulta Content-Type, como se muestra en el siguiente ejemplo:

Java

@PostMapping(path = "/pets", consumes = "application/json") 
public void addPet( @RequestBody Pet pet) {
    // ...
}
  1. Usando atributo consume para limitar el rango de visualización por tipo de contenido.
Kotlin

@PostMapping("/pets", consumes = ["application/json" ]) 
fun addPet(@RequestBody pet: Pet) {
    // ...
}
  1. Utilice el atributo consume para limitar el rango de visualización por tipo de contenido.

El atributo consume también admite expresiones de negación; por ejemplo, !text/plain significa cualquier tipo de contenido que no sea text/plain.

Puedes declarar el atributo general consume a nivel de clase. Sin embargo, a diferencia de la mayoría de los otros atributos de mapeo de solicitudes, cuando se usa a nivel de clase, el atributo consume a nivel de método anula en lugar de extender la declaración a nivel de clase.

MediaType proporciona constantes para los tipos de medios utilizados habitualmente, como APPLICATION_JSON_VALUE y APPLICATION_XML_VALUE.

Tipos de datos producidos

Puede limitar el rango de solicitudes que se muestran según el encabezado de solicitud Aceptar y la lista de tipos de contenido que produce el método del controlador, como se muestra en el siguiente ejemplo:

Java

@GetMapping(path = "/pets/{petId}", produces = "application/json") 
@ResponseBody
public Pet getPet(@PathVariable String petId) {
    // ...
}
  1. Utilice el atributo produce para limitar el rango de visualización por tipo de contenido.
Kotlin

@GetMapping("/pets/{petId}", produces = ["application/json"]) 
@ResponseBody
fun getPet( @PathVariable petId: String): Pet {
// ...
}
  1. El uso del atributo produce para limitar el rango de visualización por tipo de contenido.

El tipo de medio puede determinar el conjunto de caracteres. Se admiten expresiones negables; por ejemplo, !text/plain significa cualquier tipo de contenido que no sea "texto/plain".

Puedes declarar un genérico produce atributo a nivel de clase. Sin embargo, a diferencia de la mayoría de los otros atributos de mapeo de solicitudes, cuando se usa a nivel de clase, el atributo produce a nivel de método anula en lugar de extender la declaración a nivel de clase.

MediaType proporciona constantes para los tipos de medios utilizados habitualmente, como APPLICATION_JSON_VALUE y APPLICATION_XML_VALUE.

Parámetros, encabezados

Puede limitar el rango de visualización de consultas según las condiciones de los parámetros de consulta. Puede comprobar la presencia de un parámetro de consulta(myParam), su ausencia (!myParam) o un valor específico(myParam=myValue). El siguiente ejemplo muestra cómo verificar la presencia de un valor específico:

Java

@GetMapping(path = "/pets/{petId}", params = "myParam=myValue ") 
public void findPet(@PathVariable String petId) {
    // ...
}
  1. Comprueba si myParam es igual a myValue.
Kotlin

@GetMapping("/pets/{petId}", params = ["myParam=myValue"]) 
fun findPet(@PathVariable petId: String) {
// ...
}
  1. Comprueba si myParam es igual al valor de myValue.

Se puede utilizar lo mismo con condiciones de encabezado de solicitud, como se muestra en el siguiente ejemplo:

Java

@GetMapping(path = "/pets", headers = "myHeader=myValue") 
public void findPet(@PathVariable String petId) {
// ...
}
  1. Comprueba si myHeader es igual a myValue.
Kotlin

@GetMapping("/pets", headers = ["myHeader=myValue"]) 
fun findPet( @PathVariable petId: String) {
    // ...
}
Puede hacer coincidir Content-Type y Aceptar con la condición de los encabezados, pero es mejor usar consume y produce en su lugar.

Métodos HTTP HEAD, OPTIONS

@GetMapping (y @RequestMapping(method=HttpMethod.GET)) admiten de forma transparente el método HTTP HEAD para solicitudes de mapeo. No es necesario cambiar los métodos del controlador. La función contenedora de respuesta utilizada en javax.servlet.http.HttpServlet garantiza que el encabezado Content-Length esté establecido en el número de bytes escritos (sin escribir realmente en la respuesta) .

@GetMapping (y @RequestMapping(method=HttpMethod.GET)) se asignan implícitamente y admiten el método HEAD HTTP. Una solicitud que utiliza el método HTTP HEAD se procesa de la misma manera que un método HTTP GET, excepto que en lugar de escribir un cuerpo, se cuenta el número de bytes y se establece el encabezado Content-Length.

De forma predeterminada, el método OPCIONES HTTP se maneja configurando el encabezado de respuesta Allow en la lista de métodos HTTP enumerados en todos los métodos marcados con @RequestMapping. anotación que tiene patrones de URL coincidentes.

En el caso de la anotación @RequestMapping sin declarar métodos HTTP, el encabezado Allow se establece en GET, HEAD, POST, PUT, PATCH, DELETE , OPTIONS. Los métodos del controlador siempre deben declarar métodos HTTP admitidos (por ejemplo, utilizando variantes específicas del método HTTP: @GetMapping, @PostMapping y otros).

Puede asignar explícitamente un método anotado con @RequestMapping al método HEAD HTTP y al método OPTIONS HTTP, pero en casos normales esto no es necesario.

Anotaciones personalizadas

Spring MVC admite el uso de anotaciones compuestas para mostrar consultas. Estas son anotaciones que son en sí mismas metanotaciones @RequestMapping y están compuestas para volver a declarar un subconjunto (o todos) de los atributos marcados con la anotación @RequestMapping para un alcance más limitado. , propósito más específico.

@GetMapping, @PostMapping, @PutMapping, @DeleteMapping y @PatchMapping son ejemplos de anotaciones compuestas. Se proporcionan porque es probable que la mayoría de los métodos del controlador deban asignarse a un método HTTP específico en lugar de utilizar la anotación @RequestMapping, que se asigna a todos los métodos HTTP de forma predeterminada. Si necesita un ejemplo de anotaciones compuestas, observe cómo se declaran.

Spring MVC también admite atributos de mapeo de consultas personalizados con lógica de mapeo de consultas personalizada. Esta es una opción más avanzada que requiere subclasificar RequestMappingHandlerMapping y anular el método getCustomMethodCondition en el que puede verificar el atributo personalizado y devolver su propia RequestCondition.

Registro explícito

Puede registrar mediante programación métodos de controlador, que se pueden usar para registro dinámico o en casos más complejos, como si hay diferentes instancias del mismo controlador en URL diferentes. El siguiente ejemplo registra un método de controlador:

Java

@Configuration
public class MyConfig {
    @Autowired
    public void setHandlerMapping(RequestMappingHandlerMapping mapping, UserHandler handler) 
            throws NoSuchMethodException {
        RequestMappingInfo info = RequestMappingInfo
                .paths("/user/{id}").methods(RequestMethod.GET).build(); 
        Method method = UserHandler.class.getMethod("getUser", Long.class); 
        mapping.registerMapping(info, handler, method); 
    }
}
  1. Inyectar el controlador de destino y la asignación de controladores para los controladores.
  2. Preparar los metadatos de asignación de la solicitud.
  3. Obtener el método del controlador.
  4. Agregar registro.
Kotlin

@Configuration
class MyConfig {
    @Autowired
    fun setHandlerMapping(mapping: RequestMappingHandlerMapping, handler: UserHandler) { 
        val info = RequestMappingInfo.paths("/user/{id}").methods(RequestMethod.GET).build() 
        val method = UserHandler::class.java.getMethod("getUser", Long::class.java) 
        mapping.registerMapping(info, handler, method) 
    }
}
  1. Inyectar el controlador de destino y la asignación del controlador para los controladores.
  2. Preparar los metadatos de asignación de la solicitud.
  3. Obtener el método de controlador.
  4. Agregar registro.