Spring MVC@Path 变量被截断

我有一个控制器,它提供了对信息的 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

The parameter blahName will be blah2010.08

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

有什么办法可以防止 Spring 截断@Pathvariable 吗?

78820 次浏览

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

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 config xml 中,可以添加 DefaultAnnotationHandlerMapping并将 useDefaultSuffixPattern设置为 false(默认为 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

我只是碰巧遇到了这个问题,这里的解决方案通常并不像我预期的那样有效。

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

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

我也遇到了同样的问题,将属性设置为 false 对我也没有帮助。然而,空气污染指数显示:

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

我尝试在 RESTful URL 中添加“/end”,问题就解决了。我不喜欢这个解决方案,但它确实起作用了。

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

我解决了这个黑客 < BR >

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

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

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

request.getPathInfo()

带点(.)的 Spring MVC@Path 变量被截断

只有当参数位于 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@Path 变量被截断

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

所以如果你有 /{blahName}:

  • /param/param.json/param.xml/param.anything将产生一个值为 param的参数
  • /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-driven自动禁用它:

<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的参数
  • /param.value.json/param.value.xml/param.value.anything将生成值为 param.value的参数

注意: 与默认配置的差异只有在有类似 /something.{blahName}的映射时才可见。

如果您想保持扩展管理,因为 Spring 3.2,您还可以设置 RequestMappingHandlerMapping bean 的 useRegisteredAffixPatternMatch 属性,以保持后缀模式识别被激活,但仅限于已注册的扩展。

这里只定义 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: 夺取驱动现在接受 content洽谈选项提供一个自定义 bean,但是属性的 RequestMappingHandlerMapping 必须改为 true (默认为 false)(参见 https://jira.springsource.org/browse/SPR-7632)。

由于这个原因,您仍然必须覆盖所有的 mvc: annotion 驱动配置。我打开了一张到 Spring 的票,请求一个自定义 RequestMappingHandlerMapping: https://jira.springsource.org/browse/SPR-11253。如果你有兴趣,请投票。

在重写时,请注意还要考虑自定义执行管理重写。否则,所有自定义 Exception 映射都将失败。您必须使用一个 list 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.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>

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

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

基于 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 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 自动配置有一些问题(一些自动配置不起作用)。

相反,我开始使用 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

使用正确的 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);
}
}

如果您确定您的文本不会匹配任何默认扩展插件,您可以使用以下代码:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {


@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseRegisteredSuffixPatternMatch(true);
}
}

添加“ : . +”对我来说很有用,但是直到我删除了外部的花括号。

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

value = "/username/{id:.+}"成功了

希望我帮到了什么人

为了防止 Spring MVC@Pathvariable 被截断,我最好的解决方案是在 path 变量的末尾添加一个斜杠。

例如:

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

因此,请求看起来像:

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

你所面临的问题是由于 春天解释的 最后部分的 URI 之后点(.)作为一个 < em > 档案扩展名 喜欢。Json 还是。Xml.所以当 Spring 尝试解析 path 变量时,它只是在遇到点(.)之后截断其余的数据在这里的末尾。 注意: 也只有当你在 uri 的末尾保留 path 变量时才会发生这种情况。

例如,考虑 uri: https://localhost/example/gallery.df/link.ar

@RestController
public class CustomController {
@GetMapping("/example/{firstValue}/{secondValue}")
public void example(@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
// ...
}
}

在上面的 url firstValue = “ gallery.df”和 second Value = “ link”中,在。在解释 path 变量时将被截断。

因此,有两种可能的方法可以防止这种情况的发生:

1.)使用 regexp 映射

在映射的最后部分使用正则表达式

@GetMapping("/example/{firstValue}/{secondValue:.+}")
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}

通过使用 + ,我们指示点之后的任何值也将是 path 变量的一部分。

2.)在@Pathvariable 的末尾添加一个斜杠

@GetMapping("/example/{firstValue}/{secondValue}/")
public void example(
@PathVariable("firstValue") String firstValue,
@PathVariable("secondValue") String secondValue) {
//...
}

这将包含第二个变量,保护它不受 Spring 默认行为的影响。

3)重写 Spring 的默认 webmvc 配置

Spring 提供了一些方法来覆盖使用注释 @ EnableWebMvc导入的默认配置。我们可以通过在应用程序上下文中声明我们自己的 < em > DefaultAnnotationHandlerMapping bean 并将其 < em > useDefaultSuffixPattern 属性设置为 false 来自定义 Spring MVC 配置。 例如:

@Configuration
public class CustomWebConfiguration extends WebMvcConfigurationSupport {


@Bean
public RequestMappingHandlerMapping
requestMappingHandlerMapping() {


RequestMappingHandlerMapping handlerMapping
= super.requestMappingHandlerMapping();
handlerMapping.setUseSuffixPatternMatch(false);
return handlerMapping;
}
}

请记住,重写此默认配置会影响所有 url。

注意: 这里我们扩展 WebMvcConfigurationSupport 类来覆盖默认方法。还有一种方法可以通过实现 WebMvcConfiguration 接口来覆盖默认配置。 更多详细信息请阅读: http://docs.spring.io/spring/docs/current/javadoc-api/org/springFramework/web/servlet/config/notation/EnableWebMvc.html”rel = “ nofollow noReferrer”> https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/enablewebmvc.html