Adam McCormick
Adam McCormick

Reputation: 335

Spring - Set HandlerMapping Priority

How can I set the priority of handler mappings in spring to allow resource handlers to map before controller request mappings?

For example this configuration:

@Configuration
@EnableWebMvc
@ComponentScan("org.commons.sandbox")
public class WebConfiguration extends WebMvcConfigurerAdapter {

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

    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

With the following controller:

@Controller
public class HomeController {

    @RequestMapping("/**")
    public String home(){
        return "home";
    }
}

Captures requests to "/resources". So linking to a css file is the jsp returns the "home" view not the actual css file in the "resources" directory. I understand that it's due to the mapping "/**" but I would assume there's a way to configure the mapping order... is there?

Thanks!

Upvotes: 8

Views: 3564

Answers (2)

Grigory Kislin
Grigory Kislin

Reputation: 18010

In my case I needed SimpleUrlHandlerMapping before ResourceHandler. Solved by setOrder(). Spring Boot code:

@EnableAutoConfiguration
@Configuration
@Slf4j
public class MvcConfiguration extends WebMvcConfigurerAdapter {

    @Bean(name = "urlViewController")
    public UrlFilenameViewController getUrlViewController() {
        return new UrlFilenameViewController();
    }

    @Bean
    public SimpleUrlHandlerMapping getUrlHandlerMapping() {
        SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
        handlerMapping.setMappings(new Properties() {
            {
                put("/view/*", "urlViewController");
            }
        });
        handlerMapping.setOrder(Integer.MAX_VALUE - 5);
        return handlerMapping;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("file:./resources/static/");
        ....
        registry.setOrder(Integer.MAX_VALUE);
    }
}

Upvotes: 1

Adam McCormick
Adam McCormick

Reputation: 335

Well this is my solution... for now.

I have to extend from WebMvcConfigurationSupport directly instead of using @EnableWebMvc

This is my updated configuration

@Configuration
@ComponentScan("org.commons.sandbox")
public class WebConfiguration extends WebMvcConfigurationSupport {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry){
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
        //just to be clear that this has a priority of 0, this is default anyway
        registry.setOrder(0);
    }

    @Bean
    public ViewResolver viewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Override
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping handler = super.requestMappingHandlerMapping();
            //now i have a handle on the handler i can lower it's priority
            //in the super class implementation this is set to 0 
        handler.setOrder(1);
        return handler;
    }
}

I can now set the priority of RequestMappingHandlerMapping to be below SimpleUrlHandlerMapping of the resource handler so that it resolves the static resource requests before controller classes get a chance

Upvotes: 7

Related Questions