• 【spring mvc】配置默认Servlet处理器


    最近在开发项目时遇到将springmvc无法处理的静态资源请求转发给tomcat默认的servlet进行处理的场景,然后根据DispatcherServlet请求的路径,找到了如何配置默认Servlet处理器。

    一、配置方式

    具体需要看您是否使用了springmvc提供的方式完成的注入配置:

    1. 使用了@EnableWebMvc注解
    2. 使用了SpringBoot中的自动装配(org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration.EnableWebMvcConfiguration)

    这两种方式都是间接的使用了DelegatingWebMvcConfiguration完成了springmvc的配置

    针对这种情况可以写一个WebMvcConfigurer接口的实现来完成配置:

    1. @Component
    2. public class WebMvcConfigurerImpl extends WebMvcConfigurerAdapter {
    3. @Override
    4. public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    5. configurer.enable("default");
    6. }
    7. }

    如果您是直接继承WebMvcConfigurationSupport类完成的springmvc配置,可以重写父类的方法来完成配置:

    1. @Configuration
    2. public class WebMvcConfigurationImpl extends WebMvcConfigurationSupport {
    3. @Override
    4. protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    5. configurer.enable("default");
    6. }
    7. }

    其中default是tomcat默认的Servlet的名称。 

    二、原理

    要了解此配置的实现机制需要看WebMvcConfigurationSupport中的定义:

    1. /**
    2. * Return a handler mapping ordered at Integer.MAX_VALUE with a mapped
    3. * default servlet handler. To configure "default" Servlet handling,
    4. * override {@link #configureDefaultServletHandling}.
    5. */
    6. @Bean
    7. public HandlerMapping defaultServletHandlerMapping() {
    8. DefaultServletHandlerConfigurer configurer = new DefaultServletHandlerConfigurer(this.servletContext);
    9. configureDefaultServletHandling(configurer);
    10. HandlerMapping handlerMapping = configurer.buildHandlerMapping();
    11. return (handlerMapping != null ? handlerMapping : new EmptyHandlerMapping());
    12. }
    13. /**
    14. * Override this method to configure "default" Servlet handling.
    15. * @see DefaultServletHandlerConfigurer
    16. */
    17. protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    18. }

    类中定义了defaultServletHandlerMapping方法,方法中创建了DefaultServletHandlerConfigurer对象,使用此对象的buildHandlerMapping方法用于构建一个HandlerMapping对象。

      1. public class DefaultServletHandlerConfigurer {
      2. private final ServletContext servletContext;
      3. private DefaultServletHttpRequestHandler handler;
      4. /**
      5. * Create a {@link DefaultServletHandlerConfigurer} instance.
      6. * @param servletContext the ServletContext to use.
      7. */
      8. public DefaultServletHandlerConfigurer(ServletContext servletContext) {
      9. Assert.notNull(servletContext, "ServletContext is required");
      10. this.servletContext = servletContext;
      11. }
      12. /**
      13. * Enable forwarding to the "default" Servlet.
      14. *

        When this method is used the {@link DefaultServletHttpRequestHandler}

      15. * will try to autodetect the "default" Servlet name. Alternatively, you can
      16. * specify the name of the default Servlet via {@link #enable(String)}.
      17. * @see DefaultServletHttpRequestHandler
      18. */
      19. public void enable() {
      20. enable(null);
      21. }
      22. /**
      23. * Enable forwarding to the "default" Servlet identified by the given name.
      24. *

        This is useful when the default Servlet cannot be autodetected,

      25. * for example when it has been manually configured.
      26. * @see DefaultServletHttpRequestHandler
      27. */
      28. public void enable(String defaultServletName) {
      29. this.handler = new DefaultServletHttpRequestHandler();
      30. this.handler.setDefaultServletName(defaultServletName);
      31. this.handler.setServletContext(this.servletContext);
      32. }
      33. /**
      34. * Return a handler mapping instance ordered at {@link Integer#MAX_VALUE} containing the
      35. * {@link DefaultServletHttpRequestHandler} instance mapped to {@code "/**"};
      36. * or {@code null} if default servlet handling was not been enabled.
      37. * @since 4.3.12
      38. */
      39. protected SimpleUrlHandlerMapping buildHandlerMapping() {
      40. if (this.handler == null) {
      41. return null;
      42. }
      43. SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
      44. handlerMapping.setUrlMap(Collections.singletonMap("/**", this.handler));
      45. handlerMapping.setOrder(Integer.MAX_VALUE);
      46. return handlerMapping;
      47. }
      48. /**
      49. * @deprecated as of 4.3.12, in favor of {@link #buildHandlerMapping()}
      50. */
      51. @Deprecated
      52. protected AbstractHandlerMapping getHandlerMapping() {
      53. return buildHandlerMapping();
      54. }
      55. }
      DefaultServletHandlerConfigurer中定义了enable方法,enable方法用于创建DefaultServletHttpRequestHandler对象,并设置DefaultServletHttpRequestHandler对象的默认Servlet名称和Servlet上下文;而buildHandlerMapping方法则用于创建一个SimpleUrlHandlerMapping对象用于处理其余HandlerMapping不能处理的所有请求,使用的处理器正是enable方法中创建的DefaultServletHttpRequestHandler对象。
      1. @Override
      2. public void handleRequest(HttpServletRequest request, HttpServletResponse response)
      3. throws ServletException, IOException {
      4. RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);
      5. if (rd == null) {
      6. throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +
      7. this.defaultServletName + "'");
      8. }
      9. rd.forward(request, response);
      10. }

      DefaultServletHttpRequestHandler对象中处理请求使用了请求转发

  • 相关阅读:
    Lyapunov optimization 李雅普诺夫优化
    TMI4054H锂电池充电管理IC
    点云从入门到精通技术详解100篇-农作物叶片点云数据的三角网格重建
    Jmeter配置不同业务请求比例,应对综合场景压测
    T01西门子#DPRD_DAT
    Spring Boot 之 web 开发
    二叉树的前序遍历(C++)
    leetcode每日-2022.09-12-1608. 特殊数组的特征值
    spring入门aop和ioc
    Apifox能否替代Postman?
  • 原文地址:https://blog.csdn.net/m1729339749/article/details/138164027