ResourceHandler conflict with wildcards in Controllers

dzikoysk :

I'm trying to reserve all paths starting with /static/** for a resource handler. Unfortunately, I have some wildcards deriving out of the root path / in request mappings. Something like this:

Preview

What did I try?

  • ResourceHandlerRegistry#setOrder:

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**")
                .addResourceLocations("classpath:/resources/static/");
    
        registry.setOrder(1);
    }
    
  • Various versions of interceptor (with or without order):

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ResourcesInterceptor())
                .excludePathPatterns("/static/**")
                .order(2);
    }
    

That is a half-hearted success (probably it won't even work if I change mapping to /{profile}/{project}/**), because:

/static/style/home.css      # works
/static/style/home.cssxxx   # 404, works
/static/style               # catched by controller, expected: 404
/static                     # catched by controller, expected: 404

I've found some similar questions, mostly unanswered or with a little dirty solutions, like:

Summary:

  • I don't want to use regex, because it will be painful in the future
  • I also can't change mappings. I know, that it is the simplest way, but I'm just not able to do that.
  • Changing an order not working
  • Creating dedicated controller still have some issues with paths

I'm looking for a simple soulution, fully automated and preferably from the configuration. The question is: what's the proper way to achieve that?

NorthPL93 :

This issue is caused beause of the way that Spring handles requests from users. There are several HandlerMappings and they are executed in a specified order. Most important for us are these two:

  1. RequestMappingHandlerMapping registered in WebMvcConfigurationSupport with order=0 (we can see this in the source code and the documentation)

    /**
     * Return a {@link RequestMappingHandlerMapping} ordered at 0 for mapping
     * requests to annotated controllers.
     */
    
  2. AbstractHandlerMapping instantiated in ResourceHandleRegistry with default order Integer.MAX_VALUE-1

    private int order = Ordered.LOWEST_PRECEDENCE - 1;
    

When you create a RequestMapping with path /{profile}/{project} and try to reach resource /static/somefile.css, the request you send is grabbed by the RequestMappingHandlerMapping and does not reach the HandlerMapping created by ResourceHandlerRegistry.

A simple solution for this issue is to set order to -1 in addResourceHandlers

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/static/**")
        .addResourceLocations("classpath:/resources/static/");

    registry.setOrder(-1);
}

Then the proper HandlerMapping will serve static files, and if there is no such file, it will pass execution to your Controllers.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=68381&siteId=1