Spring MVC的@PathVariable越来越截断Spring MVC的@PathVaria

2019-05-11 15:51发布

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

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

我遇到的问题是,如果我打了服务器与特殊字符的路径变量就被截断。 例如: HTTP://本地主机:8080 /废话服务器/胡说/ GET / blah2010.08.19-02:25:47

参数blahName将blah2010.08

然而,调用request.getRequestURI()包含传递的所有信息。

任何想法如何预防春季从截断@PathVariable?

Answer 1:

尝试对正则表达式@RequestMapping参数:

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


Answer 2:

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

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



Answer 3:

春认为,最后一个点后面的东西是作为文件扩展名, .json.xml和截断它来检索您的参数。

所以,如果你有/{blahName}

  • /param/param.json/param.xml/param.anything将导致具有值的PARAM param
  • /param.value.json/param.value.xml/param.value.anything将导致具有值的PARAM param.value

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

  • /param将产生具有值的PARAM param
  • /param.json将导致与价值设置了一个param param.json
  • /param.xml将导致与价值设置了一个param param.xml
  • /param.anything将导致与价值设置了一个param param.anything
  • /param.value.json将导致与价值设置了一个param param.value.json
  • ...

如果你不在乎扩展的认可,您可以通过覆盖禁用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 param
  • /param.value.json/param.value.xml/param.value.anything将导致具有值的PARAM param.value

注:从默认的配置不同的是可见的只有当你有一个像映射/something.{blahName} 见Resthub项目问题 。

如果你想保持扩展管理,因为春季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:注解驱动现在接受contentNegotiation选项提供自定义的bean,但RequestMappingHandlerMapping的财产已被更改为true(默认为false)(参见https://jira.springsource.org/browse/SPR-7632 )。

出于这个原因,你还是要覆盖所有的MVC:注解驱动的配置。 我打开一票春天,要求定制RequestMappingHandlerMapping: https://jira.springsource.org/browse/SPR-11253 。 请投票,如果你感兴趣的内容。

虽然重写,小心也考虑定制的执行管理压倒一切。 否则,所有的自定义异常的映射将会失败。 你将不得不重复使用列表豆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>

我实现了,在开源项目Resthub ,我的,一组关于这些问题的测试部分:看https://github.com/resthub/resthub-spring-stack/pull/219/files和https://开头github.com/resthub/resthub-spring-stack/issues/217



Answer 4:

最后一个点后一切都被解释为文件扩展名,默认情况下切断。
在Spring 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 (和所有其他的,太)应包含全名,包括所有的点。

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



Answer 5:

我也遇到同样的问题,并且属性设置为false,也帮不了我。 然而, 该API说 :

请注意,其中包含“.XXX”后缀或以‘/’结尾的路径已经将不被使用在任何情况下的默认后缀模式变换。

我尝试添加“/结束”我的REST风格的URL,问题就走开了。 我不与溶液讨好,但它确实工作。

顺便说一句,我不知道什么时候加入这个“功能”春设计师所想的,然后把它在默认情况下。 恕我直言,它应该被删除。



Answer 6:

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


Answer 7:

我这个黑客解析

1)增加的HttpServletRequest在@PathVariable象下面

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

2)直接(获取URL在Request这个级别没有截断)

request.getPathInfo() 

Spring MVC的@PathVariable用点(。)是越来越截断



Answer 8:

我只是碰到了这个和解决方案,在这里一般不工作,我的预期。

我建议使用规划环境地政司表达和多个映射,如

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


Answer 9:

如果该参数是在URL中的最后一部分只存在文件扩展名的问题。 更改

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

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

和一切都会好起来再次 -



Answer 10:

如果您可以编辑请求发送到该地址,简单的解决将是一个加上尾部斜杠他们(以及在@RequestMapping值):

/path/{variable}/

所以映射是这样的:

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

另请参见Spring MVC的@PathVariable用点(。)是越来越截断 。



Answer 11:

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


Answer 12:

添加“:+”为我工作,但直到我去掉外层大括号。

value = {"/username/{id:.+}"}没有工作

value = "/username/{id:.+}"工程

希望我帮助的人:]



Answer 13:

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

更新:

我意识到有同春开机自动配置的一些问题,当我用上面的方法(有的自动配置并没有得到有效)。

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



Answer 14:

如果你确信你的文本将不会匹配任何你可以用下面的代码默认扩展名:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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


Answer 15:

我最好的解决方案,以防止Spring MVC的@PathVariable获得截断是在路径变量的末尾添加斜线。

例如:

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

因此,请求将是这样的:

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


Answer 16:

您所面临的问题是由于弹簧解释 的URI的最后部分(。)作为文件扩展名像以.json或.xml。 所以当春天尝试解析路径变量它只是截断数据的其余遇到一个点(。)在URI结束后。 注:还发生这种情况仅当您保留路径变量在URI结束。

例如,考虑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) {
        // ...  
    }
}

在上述网址firstValue =“gallery.df”和secondValue =“链接”,之后的最后一位。 获得当路径变量被解释截断。

因此,为了防止这有两种可能的方式:

1.)使用正则表达式映射

在映射的端部使用正则表达式

@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。我们可以通过在应用程序上下文中声明自己DefaultAnnotationHandlerMapping豆及其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类重写默认的方法。 有通过实现WebMvcConfigurer接口覆盖deault配置另一种方式。 有关此了解更多详细信息: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html



文章来源: Spring MVC @PathVariable getting truncated