In the Spring MVC framework XML based configuration the mvc namespace provides a number of handy elements for configuration your web application. If you include the following in your XML configuration
<mvc:annotation-driven />
then org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
does a lot of the heavy lifting for you including instantiating a HandlerMapping and injecting interceptors and a ContentNegotiationManager that you can define using the <mvc:interceptors>
element and content-negotiation-manager
attribute of <mvc:annotation-driven>
respectively.
If like me you want all this work doing for you but you want to tweak a property of the HandlerMapping then you run into a problem. There’s no facility provided by the XML configuration to allow this. This is covered in a Spring issue (go vote for it).
Here I’m sharing the workaround I’ve settled on which, unlike every other suggestion I’ve spotted, maintains support for <mvc:interceptors>.
Override the DispatcherServlet
to configure RequestMappingHandlerMapping
This code assumes you’re running in a Servlet 3.0 container. If not you’ll have to configure your DispatcherServlet
in web.xml.
Here I’ve used initStrategies
(where the HandlerMapping
instances are added to the DispatcherServlet
) to inspect the Spring context for relevant beans and set the property I wanted (stripping URL path parameters).
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.handler.AbstractHandlerMapping;
@WebServlet(name="spring-dispatcher", loadOnStartup=1, urlPatterns={"/"}, initParams={@WebInitParam(name="contextConfigLocation", value="/WEB-INF/spring/spring-dispatcher-servlet.xml")}) public class MyDispatcherServlet extends DispatcherServlet { @Override protected void initStrategies(ApplicationContext context) { super.initStrategies(context); for (AbstractHandlerMapping handlerMapping : BeanFactoryUtils.beansOfTypeIncludingAncestors( context, AbstractHandlerMapping.class, true, false).values()) { handlerMapping.setRemoveSemicolonContent(true); } } }