java Spring - 路径变量在点之后截断 - 注释

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27419743/
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-11-02 11:47:19  来源:igfitidea点击:

Spring - Path variable truncate after dot - annotation

javaspringrestspring-mvcspring-annotations

提问by masstroy

I am trying to set up a REST endpoint that allows querying a user by their email address. The email address is the last portion of the path so Spring is treating [email protected]as the value foo@exampleand truncating the extension .com.

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

I found a similar question here Spring MVC @PathVariable with dot (.) is getting truncatedHowever, I have an annotation based configuration using AbstractAnnotationConfigDispatcherServletInitializerand WebMvcConfigurerAdapter. Since I have no xml configuration, this solution will not work for me:

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

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

I have also tried this solution which uses regex but it has not worked either.

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

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

Does anyone know how to turn off the suffix pattern truncation without xml?

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

回答by bkjvbx

The dot in the path variable at the end of the URI causes two unexpected behaviours (unexpected for the majority of users, except those familiar with the huge number of Spring configuration properties).

URI 末尾的路径变量中的点会导致两种意外行为(对于大多数用户而言是意外的,除了那些熟悉大量 Spring 配置属性的用户)。

The first (which canbe fixed using the {email:.+}regex) is that the default Spring configuration matches all path extensions. So setting up a mapping for /api/{file}will mean that Spring maps a call to /api/myfile.htmlto the String argument myfile. This is useful when you want /api/myfile.html, /api/myfile.md, /api/myfile.txtand others to all point to the same resource. However, we can turn this behaviour off globally, withouthaving to resort to a regex hack on every endpoint.

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

The second problem is related to the first and correctly fixed by @masstroy. When /api/myfile.*points to the myfileresource, Spring assumes the path extension (.html, .txt, etc.) indicates that the resource should be returned with a specific format. This behaviour can also be very useful in some situations. But often, it will mean that the object returned by a method mapping cannot be converted into this format, and Spring will throw a HttpMediaTypeNotAcceptableException.

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

We can turn both off with the following (assuming Spring Boot):

我们可以通过以下方式关闭两者(假设 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);
  }
}

More about Content Negotiation.

更多关于内容协商

回答by takeoffjava

You have to add trailing slash at the end of the path variable after name like

您必须在名称后的路径变量末尾添加斜杠,例如

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

The Request like

请求喜欢

http://localhost:8080/utooa/service/api/admin/test/[email protected]/

http://localhost:8080/utooa/service/api/admin/test/[email protected]/

回答by masstroy

I've found the solution to this using the ContentNegotiationConfigurerbean from this article: http://spring.io/blog/2013/05/11/content-negotiation-using-spring-mvc

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

I added the following configuration to my WebConfig class:

我在 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);
    }
}

By setting .favorPathExtension(false), Spring will no longer use the file extension to override the accepts mediaType of the request. The Javadoc for that method reads Indicate whether the extension of the request path should be used to determine the requested media type with the highest priority.

通过设置.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.

Then I set up my @RequestMapping using the regex

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

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

回答by d0x

For the Java-Config folks:

对于 Java 配置人员:

With Spring 4 you can simply turn this feature off by:

使用 Spring 4,您可以通过以下方式简单地关闭此功能:

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  @Override
  public void configurePathMatch(PathMatchConfigurer configurer) {
    configurer.setUseSuffixPatternMatch(false);
  }

}

Then in the whole application dots will treated as dots.

然后在整个应用程序中,点将被视为点。