我正在尝试设置一个允许用户通过电子邮件地址查询用户的REST端点。电子邮件地址是路径的最后一部分,因此Spring将foo@example.com
视为值foo@example
并截断扩展名.com
。
我在这里发现了一个类似的问题Spring MVC @PathVariable with dot (.) is getting truncated
但是,我使用AbstractAnnotationConfigDispatcherServletInitializer
和WebMvcConfigurerAdapter
进行了基于注释的配置。由于我没有xml配置,这个解决方案对我不起作用:
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="useDefaultSuffixPattern" value="false" />
</bean>
我也试过这个使用正则表达式的解决方案,但它也没有用。
@RequestMapping(value = "user/by-email/{email:.+}")
有没有人知道如何在没有xml的情况下关闭后缀模式截断?
答案 0 :(得分:19)
URI末尾的path变量中的点会导致两个意外行为(大多数用户意外,除了那些熟悉大量Spring配置属性的用户)。
第一个(可以使用{email:.+}
正则表达式修复)是默认的Spring配置匹配所有路径扩展。因此,为/api/{file}
设置映射意味着Spring将对/api/myfile.html
的调用映射到String参数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的更多信息。
答案 1 :(得分:14)
您必须在路径变量末尾添加尾部斜杠,如
之类的名称 @RequestMapping(value ="/test/{name}/")
请求
http://localhost:8080/utooa/service/api/admin/test/Takeoff.Java@gmail.com/
答案 2 :(得分:7)
我使用本文中的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将不再使用文件扩展名来覆盖请求的接受mediaType。该方法的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:.+}")
答案 3 :(得分:0)
对于Java-Config人员:
使用Spring 4,您可以通过以下方式关闭此功能:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false);
}
}
然后在整个应用程序中,点将被视为点。