最近在开发项目时遇到将springmvc无法处理的静态资源请求转发给tomcat默认的servlet进行处理的场景,然后根据DispatcherServlet请求的路径,找到了如何配置默认Servlet处理器。
具体需要看您是否使用了springmvc提供的方式完成的注入配置:
- 使用了@EnableWebMvc注解
- 使用了SpringBoot中的自动装配(org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.EnableWebMvcConfiguration)
这两种方式都是间接的使用了DelegatingWebMvcConfiguration完成了springmvc的配置
针对这种情况可以写一个WebMvcConfigurer接口的实现来完成配置:
- @Component
- public class WebMvcConfigurerImpl extends WebMvcConfigurerAdapter {
-
- @Override
- public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
- configurer.enable("default");
- }
- }
如果您是直接继承WebMvcConfigurationSupport类完成的springmvc配置,可以重写父类的方法来完成配置:
- @Configuration
- public class WebMvcConfigurationImpl extends WebMvcConfigurationSupport {
-
- @Override
- protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
- configurer.enable("default");
- }
-
- }
其中default是tomcat默认的Servlet的名称。
要了解此配置的实现机制需要看WebMvcConfigurationSupport中的定义:
- /**
- * Return a handler mapping ordered at Integer.MAX_VALUE with a mapped
- * default servlet handler. To configure "default" Servlet handling,
- * override {@link #configureDefaultServletHandling}.
- */
- @Bean
- public HandlerMapping defaultServletHandlerMapping() {
- DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(this.servletContext);
- configureDefaultServletHandling(configurer);
-
- HandlerMapping handlerMapping = configurer.buildHandlerMapping();
- return (handlerMapping != null ? handlerMapping : new EmptyHandlerMapping());
- }
-
- /**
- * Override this method to configure "default" Servlet handling.
- * @see DefaultServletHandlerConfigurer
- */
- protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
- }
类中定义了defaultServletHandlerMapping方法,方法中创建了DefaultServletHandlerConfigurer对象,使用此对象的buildHandlerMapping方法用于构建一个HandlerMapping对象。
- public class DefaultServletHandlerConfigurer {
-
- private final ServletContext servletContext;
-
- private DefaultServletHttpRequestHandler handler;
-
-
- /**
- * Create a {@link DefaultServletHandlerConfigurer} instance.
- * @param servletContext the ServletContext to use.
- */
- public DefaultServletHandlerConfigurer(ServletContext servletContext) {
- Assert.notNull(servletContext, "ServletContext is required");
- this.servletContext = servletContext;
- }
-
-
- /**
- * Enable forwarding to the "default" Servlet.
- *
When this method is used the {@link DefaultServletHttpRequestHandler}
- * will try to autodetect the "default" Servlet name. Alternatively, you can
- * specify the name of the default Servlet via {@link #enable(String)}.
- * @see DefaultServletHttpRequestHandler
- */
- public void enable() {
- enable(null);
- }
-
- /**
- * Enable forwarding to the "default" Servlet identified by the given name.
- *
This is useful when the default Servlet cannot be autodetected,
- * for example when it has been manually configured.
- * @see DefaultServletHttpRequestHandler
- */
- public void enable(String defaultServletName) {
- this.handler = new DefaultServletHttpRequestHandler();
- this.handler.setDefaultServletName(defaultServletName);
- this.handler.setServletContext(this.servletContext);
- }
-
-
- /**
- * Return a handler mapping instance ordered at {@link Integer#MAX_VALUE} containing the
- * {@link DefaultServletHttpRequestHandler} instance mapped to {@code "/**"};
- * or {@code null} if default servlet handling was not been enabled.
- * @since 4.3.12
- */
- protected SimpleUrlHandlerMapping buildHandlerMapping() {
- if (this.handler == null) {
- return null;
- }
-
- SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
- handlerMapping.setUrlMap(Collections.singletonMap("/**", this.handler));
- handlerMapping.setOrder(Integer.MAX_VALUE);
- return handlerMapping;
- }
-
- /**
- * @deprecated as of 4.3.12, in favor of {@link #buildHandlerMapping()}
- */
- @Deprecated
- protected AbstractHandlerMapping getHandlerMapping() {
- return buildHandlerMapping();
- }
-
- }
DefaultServletHandlerConfigurer中定义了enable方法,enable方法用于创建DefaultServletHttpRequestHandler对象,并设置DefaultServletHttpRequestHandler对象的默认Servlet名称和Servlet上下文;而buildHandlerMapping方法则用于创建一个SimpleUrlHandlerMapping对象用于处理其余HandlerMapping不能处理的所有请求,使用的处理器正是enable方法中创建的DefaultServletHttpRequestHandler对象。- @Override
- public void handleRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
-
- RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);
- if (rd == null) {
- throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +
- this.defaultServletName + "'");
- }
- rd.forward(request, response);
- }
DefaultServletHttpRequestHandler对象中处理请求使用了请求转发。