Spring MVC @PathVariable被截断了

pho*_*gel 135 java rest spring get spring-mvc

我有一个控制器,提供对信息的RESTful访问:

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

我遇到的问题是,如果我使用带有特殊字符的路径变量命中服务器,它将被截断.例如: http:// localhost:8080/blah-server/blah/get/blah2010.08.19-02:25:47

参数blahName将是blah2010.08

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

知道如何防止Spring截断@PathVariable吗?

ear*_*las 145

尝试使用正则表达式@RequestMapping:

RequestMapping(method = RequestMethod.GET, value = Routes.BLAH_GET + "/{blahName:.+}")
Run Code Online (Sandbox Code Playgroud)

  • 诺亚,我很长一段时间没有使用它,但我认为冒号将正则表达式与参数名称分开以将其绑定到. (6认同)
  • 这有效,但正则表达式中冒号的意义是什么? (3认同)
  • 我们有一个类似的problam /item/user@abc.com,在@被截断后的任何内容,这是通过添加另一个斜杠/item/user@abc.com/解决的 (3认同)

ska*_*man 55

这可能与SPR-6164密切相关.简而言之,该框架尝试将一些智能应用于URI解释,删除它认为的文件扩展名.这将有转向的效果blah2010.08.19-02:25:47blah2010.08,因为它认为.19-02:25:47是一个文件扩展名.

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

  • 获得+1的答案以及使用"骚扰您的数据"这一短语 (28认同)
  • 对于Spring 3.1用户 - 如果您正在使用新的`RequestMappingHandlerMapping`,则要设置的属性是`useSuffixPatternMatch`(也是'false`).@Ted:链接的问题提到在3.2中他们希望增加一点控制权,所以它不一定是全有或全无. (11认同)
  • 默认情况下启用基于扩展的内容协商似乎是一个奇怪的选择.在实践中有多少系统真正以不同的格式暴露相同的资源? (3认同)
  • 在 Spring 4.2 中,这更容易配置。我们使用 Java 配置类并扩展了`WebMvcConfigurationSupport`,它提供了一个简单的钩子:`public void configurePathMatch(PathMatchConfigurer configurer)` - 只需覆盖它并设置匹配你喜欢的路径。 (2认同)

小智 29

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

所以如果你有/{blahName}:

  • /param,/param.json,/param.xml/param.anything将导致具有值的PARAMparam
  • /param.value.json,/param.value.xml/param.value.anything将导致有价值的参数param.value

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

  • /param 将导致一个有价值的参数 param
  • /param.json 将导致一个有价值的参数 param.json
  • /param.xml 将导致一个有价值的参数 param.xml
  • /param.anything 将导致一个有价值的参数 param.anything
  • /param.value.json 将导致一个有价值的参数 param.value.json
  • ...

如果您不关心扩展程序识别,可以通过覆盖mvc:annotation-drivenautomagic 来禁用它:

<bean id="handlerMapping"
      class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
    <property name="useSuffixPatternMatch" value="false"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

所以,如果你有/{blahName}:

  • /param,/param.json,/param.xml/param.anything将导致具有值的PARAMparam
  • /param.value.json,/param.value.xml/param.value.anything将导致有价值的参数param.value

注意:只有具有类似的映射时,才能看到与默认配置的差异/something.{blahName}.请参阅Resthub项目问题.

如果要保留扩展管理,从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>
Run Code Online (Sandbox Code Playgroud)

请注意,mvc:annotation-driven现在接受contentNegotiation选项以提供自定义bean,但RequestMappingHandlerMapping的属性必须更改为true(默认为false)(参见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>
Run Code Online (Sandbox Code Playgroud)

我在开源项目Resthub中实现了我对这些主题的一系列测试:请参阅https://github.com/resthub/resthub-spring-stack/pull/219/fileshttps:// github.com/resthub/resthub-spring-stack/issues/217


Jan*_*Jan 15

最后一个点之后的所有内容都被解释为文件扩展名并默认情况下被截断.
在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>
Run Code Online (Sandbox Code Playgroud)

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

编辑:这是一个弹簧api链接


Ste*_*235 7

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

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

我尝试在我的RESTful URL中添加"/ end",问题就消失了.我不满意解决方案,但确实有效.

顺便说一句,我不知道Spring设计师在添加这个"功能"时会想到什么,然后默认打开它.恕我直言,它应该被删除.


jeb*_*det 7

使用正确的Java配置类:

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Kan*_*mar 5

我通过这个 hack 解决了

1)在@PathVariable中添加HttpServletRequest,如下所示

 @PathVariable("requestParam") String requestParam, HttpServletRequest request) throws Exception { 
Run Code Online (Sandbox Code Playgroud)

2)直接获取请求中的URL(此级别没有截断)

request.getPathInfo() 
Run Code Online (Sandbox Code Playgroud)

带点 (.) 的 Spring MVC @PathVariable 被截断