Spring MVC @PathVariable被截断

我有一个提供REST式访问信息的控制器:

@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}") public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request, HttpServletResponse response) { 

我遇到的问题是,如果我用具有特殊字符的pathvariables打到服务器,它将被截断。 例如: http:// localhost:8080 / blah-server / blah / get / blah2010.08.19-02:25:47

参数blahName将是blah2010.08

但是,调用request.getRequestURI()包含传入的所有信息。

任何想法如何防止截断@PathVariable的Spring?

尝试使用@RequestMapping参数的正则expression式:

 RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}") 

这可能与SPR-6164密切相关。 简而言之,该框架试图将一些智能应用到URI解释,删除它认为是文件扩展名。 这将会使blah2010.08.19-02:25:47变成blah2010.08 ,因为它认为.19-02:25:47是一个文件扩展名。

如链接问题中所述,可以通过在应用程序上下文中声明您自己的DefaultAnnotationHandlerMapping bean并将其useDefaultSuffixPattern属性设置为false来禁用此行为。 这将覆盖默认行为,并停止骚扰您的数据。

Spring认为最后一个点后面的任何内容都是文件扩展名,例如.json.xml并截断它以检索您的参数。

所以如果你有/{blahName}

  • /param/param /param.json/param /param.xml/param.anything将会产生一个参数值param
  • /param.value.json/param.value.anything将会产生一个参数param.value

如果您按照build议将映射更改为/{blahName:.+} ,则包括最后一个点在内的任何点都将被视为参数的一部分:

  • /param将导致一个参数值param
  • /param.json将产生一个param值为param.json的参数
  • /param.xml将生成一个param值为param.xml的参数
  • /param.anything将导致一个参数的值param.anything
  • /param.value.json将会产生一个param值为param.value.json的参数

如果您不关心扩展识别,可以通过覆盖mvc:annotation-driven来禁用它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> 

所以,再一次,如果你有/{blahName}

  • /param/param /param.json/param /param.xml/param.anything将会产生一个参数值param
  • /param.value.json/param.value.anything将会产生一个参数param.value

注意:仅当您有像/something.{blahName}这样的映射时,才能看到与默认configuration的区别。 请参阅Resthub项目问题 。

如果你想保持扩展pipe理,从Spring 3.2开始,你还可以设置RequestMappingHandlerMapping bean的useRegisteredSuffixPatternMatch属性,以保持后缀模式识别的激活,但限于注册扩展。

这里只定义了json和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> 

请注意,mvc:annotation-driven现在接受一个contentNegotiation选项来提供一个自定义Bean,但RequestMappingHandlerMapping的属性必须更改为true(默认为false)(参见https://jira.springsource.org/browse/SPR-7632 )。

因此,您仍然必须覆盖所有mvc:注释驱动的configuration。 我打开了Spring的一张票,要求一个自定义的RequestMappingHandlerMapping: https : //jira.springsource.org/browse/SPR-11253 。 请投票,如果你有兴趣。

在压倒一切的时候,要小心的考虑自定义的执行pipe理覆盖。 否则,所有的自定义exception映射都将失败。 您将不得不重复使用messageCoverters与列表bean:

 <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> 

我在Resthub的开源项目中实现了一个关于这些主题的testing: https: //github.com/resthub/resthub-spring-stack/pull/219/files和https:// github.com/resthub/resthub-spring-stack/issues/217

最后一个点之后的所有内容都被解释为文件扩展名,并且默认为closures
在你的spring config xml中,你可以添加DefaultAnnotationHandlerMapping并且设置useDefaultSuffixPatternfalse (默认值为true )。

所以打开你的spring xml mvc-config.xml (或者叫它)然后添加

 <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="useDefaultSuffixPattern" value="false" /> </bean> 

现在,您的@PathVariable blahName (以及其他全部)应该包含全名,包括所有的点。

编辑:这是一个链接到spring的api

我也遇到了同样的问题,并将该属性设置为false也没有帮助我。 但是, API说 :

请注意,包含“.xxx”后缀或以“/”结尾的path在任何情况下都不会使用默认的后缀模式进行转换。

我尝试添加“/结束”到我的RESTfulurl,问题就消失了。 我不喜欢解决scheme,但它确实有效。

顺便说一下,我不知道Springdevise者在添加这个“function”时是怎么想的,然后默认打开它。 恕我直言,它应该被删除。

使用正确的Javaconfiguration类:

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false); } @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(false); } } 

