spring.mvc.servlet.load-on-startup属性方法源码解读

 更新时间:2023年12月10日 08:36:13   作者:codecraft  
这篇文章主要介绍了spring.mvc.servlet.load-on-startup的属性方法源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下spring.mvc.servlet.load-on-startup

spring.mvc.servlet.load-on-startup

org/springframework/boot/autoconfigure/web/servlet/WebMvcProperties.java

@ConfigurationProperties(prefix = "spring.mvc")
public class WebMvcProperties {
    //......
    private final Servlet servlet = new Servlet();
    public static class Servlet {
        /**
         * Path of the dispatcher servlet.
         */
        private String path = "/";
        /**
         * Load on startup priority of the dispatcher servlet.
         */
        private int loadOnStartup = -1;
        public String getPath() {
            return this.path;
        }
        public void setPath(String path) {
            Assert.notNull(path, "Path must not be null");
            Assert.isTrue(!path.contains("*"), "Path must not contain wildcards");
            this.path = path;
        }
        public int getLoadOnStartup() {
            return this.loadOnStartup;
        }
        public void setLoadOnStartup(int loadOnStartup) {
            this.loadOnStartup = loadOnStartup;
        }
        public String getServletMapping() {
            if (this.path.equals("") || this.path.equals("/")) {
                return "/";
            }
            if (this.path.endsWith("/")) {
                return this.path + "*";
            }
            return this.path + "/*";
        }
        public String getPath(String path) {
            String prefix = getServletPrefix();
            if (!path.startsWith("/")) {
                path = "/" + path;
            }
            return prefix + path;
        }
        public String getServletPrefix() {
            String result = this.path;
            int index = result.indexOf('*');
            if (index != -1) {
                result = result.substring(0, index);
            }
            if (result.endsWith("/")) {
                result = result.substring(0, result.length() - 1);
            }
            return result;
        }
    }    
}
WebMvcProperties.Servlet定义了loadOnStartup属性,默认为-1

DispatcherServletAutoConfiguration

org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration.java

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(DispatcherServlet.class)
@AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class)
public class DispatcherServletAutoConfiguration {

    //......

    @Configuration(proxyBeanMethods = false)
    @Conditional(DispatcherServletRegistrationCondition.class)
    @ConditionalOnClass(ServletRegistration.class)
    @EnableConfigurationProperties(WebMvcProperties.class)
    @Import(DispatcherServletConfiguration.class)
    protected static class DispatcherServletRegistrationConfiguration {

        @Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
        @ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
        public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
                WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
            DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
                    webMvcProperties.getServlet().getPath());
            registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
            registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
            multipartConfig.ifAvailable(registration::setMultipartConfig);
            return registration;
        }

    }

    //......
}
DispatcherServletRegistrationConfiguration注册了DispatcherServletRegistrationBean,它会读取webMvcProperties.getServlet().getLoadOnStartup()然后设置其loadOnStartup属性

ServletRegistrationBean

org/springframework/boot/web/servlet/ServletRegistrationBean.java

public class ServletRegistrationBean<T extends Servlet> extends DynamicRegistrationBean<ServletRegistration.Dynamic> {
    private static final String[] DEFAULT_MAPPINGS = { "/*" };
    private T servlet;
    private Set<String> urlMappings = new LinkedHashSet<>();
    private boolean alwaysMapUrl = true;
    private int loadOnStartup = -1;
    private MultipartConfigElement multipartConfig;
    //......
    @Override
    protected void configure(ServletRegistration.Dynamic registration) {
        super.configure(registration);
        String[] urlMapping = StringUtils.toStringArray(this.urlMappings);
        if (urlMapping.length == 0 && this.alwaysMapUrl) {
            urlMapping = DEFAULT_MAPPINGS;
        }
        if (!ObjectUtils.isEmpty(urlMapping)) {
            registration.addMapping(urlMapping);
        }
        registration.setLoadOnStartup(this.loadOnStartup);
        if (this.multipartConfig != null) {
            registration.setMultipartConfig(this.multipartConfig);
        }
    }
}
ServletRegistrationBean定义了loadOnStartup属性,默认为-1,其configure方法会设置loadOnStartup到ServletRegistration.Dynamic

StandardWrapper

org/apache/catalina/core/StandardWrapper.java

/**
     * Set the load-on-startup order value (negative value means
     * load on first call).
     *
     * @param value New load-on-startup value
     */
    @Override
    public void setLoadOnStartup(int value) {
        int oldLoadOnStartup = this.loadOnStartup;
        this.loadOnStartup = value;
        support.firePropertyChange("loadOnStartup",
                                   Integer.valueOf(oldLoadOnStartup),
                                   Integer.valueOf(this.loadOnStartup));
    }
    /**
     * @return the load-on-startup order value (negative value means
     * load on first call).
     */
    @Override
    public int getLoadOnStartup() {
        if (isJspServlet && loadOnStartup < 0) {
            /*
             * JspServlet must always be preloaded, because its instance is
             * used during registerJMX (when registering the JSP
             * monitoring mbean)
             */
             return Integer.MAX_VALUE;
        } else {
            return this.loadOnStartup;
        }
    }
