Java Spring MVC @PathVariable 被截断

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3526523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:32:13  来源:igfitidea点击:

Spring MVC @PathVariable getting truncated

javaspringrestspring-mvcget

提问by phogel

I have a controller that provides RESTful access to information:

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

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

The problem I am experiencing is that if I hit the server with a path variable with special characters it gets truncated. For example: http://localhost:8080/blah-server/blah/get/blah2010.08.19-02:25:47

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

The parameter blahName will be blah2010.08

参数 blahName 将为 blah2010.08

However, the call to request.getRequestURI() contains all the information passed in.

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

Any idea how to prevent Spring from truncating the @PathVariable?

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

回答by earldouglas

Try a regular expression for the @RequestMappingargument:

尝试使用正则表达式作为@RequestMapping参数:

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

回答by skaffman

This is probably closely related to SPR-6164. Briefly, the framework tries to apply some smarts to the URI interpretation, removing what it thinks are file extensions. This would have the effect of turning blah2010.08.19-02:25:47into blah2010.08, since it thinks the .19-02:25:47is a file extension.

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

As described in the linked issue, you can disable this behaviour by declaring your own DefaultAnnotationHandlerMappingbean in the app context, and setting its useDefaultSuffixPatternproperty to false. This will override the default behaviour, and stop it molesting your data.

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

回答by Jan

Everything after the last dot is interpreted as file extension and cut off by default.
In your spring config xml you can add DefaultAnnotationHandlerMappingand set useDefaultSuffixPatternto false(default is true).

最后一个点之后的所有内容都被解释为文件扩展名并在默认情况下被切断。
在您的 spring 配置 xml 中,您可以添加DefaultAnnotationHandlerMapping并设置useDefaultSuffixPatternfalse(默认为true)。

So open your spring xml mvc-config.xml(or however it is called) and add

所以打开你的spring xml mvc-config.xml(或者它被称为)并添加

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

Now your @PathVariableblahName(and all other, too) should contain the full name including all dots.

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

EDIT: Here is a link to the spring api

编辑:这是spring api链接

回答by Mark Elliot

I just ran into this and the solutions here didn't generally work as I expected.

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

I suggest using a SpEL expression and multiple mappings, e.g.

我建议使用 SpEL 表达式和多个映射,例如

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

回答by Steve11235

I also ran into the same issue, and setting the property to false didn't help me either. However, the API says:

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

Note that paths which include a ".xxx" suffix or end with "/" already will not be transformed using the default suffix pattern in any case.

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

I tried adding "/end" to my RESTful URL, and the problem went away. I'm not please with the solution, but it did work.

我尝试在我的 RESTful URL 中添加“/end”,问题就解决了。我对解决方案不满意,但它确实有效。

BTW, I don't know what the Spring designers were thinking when they added this "feature" and then turned it on by default. IMHO, it should be removed.

顺便说一句,我不知道 Spring 设计师在添加这个“功能”然后默认开启时是怎么想的。恕我直言,它应该被删除。

回答by Kanagavelu Sugumar

I resolved by this hack

我解决了这个黑客

1) Added HttpServletRequest in @PathVariable like below

1) 在@PathVariable 中添加 HttpServletRequest 如下

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

2) Get the URL directly (At this level no truncation) in the request

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

request.getPathInfo() 

Spring MVC @PathVariable with dot (.) is getting truncated

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

回答by chrismarx

The file extension problem only exists if the parameter is in the last part of the URL. Change

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

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

to

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

and all will be well again-

一切都会好起来的——

回答by Micha? Rybak

If you can edit the address that requests are sent to, simple fix would be to add a trailing slash to them (and also in the @RequestMappingvalue):

如果您可以编辑请求发送到的地址,简单的解决方法是向它们添加尾部斜杠(也在@RequestMapping值中):

/path/{variable}/

so the mapping would look like:

所以映射看起来像:

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

See also Spring MVC @PathVariable with dot (.) is getting truncated.

另请参阅Spring MVC @PathVariable with dot (.) is getting truncated

回答by bmeurant

