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屬性,默認(rèn)為-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注冊(cè)了DispatcherServletRegistrationBean,它會(huì)讀取webMvcProperties.getServlet().getLoadOnStartup()然后設(shè)置其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屬性,默認(rèn)為-1,其configure方法會(huì)設(shè)置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屬性最后設(shè)置到了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方法會(huì)取出所有l(wèi)oadOnStartup大于等于0的wrapper,按loadOnStartup值放入到TreeMap<Integer, ArrayList<Wrapper>>,然后遍歷該TreeMap挨個(gè)執(zhí)行wrapper.load()進(jìn)行加載
小結(jié)
springboot的spring.mvc.servlet.load-on-startup屬性,最后設(shè)置到tomcat的StandardWrapper;而tomcat的StandardContext的loadOnStartup方法會(huì)取出所有l(wèi)oadOnStartup大于等于0的wrapper,按loadOnStartup值放入到TreeMap<Integer, ArrayList<Wrapper>>,然后遍歷該TreeMap挨個(gè)執(zhí)行wrapper.load()進(jìn)行加載。
以上就是聊聊spring.mvc.servlet.load-on-startup的詳細(xì)內(nèi)容,更多關(guān)于spring.mvc.servlet.load-on-startup的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringMVC項(xiàng)目訪問(wèn)controller時(shí)候報(bào)404的解決
這篇文章主要介紹了SpringMVC項(xiàng)目訪問(wèn)controller時(shí)候報(bào)404的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
SpringBoot整合Mybatis Generator自動(dòng)生成代碼
SpringBoot 整合 Mybatis Generator自動(dòng)生成dao、entity、mapper.xml實(shí)現(xiàn)單表增刪改查。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08
java返回json請(qǐng)求中文變成問(wèn)號(hào)的問(wèn)題及解決
這篇文章主要介紹了java返回json請(qǐng)求中文變成問(wèn)號(hào)的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
MybatisPlus調(diào)用原生SQL的三種方法實(shí)例詳解
這篇文章主要介紹了MybatisPlus調(diào)用原生SQL的三種方法,在有些情況下需要用到MybatisPlus查詢?cè)鶶QL,MybatisPlus其實(shí)帶有運(yùn)行原生SQL的方法,我這里列舉三種,需要的朋友可以參考下2022-09-09
SpringBoot定時(shí)任務(wù)的實(shí)現(xiàn)詳解
這篇文章主要介紹了SpringBoot定時(shí)任務(wù)的實(shí)現(xiàn)詳解,定時(shí)任務(wù)是企業(yè)級(jí)開(kāi)發(fā)中最常見(jiàn)的功能之一,如定時(shí)統(tǒng)計(jì)訂單數(shù)、數(shù)據(jù)庫(kù)備份、定時(shí)發(fā)送短信和郵件、定時(shí)統(tǒng)計(jì)博客訪客等,簡(jiǎn)單的定時(shí)任務(wù)可以直接通過(guò)Spring中的@Scheduled注解來(lái)實(shí)現(xiàn),需要的朋友可以參考下2024-01-01
Java構(gòu)造方法 super 及自定義異常throw合集詳解用法
異常是程序中的一些錯(cuò)誤,但不是所有錯(cuò)誤都是異常,且錯(cuò)誤有時(shí)候是可以避免的,super可以理解為是指向自己超(父)類對(duì)象的一個(gè)指針,而這個(gè)超類指的是離自己最近的一個(gè)父類,構(gòu)造器也叫構(gòu)造方法、構(gòu)造函數(shù),是一種特殊類型的方法,負(fù)責(zé)類中成員變量(域)的初始化2021-10-10
JAVA遞歸生成樹(shù)形菜單的實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了JAVA遞歸生成樹(shù)形菜單,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01

