聊聊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;//......@Overrideprotected 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*/@Overridepublic 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).*/@Overridepublic 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 initializedTreeMap<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" servletsfor (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 specifiedif(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()进行加载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/210703.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

json精讲

本文介绍json的规范及javascript和java对数据的交换读取 1. json介绍1.1 json简介1.2为什么使用 JSON&#xff1f; 2. json规范2.1基础规范2.2 key值为-字符串、数字、布尔值2.3 key值为对象Object2.4 key值为数组2.5 json本身就是一个数组 3.javascript操作json3.1 javascript…

WPF(Windows Presentation Foundation) 的 Menu控件

WPF&#xff08;Windows Presentation Foundation&#xff09;的 Menu 是一种用于创建菜单的控件。菜单通常位于应用程序窗口的顶部&#xff0c;并提供了一组命令或选项&#xff0c;用于导航到不同的功能区域、执行特定的操作或访问特定的功能。 Menu 控件是 WPF 中的一个容器…

2、关于使用ajax验证绕过(实例2)

ajax原理我上一篇有写过&#xff0c;参考&#xff1a;1、关于前端js-ajax绕过-CSDN博客 一、实例环境&#xff1a; 为手机上的某一割韭菜app 二、目的&#xff1a; 实现绕过手机验证码&#xff0c;找回密码 三、工具&#xff1a; bp代理 四、验证步骤如下&#xff1a; …

ECU安全学习网站和书籍介绍

ECU安全是指关注和保护汽车电子控制单元&#xff08;ECU&#xff09;的安全性和防护措施。ECU是现代汽车中的关键组件&#xff0c;它负责监控和控制车辆各种系统的运行&#xff0c;如发动机、制动、转向等。ECU安全的重要性在于防止恶意攻击者操控或干扰车辆的操作。 ECU安全涉…

hive自定义函数及案例

一.自定义函数 1.Hive自带了一些函数&#xff0c;比如&#xff1a;max/min等&#xff0c;但是数量有限&#xff0c;自己可以通过自定义UDF来方便的扩展。 2.当Hive提供的内置函数无法满足你的业务处理需要时&#xff0c;此时就可以考虑使用用户自定义函数。 3.根据用户自定义…

GitHub为Rust语言添加了供应链安全工具

GitHub的供应链安全特性包括咨询数据库、Dependabot警报和依赖关系图现在可以用于Rust Cargo文件。 为了帮助Rust开发人员发现和防止安全漏洞&#xff0c;GitHub已经为快速增长的Rust语言提供了供应链安全特性套件。 这些特性包括GitHub Advisory Database&#xff0c;它已经有…

构建外卖系统:使用Django框架

在当今数字化的时代&#xff0c;外卖系统的搭建不再是什么复杂的任务。通过使用Django框架&#xff0c;我们可以迅速建立一个强大、灵活且易于扩展的外卖系统。本文将演示如何使用Django构建一个简单的外卖系统&#xff0c;并包含一些基本的技术代码。 步骤一&#xff1a;安装…

shell的条件测试

shell 的条件测试 概述 条件测试是 shell 编程中非常重要的一个概念&#xff0c;它允许我们根据某个条件是否满足&#xff0c;来选择执行相应的任务。 条件测试的语法 shell 中的条件测试语法如下&#xff1a; [ 条件表达式 ]如果条件表达式为真&#xff0c;则返回 0&…

CentOS 7.9--离线安装python3.9.18+virtualenv-20.25.0

# 想在centos6.x 上安装新版本的python&#xff0c;但是担心在用系统的环境被破坏&#xff0c;所以需要安装python虚拟环境&#xff0c;然后就找到自用的aliyun主机先测试下离线安装&#xff0c;在用6.X环境是没有互联网的&#xff0c;必须需要离线安装。 1. 下载对应python源…

力扣解题之保姆教程:(1)两数之和(代码详解)

题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回…

Django模板

以下是一个简单的Django模板示例&#xff1a; <!DOCTYPE html> <html><head><title>{{ title }}</title></head><body><h1>{{ heading }}</h1><p>{{ content }}</p></body> </html>一、模板的…

波奇学Linux:父子进程和进程状态

vim编辑器&#xff0c;编写一个程序模拟进程 在vim中查看sleep函数 底行模式输入 写个Makefile自动运行波奇学Linux:yum和vim-CSDN博客 运行程序 PID和PPID 查看进程目录信息 实际有过滤出来有两个&#xff0c;一个进程本身一个是grep程序&#xff0c;通过 -v grep过滤走含gre…

新版Android Studio 正则表达式匹配代码注释,删除注释,删除全部注释,IntelliJ IDEA 正则表达式匹配代码注释

正则表达式匹配代码注释 完整表达式拼接Android Studio 搜索匹配【IntelliJ IDEA 也是一样的】 完整表达式拼接 (/*{1,2}[\s\S]?*/)|(//[\x{4e00}-\x{9fa5}].)|(<!-[\s\S]?–>)|(^\s\n)|(System.out.println.*) 表达式拆解&#xff0c;可以根据自己需求自由组合&#x…

Mybatis、Mybatis整合Spring的流程图

Mybatis 注意MapperProxy里面有invoke方法&#xff0c;当进到invoker方法会拿到 二、mybatis整合Spring 1、当我们的拿到的【Dao】其实就是【MapperProxy】&#xff0c;执行Dao的方法时&#xff0c;会被MapperProxy的【Invoke方法拦截】 2、图上已经标注了MapperProxy包含哪些…

力扣:200. 岛屿数量(Python3)

题目&#xff1a; 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此外&#xff0c;你可以假…

STM32-TIM定时器中断

目录 一、TIM&#xff08;Timer&#xff09;定时器简介 二、定时器类型 2.1基本定时器结构 2.2通用定时器结构 2.3高级定时器结构 三、定时中断基本结构 四、时序图分析 4.1 预分频器时序 4.2 计数器时序 4.3 计数器无预装时序&#xff08;无影子寄存器&#xff09; …

C#的线程技术及操作

每个正在操作系统上运行的应用程序都是一个进程&#xff0c;一个进程可以包括一个或多个线程。线程是操作系统分配处理器时间的基本单元&#xff0c;在进程中可以有多个线程同时执行代码。每个线程都维护异常处理程序、调度优先级和一组系统用于在调度该线程前保存线程上下文的…

PyQt6 水平布局Horizontal Layout (QHBoxLayout)

锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计41条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话版…

[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-1开环系统与闭环系统Open/Closed Loop System

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-1开环系统与闭环系统Open/Closed Loop System EG1: 烧水与控温水壶EG2: 蓄水与最终水位闭环控制系统 EG1: 烧水与控温水壶 EG2: 蓄水与最终水位 h ˙ q i n A − g h A R \dot{…

阿里云SLS采集jvm日志

一、背景 java应用部署在阿里云的k8s容器里&#xff0c;采集其日志的需求则是一个不可缺少的。而不同公司的jvm日志会存在很大的差异&#xff0c;所以本文仅以我的实际情况作一个示例&#xff0c;仅供有需要采集jvm日志的同学们一个参考。 我们打印的Jvm日志格式见下&#xf…