我通过这个黑客解决了

1)像下面那样在@PathVariable中添加了HttpServletRequest

  @PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception { 

2)请求中直接获取URL(在这个级别上不截断)

 request.getPathInfo() 

带点(。)的Spring MVC @PathVariable正在被截断

我刚刚遇到了这个问题,这里的解决scheme通常没有像我预期的那样工作。

我build议使用SpELexpression式和多个映射,例如

 @RequestMapping(method = RequestMethod.GET, value = {Routes.BLAH_GET + "/{blahName:.+}", Routes.BLAH_GET + "/{blahName}/"}) 

只有当参数位于URL的最后部分时,文件扩展名问题才存在。 更改

 @RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}") 

 @RequestMapping( method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/safe") 

一切都会好起来的 –

如果你可以编辑发送请求的地址,简单的修正就是给它们添加一个斜线(还有在@RequestMapping值中):

 /path/{variable}/ 

所以映射将如下所示:

 RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}/") 

使用点(。)的Spring MVC @PathVariable也被截断 。

 //in your xml dispatcher add this property to your default annotation mapper bean as follow <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"> <property name="alwaysUseFullPath" value="true"></property> </bean> 

添加“:。+”为我工作,但直到我删除外大括号。

value = {"/username/{id:.+}"}不起作用

value = "/username/{id:.+}"作品

希望我帮助过某人:]

基于Java的configuration解决scheme,以防止截断(使用一个不被弃用的类):

 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 PolRepWebConfig extends WebMvcConfigurationSupport { @Override @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { final RequestMappingHandlerMapping handlerMapping = super .requestMappingHandlerMapping(); // disable the truncation after . handlerMapping.setUseSuffixPatternMatch(false); // disable the truncation after ; handlerMapping.setRemoveSemicolonContent(false); return handlerMapping; } } 

资料来源:http://www.javacodegeeks.com/2013/01/spring-mvc-customizing-requestmappinghandlermapping.html

更新:

当我使用上面的方法时,我意识到Spring Boot自动configuration有一些问题(一些自动configuration不起作用)。

相反,我开始使用BeanPostProcessor方法。 它似乎工作得更好。

 import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { private static final Logger logger = LoggerFactory .getLogger(MyBeanPostProcessor.class); @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof RequestMappingHandlerMapping) { setRemoveSemicolonContent((RequestMappingHandlerMapping) bean, beanName); setUseSuffixPatternMatch((RequestMappingHandlerMapping) bean, beanName); } return bean; } private void setRemoveSemicolonContent( RequestMappingHandlerMapping requestMappingHandlerMapping, String beanName) { logger.info( "Setting 'RemoveSemicolonContent' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}", beanName); requestMappingHandlerMapping.setRemoveSemicolonContent(false); } private void setUseSuffixPatternMatch( RequestMappingHandlerMapping requestMappingHandlerMapping, String beanName) { logger.info( "Setting 'UseSuffixPatternMatch' on 'RequestMappingHandlerMapping'-bean to false. Bean name: {}", beanName); requestMappingHandlerMapping.setUseSuffixPatternMatch(false); } } 

受启发:http://ronaldxq.blogspot.com/2014/10/spring-mvc-setting-alwaysusefullpath-on.html

如果你确定你的文本不符合任何默认的扩展名,你可以使用下面的代码:

 @Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseRegisteredSuffixPatternMatch(true); } } 

防止Spring MVC @PathVariable被截断的最佳解决scheme是在pathvariables的末尾添加尾部斜线。

例如:

 @RequestMapping(value ="/email/{email}/") 

所以,请求将如下所示:

 http://localhost:8080/api/email/test@test.com/