【问题标题】:Spring - Path variable truncate after dot - annotationSpring - 点后截断路径变量 - 注释
【发布时间】:2015-02-09 18:04:57
【问题描述】:

我正在尝试设置一个允许通过电子邮件地址查询用户的 REST 端点。电子邮件地址是路径的最后一部分,因此 Spring 将 foo@example.com 视为值 foo@example 并截断扩展名 .com

我在这里发现了一个类似的问题Spring MVC @PathVariable with dot (.) is getting truncated 但是,我有一个使用AbstractAnnotationConfigDispatcherServletInitializerWebMvcConfigurerAdapter 的基于注释的配置。由于我没有 xml 配置,因此此解决方案不适用于我:

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

我也试过这个使用正则表达式的解决方案,但也没有用。

@RequestMapping(value = "user/by-email/{email:.+}")

有谁知道如何在没有xml的情况下关闭后缀模式截断?

【问题讨论】:

  • this 对你有帮助吗

标签: java spring rest spring-mvc spring-annotations


【解决方案1】:

URI 末尾的路径变量中的点会导致两种意外行为(大多数用户都无法预料到,除了那些熟悉大量 Spring 配置属性的用户)。

第一个(可以使用{email:.+} 正则表达式修复)是默认 Spring 配置匹配所有路径扩展。因此,为/api/{file} 设置映射意味着Spring 将对/api/myfile.html 的调用映射到字符串参数myfile。当您希望/api/myfile.html/api/myfile.md/api/myfile.txt 和其他人都指向同一资源时,这很有用。但是,我们可以在全局范围内关闭此行为, 不必在每个端点上都使用正则表达式破解。

第二个问题与第一个问题有关,并由@masstroy 正确修复。当/api/myfile.* 指向myfile 资源时,Spring 假定路径扩展(.html.txt 等)表示该资源应以特定格式返回。这种行为在某些情况下也非常有用。但是很多时候,会意味着方法映射返回的对象不能转换成这种格式,Spring会抛出一个HttpMediaTypeNotAcceptableException

我们可以通过以下方式关闭两者(假设是 Spring Boot):

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

  @Override
  public void configurePathMatch(PathMatchConfigurer configurer) {
    // turn off all suffix pattern matching
    configurer.setUseSuffixPatternMatch(false);
    // OR
    // turn on suffix pattern matching ONLY for suffixes
    // you explicitly register using
    // configureContentNegotiation(...)
    configurer.setUseRegisteredSuffixPatternMatch(true);
  }

  @Override
  public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    configurer.favorPathExtension(false);
  }
}

更多关于Content Negotiation

【讨论】:

    【解决方案2】:

    你必须在路径变量的末尾添加斜杠在名称之后

     @RequestMapping(value ="/test/{name}/")
    

    请求喜欢

    http://localhost:8080/utooa/service/api/admin/test/Takeoff.Java@gmail.com/

    【讨论】:

      【解决方案3】:

      我使用本文中的ContentNegotiationConfigurer bean 找到了解决方案:http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

      我在我的 WebConfig 类中添加了以下配置:

      @EnableWebMvc
      @Configuration
      @ComponentScan(basePackageClasses = { RestAPIConfig.class })
      public class WebConfig extends WebMvcConfigurerAdapter {    
          @Override
          public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
              configurer.favorPathExtension(false);
              configurer.defaultContentType(MediaType.APPLICATION_JSON);
          }
      }
      

      通过设置.favorPathExtension(false),Spring 将不再使用文件扩展名来覆盖请求的接受媒体类型。该方法的 Javadoc 为 Indicate whether the extension of the request path should be used to determine the requested media type with the highest priority.

      然后我使用正则表达式设置我的@RequestMapping

      @RequestMapping(value = "/user/by-email/{email:.+}")
      

      【讨论】:

      • 请注意,除了使用{email:.+} hack,您还可以通过覆盖WebMvcConfigurerAdapter.configurePathMatch(PathMatcherConfigurer configurer) 并设置configurer.setUseSuffixPatternMatch(false) 来禁用后缀模式匹配。您还可以将后缀模式匹配限制为显式注册的文件扩展名。
      • {email:.+} 为我工作,无需任何额外配置。这意味着它没有逐点截断部分。但还有另一个问题。 ExceptionHandler 不能与虚线变量一起正常工作。您的解决方案也解决了这个问题
      • @bkjvbx 您能否将您的解决方案发布为答案,它看起来比这个更好,我将其标记为已接受的答案
      • @masstroy 完成。
      【解决方案4】:

      对于 Java 配置人员:

      使用 Spring 4,您只需通过以下方式关闭此功能:

      @Configuration
      public class WebMvcConfig extends WebMvcConfigurerAdapter {
      
        @Override
        public void configurePathMatch(PathMatchConfigurer configurer) {
          configurer.setUseSuffixPatternMatch(false);
        }
      
      }
      

      那么在整个应用程序中,点将被视为点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-16
        • 1970-01-01
        • 2015-03-15
        • 1970-01-01
        • 2014-08-03
        • 2013-11-20
        • 2017-01-11
        相关资源
        最近更新 更多