Spring considers that anything behind the last dot is a file extension such as .jsonor .xmland truncate it to retrieve your parameter.

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

So if you have /{blahName}:

所以如果你有/{blahName}

  • /param, /param.json, /param.xmlor /param.anythingwill result in a param with value param
  • /param.value.json, /param.value.xmlor /param.value.anythingwill result in a param with value param.value
  • /param, /param.json, /param.xmlor/param.anything将产生一个带值的参数param
  • /param.value.json,/param.value.xml否则/param.value.anything会产生一个带值的参数param.value

If you change your mapping to /{blahName:.+}as suggested, any dot, including the last one, will be considered as part of your parameter:

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

  • /paramwill result in a param with value param
  • /param.jsonwill result in a param with value param.json
  • /param.xmlwill result in a param with value param.xml
  • /param.anythingwill result in a param with value param.anything
  • /param.value.jsonwill result in a param with value param.value.json
  • ...
  • /param将产生一个带值的参数 param
  • /param.json将产生一个带值的参数 param.json
  • /param.xml将产生一个带值的参数 param.xml
  • /param.anything将产生一个带值的参数 param.anything
  • /param.value.json将产生一个带值的参数 param.value.json
  • ...

If you don't care of extension recognition, you can disable it by overriding mvc:annotation-drivenautomagic:

如果你不关心扩展识别,你可以通过覆盖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>

So, again, if you have /{blahName}:

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

  • /param, /param.json, /param.xmlor /param.anythingwill result in a param with value param
  • /param.value.json, /param.value.xmlor /param.value.anythingwill result in a param with value param.value
  • /param, /param.json, /param.xmlor/param.anything将产生一个带值的参数param
  • /param.value.json,/param.value.xml否则/param.value.anything会产生一个带值的参数param.value

Note: the difference from the default config is visible only if you have a mapping like /something.{blahName}. See Resthub project issue.

注意:与默认配置的不同之处仅在您有像/something.{blahName}. 请参阅Resthub 项目问题

If you want to keep extension management, since Spring 3.2 you can also set the useRegisteredSuffixPatternMatch property of RequestMappingHandlerMapping bean in order to keep suffixPattern recognition activated but limited to registered extension.

如果要保持扩展管理,从 Spring 3.2 开始,您还可以设置 RequestMappingHandlerMapping bean 的 useRegisteredSuffixPatternMatch 属性,以保持 suffixPattern 识别激活但仅限于注册的扩展。

Here you define only json and xml extensions:

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

Note that mvc:annotation-driven accepts now a contentNegotiation option to provide a custom bean but the property of RequestMappingHandlerMapping has to be changed to true (default false) (cf. https://jira.springsource.org/browse/SPR-7632).

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

For that reason, you still have to override all the mvc:annotation-driven configuration. I opened a ticket to Spring to ask for a custom RequestMappingHandlerMapping: https://jira.springsource.org/browse/SPR-11253. Please vote if you are interested in.

因此,您仍然必须覆盖所有 mvc:annotation-driven 配置。我向 Spring 开了一张票,要求自定义 RequestMappingHandlerMapping:https: //jira.springsource.org/browse/SPR-11253。如果您有兴趣,请投票。

While overriding, be careful to consider also custom Execution management overriding. Otherwise, all your custom Exception mappings will fail. You will have to reuse messageCoverters with a list bean:

在覆盖时,请注意还要考虑自定义执行管理覆盖。否则,您所有的自定义异常映射都将失败。您将不得不使用列表 bean 重用 messageCoverters:

<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.MappingHymansonHttpMessageConverter"></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>

I implemented, in the open source project Resthubthat I am part of, a set of tests on these subjects: see https://github.com/resthub/resthub-spring-stack/pull/219/filesand https://github.com/resthub/resthub-spring-stack/issues/217

我在我参与的开源项目Resthub中实现了一组关于这些主题的测试:参见https://github.com/resthub/resthub-spring-stack/pull/219/fileshttps:// github.com/resthub/resthub-spring-stack/issues/217

回答by Fareed Alnamrouti

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