responsebody - spring boot rest controller mapping
Spring MVC @PathVariable con punto(.) Se está truncando (14)
Actualización para Spring 4: desde la PathMatchConfigurer
4.0.1 puede usar PathMatchConfigurer
(a través de su WebMvcConfigurer
), por ejemplo
@Configuration
protected static class AllResources extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseRegisteredSuffixPatternMatch(true);
}
}
En xml, sería ( https://jira.spring.io/browse/SPR-10163 ):
<mvc:annotation-driven>
[...]
<mvc:path-matching registered-suffixes-only="true"/>
</mvc:annotation-driven>
Esta es la continuación de la pregunta Spring MVC @PathVariable truncada
El foro de Spring indica que se ha corregido (versión 3.2) como parte de ContentNegotiationManager. Vea el siguiente enlace.
https://jira.springsource.org/browse/SPR-6164
https://jira.springsource.org/browse/SPR-7632
En mi aplicación se trunca el parámetro de solicitud con .com.
¿Alguien podría explicarme cómo usar esta nueva característica? ¿Cómo es configurable en xml?
Nota: spring forum- # 1 Spring MVC @PathVariable con punto (.) Se está truncando
Además de la respuesta de Martin Frey, esto también puede solucionarse agregando una barra diagonal al valor de RequestMapping:
/path/{variable}/
Tenga en cuenta que esta solución no admite la capacidad de mantenimiento. Ahora se requiere que todos los URI tengan una barra inclinada, algo que puede no ser evidente para los usuarios de API / nuevos desarrolladores. Porque es probable que no todos los parámetros tengan un .
En ellos, también puede crear errores intermitentes.
Aquí hay un enfoque que se basa únicamente en la configuración de Java:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport{
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
handlerMapping.setUseSuffixPatternMatch(false);
handlerMapping.setUseTrailingSlashMatch(false);
return handlerMapping;
}
}
En Spring Boot Rest Controller, he resuelto estos pasos siguiendo estos pasos:
RestController:
@GetMapping("/statusByEmail/{email:.+}/")
public String statusByEmail(@PathVariable(value = "email") String email){
//code
}
Y de Rest Client:
Get http://mywebhook.com/statusByEmail/[email protected]/
En Spring Boot, la expresión Regular resuelve el problema como
@GetMapping("/path/{param1:.+}")
Finalmente encontré la solución en Spring Docs :
Para deshabilitar completamente el uso de las extensiones de archivo, debe configurar lo siguiente:
useSuffixPatternMatching(false), see PathMatchConfigurer favorPathExtension(false), see ContentNegotiationConfigurer
Agregar esto a mi implementación de WebMvcConfigurerAdapter
solucionó el problema:
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
@Override
public void configurePathMatch(PathMatchConfigurer matcher) {
matcher.setUseSuffixPatternMatch(false);
}
La solución completa que incluye las direcciones de correo electrónico en los nombres de ruta para la primavera 4.2 es
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true" />
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
<mvc:annotation-driven
content-negotiation-manager="contentNegotiationManager">
<mvc:path-matching suffix-pattern="false" registered-suffixes-only="true" />
</mvc:annotation-driven>
Añade esto a la aplicación-xml
Para mi el
@GetMapping(path = "/a/{variableName:.+}")
funciona, pero solo si también codifica el "punto" en su url de solicitud como "% 2E", entonces funciona. Pero requiere que las URL sean todas ... que no sean una codificación "estándar", aunque son válidas. Se siente como una especie de error: |
La otra alternativa, similar a la forma de "barra inclinada al final" es mover la variable que tendrá el punto "en línea" ej:
@GetMapping (ruta = "/ {variableName} / a")
ahora se conservarán todos los puntos, no se necesitan modificaciones ni expresiones regulares.
Por lo que sé, este problema aparece solo para la variable de ruta al final del mapeo de solicitud.
Pudimos resolver eso definiendo el complemento de expresiones regulares en el mapeo de solicitud.
/somepath/{variable:.+}
Si está utilizando Spring 3.2.xy <mvc:annotation-driven />
, cree este pequeño BeanPostProcessor
:
package spring;
public final class DoNotTruncateMyUrls implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RequestMappingHandlerMapping) {
((RequestMappingHandlerMapping)bean).setUseSuffixPatternMatch(false);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Luego ponga esto en su configuración MVC xml:
<bean class="spring.DoNotTruncateMyUrls" />
Spring considera que cualquier cosa detrás del último punto es una extensión de archivo como .json
o .xml
y trucarla para recuperar su parámetro.
Así que si tienes /somepath/{variable}
:
-
/somepath/param
,/somepath/param.json
,/somepath/param.xml
o/somepath/param.anything
resultará en un parámetro con valorparam
-
/somepath/param.value.json
,/somepath/param.value.xml
o/somepath/param.value.anything
resultará en unparam.value
con valorparam.value
Si cambia su asignación a /somepath/{variable:.+}
como se sugiere, cualquier punto, incluido el último, se considerará como parte de su parámetro:
-
/somepath/param
dará como resultado un parámetro con valorparam
-
/somepath/param.json
dará como resultado unparam.json
con valorparam.json
-
/somepath/param.xml
resultará en unparam.xml
con valorparam.xml
-
/somepath/param.anything
resultará en unparam.anything
con valorparam.anything
-
/somepath/param.value.json
dará como resultado unparam.value.json
con valorparam.value.json
- ...
Si no le importa el reconocimiento de extensión, puede desactivarlo anulando mvc:annotation-driven
automagic:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="useSuffixPatternMatch" value="false"/>
</bean>
Entonces, de nuevo, si tienes /somepath/{variable}
:
-
/somepath/param
,/somepath/param.json
,/somepath/param.xml
o/somepath/param.anything
resultará en un parámetro con valorparam
-
/somepath/param.value.json
,/somepath/param.value.xml
o/somepath/param.value.anything
resultará en unparam.value
con valorparam.value
nota: la diferencia con la configuración predeterminada es visible solo si tiene una asignación como somepath/something.{variable}
. ver el tema del proyecto Resthub
Si desea mantener la administración de extensiones, desde Spring 3.2 también puede configurar la propiedad useRegisteredSuffixPatternMatch del bean RequestMappingHandlerMapping para mantener activado el reconocimiento suffixPattern pero limitado a la extensión registrada.
Aquí solo se definen las extensiones json y xml:
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="useRegisteredSuffixPatternMatch" value="true"/>
</bean>
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>
Tenga en cuenta que mvc: annotation-driven ahora acepta una opción contentNegotiation para proporcionar un bean personalizado, pero la propiedad de RequestMappingHandlerMapping debe cambiarse a verdadero (valor predeterminado falso) (consulte https://jira.springsource.org/browse/SPR-7632 ).
Por esa razón, todavía tiene que anular la configuración de mvc: annotation-impulsada por todos. Abrí un boleto a Spring para solicitar un RequestMappingHandlerMapping personalizado: https://jira.springsource.org/browse/SPR-11253 . Por favor vota si estás interesado.
Mientras reemplaza, tenga cuidado de considerar también la omisión de la administración de ejecución personalizada. De lo contrario, todas sus asignaciones de excepción personalizadas fallarán. Deberá reutilizar messageCoverters con un bean de lista:
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
<util:list id="messageConverters">
<bean class="your.custom.message.converter.IfAny"></bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.StringHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"></bean>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</util:list>
<bean name="exceptionHandlerExceptionResolver"
class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
<property name="order" value="0"/>
<property name="messageConverters" ref="messageConverters"/>
</bean>
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionService" />
<property name="validator" ref="validator" />
</bean>
</property>
<property name="messageConverters" ref="messageConverters"/>
</bean>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
</bean>
Implementé, en el proyecto de código abierto Resthub que Resthub 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
Una forma bastante fácil de solucionar este problema es agregar una barra inclinada ...
p.ej:
utilizar :
/somepath/filename.jpg/
en lugar de:
/somepath/filename.jpg
agregar el ":. +" funcionó para mí, pero no hasta que quité los soportes externos.
value = { "/username/{id:.+}" } no funcionó
value = "/username/{id:.+}" funciona
Espero haber ayudado a alguien :)
/somepath/{variable:.+}
funciona en la etiqueta requestMapping
Java.