Is it possible to extend WebMvcConfigurationSuppor

2020-02-02 11:10发布

问题:

I need to extend the WebMvcConfigurationSupport class too modify two things:

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {
    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
        handlerMapping.setRemoveSemicolonContent(false);
        handlerMapping.setOrder(1);
        return handlerMapping;
    }
}

I like the defaults that are registered from the WebMvcAutoConfiguration class but due to the conditional annotation on the class, when I extend the WebMvcConfigurationSupport class it prevents the auto configuration from happening.

@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
    WebMvcConfigurerAdapter.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class WebMvcAutoConfiguration {...}

Is there to have the WebMvcAutoConfiguration class load without having to essentially copy/paste most of the code in that class?

Or is it possible to call RequestMappingHandlerMapping setOrder() and setRemoveSemicolonContent() from somewhere else so I can just use the @EnableWebMvc annotation and have the autoconfiguration class run without any issues?

Thanks in advance!

回答1:

Your analysis is correct (@EnableWebMvc or directly extending WebMvcConfigurationSupport will switch off the WebMvcAutoConfiguration). I'm not sure what the alternative is, since a) we need a "get-out" clause for the autoconfig, and b) I don't think Spring likes to have two WebMvcConfigurationSupports in the same context. Happy to discuss on github if you want to try and find a way to change it (there might be some middle ground).



回答2:

Extend from DelegatingWebMvcConfiguration instead of WebMvcConfigurationSupport, it will not prevent the autoconfig to take place:

@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {
    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
        handlerMapping.setRemoveSemicolonContent(false);
        handlerMapping.setOrder(1);
        return handlerMapping;
    }
}


回答3:

I managed to customize the RequestMappingHandlerMapping while keeping WebMvcAutoConfiguration using a BeanPostProcessor:

@Configuration
public class RequestMappingConfiguration {
    @Bean
    public RequestMappingHandlerMappingPostProcessor requestMappingHandlerMappingPostProcessor() {
        return new RequestMappingHandlerMappingPostProcessor();
    }

    public static class RequestMappingHandlerMappingPostProcessor implements BeanPostProcessor {

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof RequestMappingHandlerMapping) {
                ((RequestMappingHandlerMapping) bean).setUseSuffixPatternMatch(false);
            }
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
}

I would be happy if Spring Boot provides a better way to handle that... maybe something could be done around PathMatchConfigurer ?



回答4:

I think the best way to do this in Spring Boot now is to add a WebMvcRegistrations component to your context - this solution didn't exist at the time of your question (it's been available since Spring Boot 1.4.0).