Esta es la continuación de la pregunta Spring MVC @PathVariable truncada
El foro de Spring afirma que se ha solucionado (versión 3.2) como parte de ContentNegotiationManager. ver el siguiente enlace.
https://jira.springsource.org/browse/SPR-6164
https://jira.springsource.org/browse/SPR-7632
En mi solicitud requestParameter con .com está truncado.
¿Alguien podría explicarme cómo usar esta nueva función? ¿Cómo es configurable en xml?
Nota: Spring forum- # 1 Spring MVC @PathVariable con punto (.) Se está truncando
spring
rest
spring-mvc
spring-annotations
Kanagavelu Sugumar
fuente
fuente
<!-- Spring Configuration needed to avoid URI using dots to be truncated --> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="useDefaultSuffixPattern" value="false" /> </bean>
{variable_name:regular_expression}
, por lo que aquí tenemos una variable llamadavariable
, cuyo valor se combinará usando regex.+
(donde.
significa 'cualquier carácter' y+
significa 'una o más veces').variable
de manera regular, Spring usa sus funciones de detección de sufijos y trunca todo después del punto. Cuando utiliza la coincidencia de expresiones regulares, esas características no se utilizan: la variable solo se corresponde con la expresión regular que proporciona."variable:.+"
no funciona cuando hay más de un punto en la variable. por ejemplo, poner correos electrónicos al final de rutas relajantes como/path/[email protected]
. El controlador ni siquiera recibe una llamada, pero funciona cuando solo hay un punto/path/[email protected]
. ¿Alguna idea de por qué y / o una solución alternativa?Spring considera que todo lo que está detrás del último punto es una extensión de archivo como
.json
o.xml
y lo truca para recuperar su parámetro.Entonces si tienes
/somepath/{variable}
:/somepath/param
,/somepath/param.json
,/somepath/param.xml
O/somepath/param.anything
dará lugar a un parámetro con el valorparam
/somepath/param.value.json
,/somepath/param.value.xml
o/somepath/param.value.anything
dará como resultado un parámetro con valorparam.value
Si cambia la asignación a
/somepath/{variable:.+}
lo sugerido, cualquier punto, incluido el último, se considerará como parte de su parámetro:/somepath/param
resultará en un parámetro con valorparam
/somepath/param.json
resultará en un parámetro con valorparam.json
/somepath/param.xml
resultará en un parámetro con valorparam.xml
/somepath/param.anything
resultará en un parámetro con valorparam.anything
/somepath/param.value.json
resultará en un parámetro con valorparam.value.json
Si no le importa el reconocimiento de extensión, puede deshabilitarlo anulando el
mvc:annotation-driven
autómata:Entonces, de nuevo, si tienes
/somepath/{variable}
:/somepath/param
,/somepath/param.json
,/somepath/param.xml
O/somepath/param.anything
dará lugar a un parámetro con el valorparam
/somepath/param.value.json
,/somepath/param.value.xml
o/somepath/param.value.anything
dará como resultado un parámetro con valorparam.value
nota: la diferencia con la configuración predeterminada es visible solo si tiene un mapeo como
somepath/something.{variable}
. ver problema del proyecto Resthubsi desea mantener la administración de extensiones, desde Spring 3.2 también puede establecer la propiedad useRegisteredSuffixPatternMatch del bean RequestMappingHandlerMapping para mantener activado el reconocimiento de sufijoPattern pero limitado a la extensión registrada.
Aquí define solo extensiones json y xml:
Tenga en cuenta que mvc: impulsado por anotaciones acepta ahora una opción contentNegotiation para proporcionar un bean personalizado, pero la propiedad de RequestMappingHandlerMapping debe cambiarse a verdadero (valor predeterminado falso) (cf. https://jira.springsource.org/browse/SPR-7632 )
Por esa razón, aún debe anular toda la configuración mvc: basada en anotaciones. Abrí un boleto a Spring para solicitar un RequestMappingHandlerMapping personalizado: https://jira.springsource.org/browse/SPR-11253 . Por favor vote si está interesado.
Al anular, tenga cuidado de considerar también la anulación de la gestión de ejecución personalizada. De lo contrario, todas sus asignaciones de excepción personalizadas fallarán. Tendrá que reutilizar messageCoverters con un bean de lista:
Implementé, en el proyecto de código abierto Resthub del que formo parte, un conjunto de pruebas sobre estos temas: consulte https://github.com/resthub/resthub-spring-stack/pull/219/files & https: // github.com/resthub/resthub-spring-stack/issues/217
fuente
Actualización para Spring 4: desde 4.0.1 puede usar
PathMatchConfigurer
(a través de suWebMvcConfigurer
), por ejemploEn xml, sería ( https://jira.spring.io/browse/SPR-10163 ):
fuente
matcher.setUseSuffixPatternMatch(false)
para deshabilitar completamente la coincidencia de sufijo.Además de la respuesta de Martin Frey, esto también se puede solucionar agregando una barra diagonal al valor de RequestMapping:
Tenga en cuenta que esta solución no admite la mantenibilidad. Ahora requiere que todos los URI tengan una barra diagonal final, algo que puede no ser evidente para los usuarios de API / nuevos desarrolladores. Debido a que es probable que no todos los parámetros tengan un elemento
.
, también puede crear errores intermitentesfuente
En Spring Boot Rest Controller, los resolví siguiendo estos pasos:
RestController:
Y desde Rest Client:
fuente
agregar el ":. +" funcionó para mí, pero no hasta que eliminé las llaves exteriores.
value = { "/username/{id:.+}" } no funcionó
value = "/username/{id:.+}" funciona
Espero haber ayudado a alguien :)
fuente
id
/somepath/{variable:.+}
Funciona en larequestMapping
etiqueta Java .fuente
"/{code:.+}"
funciona para muchos puntos, no uno, es decir61.12.7
, también funciona para, por ejemplo[email protected]
Aquí hay un enfoque que se basa exclusivamente en la configuración de Java:
fuente
Una forma bastante fácil de solucionar este problema es agregar una barra diagonal final ...
p.ej:
utilizar :
en vez de:
fuente
En Spring Boot, la expresión regular resuelve el problema como
fuente
"/{code:.+}"
funciona para muchos puntos, no uno, es decir61.12.7
, también funciona para, por ejemplo[email protected]
La solución completa que incluye direcciones de correo electrónico en los nombres de ruta para spring 4.2 es
Agregue esto a la aplicación-xml
fuente
Si está utilizando Spring 3.2.xy
<mvc:annotation-driven />
cree este pequeñoBeanPostProcessor
:Luego ponga esto en su MVC config xml:
fuente
BeanPostProcessor
para esto. Si lo usaWebMvcConfigurationSupport
, puede anular elrequestMappingHandlerMapping
@Bean
método. Si usa la configuración XML, puede declarar su propioRequestMappingHandlerMapping
bean y declarar esa propiedad.Finalmente encontré solución en Spring Docs :
Agregar esto a mi
WebMvcConfigurerAdapter
implementación resolvió el problema:fuente
Para mi el
funciona, pero solo si también codifica el "punto" en su url de solicitud como "% 2E", entonces funciona. Pero requiere que todas las URL sean eso ... lo cual no es una codificación "estándar", aunque es válida. Se siente como un error: |
La otra solución, similar a la forma de "barra inclinada final" es mover la variable que tendrá el punto "en línea" ej:
@GetMapping (ruta = "/ {variableName} / a")
ahora todos los puntos se conservarán, no se necesitan modificaciones ni expresiones regulares.
fuente
A partir de Spring 5.2.4 (Spring Boot v2.2.6.RELEASE)
PathMatchConfigurer.setUseSuffixPatternMatch
yContentNegotiationConfigurer.favorPathExtension
han quedado en desuso ( https://spring.io/blog/2020/03/24/spring-framework-5-2-5-available-now and https://github.com/spring-projects/spring-framework/issues/24179 ).El verdadero problema es que el cliente solicita un tipo de medio específico (como .com) y Spring agregó todos esos tipos de medios de forma predeterminada. En la mayoría de los casos, su controlador REST solo producirá JSON, por lo que no admitirá el formato de salida solicitado (.com). Para superar este problema, debería ser bueno actualizando su controlador de descanso (o método específico) para admitir el formato de 'salida' (
@RequestMapping(produces = MediaType.ALL_VALUE
)) y, por supuesto, permitir caracteres como un punto ({username:.+}
).Ejemplo:
Spring 5.3 y superior solo coincidirá con sufijos registrados (tipos de medios).
fuente