Spring MVC @PathVariable被截断了
问题
我有一个控制器,提供对信息的RESTful访问:
@RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName}")
public ModelAndView getBlah(@PathVariable String blahName, HttpServletRequest request,
HttpServletResponse response) {
我遇到的问题是,如果我使用带有特殊字符的路径变量命中服务器,它将被截断。例如:http://localhost:8080/blah-server/blah/get/blah2010.08.19-02:25:47
参数blahName将为blah2010.08
但是,对request.getRequestURI()的调用包含传入的所有信息。
知道如何防止Spring截断@PathVariable吗?
#1 热门回答(138 赞)
尝试使用@RequestMapping
argument的正则表达式:
RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")
#2 热门回答(54 赞)
这可能与SPR-6164密切相关。简而言之,该框架尝试将一些智能应用于URI解释,删除它认为的文件扩展名。这会产生turnblah2010.08.19-02:25:47
intoblah2010.08
的影响,因为它认为.19-02:25:47
是一个文件扩展名。
如链接问题中所述,你可以通过在应用程序上下文中声明自己的DefaultAnnotationHandlerMapping
bean并将其useDefaultSuffixPattern
属性设置为false
来禁用此行为。这将覆盖默认行为,并停止骚扰你的数据。
#3 热门回答(28 赞)
Spring认为最后一个点后面的任何内容都是文件扩展名,例如.json
or.xml
并截断它以检索你的参数。
所以如果你有/{blahName}
:
- / param,/ param.json,/ param.xml或/param.anything将导致带有值参数的参数
- /param.value.json,/ param.value.xml或/param.value.anything将生成一个值为param.value的param
如果你将映射更改为建议的/{blahName:.+}
,则任何点(包括最后一个点)都将被视为参数的一部分:
- / param将导致带有值参数的参数
- /param.json将生成一个值为param.json的param
- /param.xml将生成一个值为param.xml的param
- /param.anything会产生一个带有值param.anything的param
- /param.value.json将生成一个值为param.value.json的param
- ......
如果你不关心扩展程序识别,可以通过覆盖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.json,/ param.xml或/param.anything将导致带有值参数的参数
- /param.value.json,/ param.value.xml或/param.value.anything将生成一个值为param.value的param
注意:只有当你具有像/something.{blahName}
这样的映射时,才能看到与默认配置的差异。 SeeResthub project issue。
如果你想保持扩展管理,从Spring 3.2开始,你也可以设置RequestMappingHandlerMapping bean的useRegisteredSuffixPatternMatch属性,以便使suffixPattern识别激活,但仅限于注册扩展。
在这里,你只定义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)(cf.https://jira.springsource.org/browse/SPR-7632)。
因此,你仍然必须覆盖所有mvc:annotation驱动的配置。我打开了一张Spring的票,要求自定义RequestMappingHandlerMapping:https://jira.springsource.org/browse/SPR-11253。如果你有兴趣,请投票。
在覆盖时,请注意考虑自定义执行管理覆盖。否则,所有自定义的异常映射都将失败。你将不得不将messageCoverters与list 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中实现了对这些主题的一系列测试:seehttps://github.com/resthub/resthub-spring-stack/pull/219/filesandhttps://github.com/resthub/resthub-spring-stack/issues/217