SpringMVC: Inconsistent mapping behavior depending on url extension

前端 未结 2 882
耶瑟儿~
耶瑟儿~ 2020-12-16 21:04

I have a RESTful spring based endpoint to get assets stored in a db to a javascript editor. The relevant parts boil down to:

@RestController
@RequestMapping(         


        
相关标签:
2条回答
  • 2020-12-16 21:22

    It's not a bug, it's a feature...

    As @axtavt and @rhinds have supposed, something is messing around which the content type. The browsers sends a correct Accept: application/json but spring ignores this and uses the extension of the url (aarrgh). From the docs:

    16.16.4 Configuring Content Negotiation

    You can configure how Spring MVC determines the requested media types from the client for
    request mapping as well as for content negotiation purposes. The available options are to 
    check the file extension in the request URI, the "Accept" header, a request parameter, as 
    well as to fall back on a default content type. By default, file extension in the request 
    URI is checked first and the "Accept" header is checked next.
    

    The solution is quite simple as you can disable this "feature":

    @Configuration
    @EnableWebMvc
    public class RestCommonsMvcConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer.favorPathExtension(false);
        }
    
    }
    

    See also Spring does not ignore file extension for xml-config.

    Related

    • Spring MVC @PathVariable with dot (.) is getting truncated
    0 讨论(0)
  • 2020-12-16 21:41

    I had required an extra step in my special case. I would like to add an extra information to @dirk-lachowski's great comment in case someone else needs. In my case I am importing an extension from WebMvcConfigurationSupport class

    @Configuration
    @EnableWebMvc
    @Import({ SearchWebMvcConfigurationSupport.class })
    public class SearchSpringConfiguration extends WebMvcConfigurerAdapter {
        @Override
        public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer.favorPathExtension(false);
        }
    }
    

    If you need to override requestMappingHandlerMapping method then you also have to add m.setUseSuffixPatternMatch(false);

    @Configuration
    public class SearchWebMvcConfigurationSupport extends WebMvcConfigurationSupport {
        @Override
        @Bean
        public RequestMappingHandlerMapping requestMappingHandlerMapping() {
            RequestMappingHandlerMapping m = super.requestMappingHandlerMapping();
            m.setAlwaysUseFullPath(true); // This makes your endpoints receive full path, including servlet mapping (you probably will not need this)
            m.setUseSuffixPatternMatch(false);
            return m;
        }
    }
    
    0 讨论(0)
提交回复
热议问题