loadOnStartup属性最后设置到了tomcat的StandardWrapper

StandardContext

org/apache/catalina/core/StandardContext.java

/**
     * Load and initialize all servlets marked "load on startup" in the
     * web application deployment descriptor.
     *
     * @param children Array of wrappers for all currently defined
     *  servlets (including those not declared load on startup)
     * @return <code>true</code> if load on startup was considered successful
     */
    public boolean loadOnStartup(Container children[]) {
        // Collect "load on startup" servlets that need to be initialized
        TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap<>();
        for (Container child : children) {
            Wrapper wrapper = (Wrapper) child;
            int loadOnStartup = wrapper.getLoadOnStartup();
            if (loadOnStartup < 0) {
                continue;
            }
            Integer key = Integer.valueOf(loadOnStartup);
            ArrayList<Wrapper> list = map.get(key);
            if (list == null) {
                list = new ArrayList<>();
                map.put(key, list);
            }
            list.add(wrapper);
        }
        // Load the collected "load on startup" servlets
        for (ArrayList<Wrapper> list : map.values()) {
            for (Wrapper wrapper : list) {
                try {
                    wrapper.load();
                } catch (ServletException e) {
                    getLogger().error(sm.getString("standardContext.loadOnStartup.loadException",
                          getName(), wrapper.getName()), StandardWrapper.getRootCause(e));
                    // NOTE: load errors (including a servlet that throws
                    // UnavailableException from the init() method) are NOT
                    // fatal to application startup
                    // unless failCtxIfServletStartFails="true" is specified
                    if(getComputedFailCtxIfServletStartFails()) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
StandardContext的loadOnStartup方法会取出所有loadOnStartup大于等于0的wrapper,按loadOnStartup值放入到TreeMap<Integer, ArrayList<Wrapper>>,然后遍历该TreeMap挨个执行wrapper.load()进行加载

小结

springboot的spring.mvc.servlet.load-on-startup属性,最后设置到tomcat的StandardWrapper;而tomcat的StandardContext的loadOnStartup方法会取出所有loadOnStartup大于等于0的wrapper,按loadOnStartup值放入到TreeMap<Integer, ArrayList<Wrapper>>,然后遍历该TreeMap挨个执行wrapper.load()进行加载。

以上就是聊聊spring.mvc.servlet.load-on-startup的详细内容,更多关于spring.mvc.servlet.load-on-startup的资料请关注脚本之家其它相关文章!

相关文章

  • 一文掌握Spring Boot 日志文件

    一文掌握Spring Boot 日志文件

    日志是程序的重要组成部分,日志对于我们来说,最主要的用途就是排除和定位问题,这篇文章主要介绍了Spring Boot 日志文件,需要的朋友可以参考下
    2023-03-03
  • 详解Java类型擦除机制

    详解Java类型擦除机制

    Java泛型是JDK 5引入的一个特性,它允许我们定义类和接口的时候使用参数类型,泛型在集合框架中被广泛使用。这篇文章主要介绍了Java类型擦除机制,需要的朋友可以参考下
    2019-07-07
  • 基于selenium 获取新页面元素失败的解决方法

    基于selenium 获取新页面元素失败的解决方法

    今天小编就为大家分享一篇基于selenium 获取新页面元素失败的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • JPA设置默认字段及其长度详解

    JPA设置默认字段及其长度详解

    JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。本文主要介绍了JPA如何设置默认字段及其长度,感兴趣的同学可以了解一下
    2021-12-12
  • java实现简单银行家算法

    java实现简单银行家算法

    这篇文章主要为大家详细介绍了java实现简单银行家算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • springboot3环境隔离的实现

    springboot3环境隔离的实现

    在开发中,环境很多,本文主要介绍了springboot3环境隔离的实现,能够快速切换开发、测试、生产环境,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Gradle的使用教程详解

    Gradle的使用教程详解

    Gradle它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,目前也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置,下面通过本文给大家介绍Gradle的使用教程,感兴趣的朋友一起看看吧
    2020-09-09
  • 处理Log4j2不能打印行号的问题(AsyncLogger)

    处理Log4j2不能打印行号的问题(AsyncLogger)

    这篇文章主要介绍了处理Log4j2不能打印行号的问题(AsyncLogger),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Spring实战之ResourceLoader接口资源加载用法示例

    Spring实战之ResourceLoader接口资源加载用法示例

    这篇文章主要介绍了Spring实战之ResourceLoader接口资源加载用法,结合实例形式分析了Spring使用ResourceLoader接口加载资源的相关配置与使用技巧,需要的朋友可以参考下
    2020-01-01
  • java优化if-else的11种方案

    java优化if-else的11种方案

    If-Else结构是一种常见的条件判断语句,通过优化If-Else结构,可以提高代码的可读性和执行效率,本文主要介绍了java优化if-else的11种方案,感兴趣的可以了解一下
    2024-08-08

最新评论