当前位置: 首页 > news >正文

SpringBoot 底层机制分析【Tomcat 启动+Spring 容器初始化+Tomcat 如何关联Spring 容器】【下】

😀前言
本篇博文是关于SpringBoot 底层机制分析实现,希望能够帮助你更好的了解SpringBoot 😊

🏠个人主页:晨犀主页
🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大家,您的满意是我的动力😉😉

💕欢迎大家:这里是CSDN,我总结知识的地方,欢迎来到我的博客,感谢大家的观看🥰
如果文章有什么需要改进的地方还请大佬不吝赐教 先在此感谢啦😊

文章目录

  • 分析SpringBoot 底层机制【Tomcat 启动分析+Spring 容器初始化+Tomcat 如何关联Spring 容器】
    • 实现任务阶段1- 创建Tomcat, 并启动
      • ● 代码实现
      • 完成测试
      • 运行效果
    • 实现任务阶段2- 创建Spring 容器
      • ● 代码实现
    • 实现任务阶段3- 将Tomcat 和Spring 容器关联, 并启动Spring 容器
      • ● 代码实现
      • 完成测试
      • 注意事项和细节
    • 😄总结

分析SpringBoot 底层机制【Tomcat 启动分析+Spring 容器初始化+Tomcat 如何关联Spring 容器】

实现任务阶段1- 创建Tomcat, 并启动

说明: 创建Tomcat, 并启动

● 代码实现

1.修改nlc-springboot\pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.nlc</groupId><artifactId>nlc-springboot</artifactId><version>1.0-SNAPSHOT</version><!-- 导入springboot 父工程,规定的写法解读:1. springboot 我们指定2.5.3--><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.3</version></parent><!-- 导入web 项目场景启动器,会自动导入和web 开发相关依赖,非常方便--><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><!--用我们指定tomcat 版本来完, 可以到mvn 去获取依赖坐标.解读:1. 使用指定的tomcat 才会验证,效果高版本的tomcat默认不会真正监听2. 使用了指定tomcat , 需要在spring-boot-starter-web 排除内嵌的 starter-tomcat3. 否则会出现包冲突, 提示GenericServlet Not Found 类似错误--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>8.5.75</version></dependency></dependencies>
</project>

2 、创建nlc-springboot\src\main\java\com\nlc\nlcspringboot\NlcSpringApplication.java

public class NlcSpringApplication {//这里我们会创建tomcat对象,并关联Spring容器, 并启动public static void run() {try {//创建Tomcat对象 NlcTomcatTomcat tomcat = new Tomcat();//1. 让tomcat可以将请求转发到spring web容器,因此需要进行关联//2. "/nlcboot" 就是我们的项目的 application context , 就是我们原来配置tomcat时,指定的application context//3. "D:\\nlc_springboot\\nlc-springboot" 指定项目的目录tomcat.addWebapp("/nlcboot","D:\\nlc_springboot\\nlc-springboot");//设置9090tomcat.setPort(9090);//启动tomcat.start();//等待请求接入System.out.println("======9090====等待请求=====");tomcat.getServer().await();} catch (Exception e) {e.printStackTrace();}}
}

3、创建nlc-springboot\src\main\java\com\nlc\nlcspringboot\NlcMainApp.java

public class NlcMainApp {public static void main(String[] args) {//启动NlcSpringBoot项目/程序NlcSpringApplication.run();}
}

完成测试

运行效果

image-20230809170546683

image-20230809171436029

浏览器请求, http://localhost:9090/ , 这时没有返回信息

image-20230809110020515

实现任务阶段2- 创建Spring 容器

说明: 创建Spring 容器

● 代码实现

1 、创建nlc-springboot\src\main\java\com\nlc\nlcspringboot\bean\Monster.java , 做一个测试Bean

public class Monster {
}

2 、创建nlc-springboot\src\main\java\com\nlc\nlcspringboot\controlller\HiController.java, 作为Controller

@RestController
public class NlcHiController {@RequestMapping("/hi")public String hi() {System.out.println("hi i am HiController");return "hi i am HiController";}
}

3 、创建nlc-springboot\src\main\java\com\nlc\nlcspringboot\config\NlcConfig.java , 作为Spring 的配置文件.

@Configuration
@ComponentScan("com.nlc.nlcspringboot")
public class NlcConfig {/*** 1. 通过@Bean 的方式, 将new 出来的Bean 对象, 放入到Spring 容器* 2. 该bean 在Spring 容器的name 就是方法名* 3. 通过方法名, 可以得到new Monster()*/@Beanpublic Monster monster() {return new Monster();}
}

4 、创建nlc-springboot\src\main\java\com\nlc\nlcspringboot\NlcWebApplicationInitializer.java , 作为Spring 的容器.

/*** 解读* 1. 创建我们的Spring 容器* 2. 加载/关联Spring容器的配置-按照注解的方式* 3. 完成Spring容器配置的bean的创建, 依赖注入* 4. 创建前端控制器 DispatcherServlet , 并让其持有Spring容器* 5. 当DispatcherServlet 持有容器, 就可以进行分发映射, 回忆我们实现SpringMVC底层机制* 6. 这里onStartup 是Tomcat调用, 并把ServletContext 对象传入*/
public class NlcWebApplicationInitializer implements WebApplicationInitializer {@Overridepublic void onStartup(ServletContext servletContext) throws ServletException {System.out.println("startup ....");//加载Spring web application configuration => 容器//自己 写过 NlcSpringApplicationContextAnnotationConfigWebApplicationContext ac =new AnnotationConfigWebApplicationContext();//在ac中注册 NlcConfig.class 配置类ac.register(NlcConfig.class);ac.refresh();//刷新上下文,完成bean的创建和配置//1. 创建注册非常重要的前端控制器 DispatcherServlet//2. 让DispatcherServlet 持有容器//3. 这样就可以进行映射分发, 回忆一下SpringMvc机制[自己实现过]//NlcDispatcherServletDispatcherServlet dispatcherServlet = new DispatcherServlet(ac);//返回了ServletRegistration.Dynamic对象ServletRegistration.Dynamic registration =servletContext.addServlet("app", dispatcherServlet);//当tomcat启动时,加载 dispatcherServletregistration.setLoadOnStartup(1);//拦截请求,并进行分发处理//这里提示/ 和/*的配置,会匹配所有的请求,//当Servlet 配置了"/", 会覆盖tomcat 的DefaultServlet, 当其他的utl-pattern 都匹配不上时, 都会走这个Servlet, 这样可以拦截到其它静态资源//这个默认的servlet 是处理静态资源的,一旦拦截,静态资源不能处理//当Servelt 配置了"/*", 表示可以匹配任意访问路径registration.addMapping("/");}
}

实现任务阶段3- 将Tomcat 和Spring 容器关联, 并启动Spring 容器

说明: 将Tomcat 和Spring 容器关联, 并启动Spring 容器

● 代码实现

  1. 修改nlc-springboot\src\main\java\com\nlc\nlcspringboot\NlcSpringApplication.java
public class NlcSpringApplication {//这里我们会创建tomcat对象,并关联Spring容器, 并启动public static void run() {try {//创建Tomcat对象 NlcTomcatTomcat tomcat = new Tomcat();//1. 让tomcat可以将请求转发到spring web容器,因此需要进行关联//2. "/nlcboot" 就是我们的项目的 application context , 就是我们原来配置tomcat时,指定的application context//3. "D:\\nlc_springboot\\nlc-springboot" 指定项目的目录tomcat.addWebapp("/nlcboot","D:\\nlc_springboot\\nlc-springboot");//设置9090tomcat.setPort(9090);//启动tomcat.start();//等待请求接入System.out.println("======9090====等待请求=====");tomcat.getServer().await();} catch (Exception e) {e.printStackTrace();}}
}
  1. debug 一下, 看看是否进行Spring 容器的初始化工作, 可以看到ac.refresh() 会将NlcConfig.class 中配置Bean 实例化装入到容器中…

image-20230809162953008

image-20230809163055321

里面有很多,可以自己看看

image-20230809163520263

完成测试

1、启动项目, 运行NlcMainApp

public class NlcMainApp {public static void main(String[] args) {//启动NlcSpringBoot项目/程序NlcSpringApplication.run();}
}

2、运行的效果

image-20230809190615952

image-20230809191513799

注意事项和细节

1、如果启动包异常, 如下:

严重: Servlet [jsp] in web application [/nlcboot] threw load() exception
java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet
2 、解决方案, 引入对应版本的jasper 包即可, 修改nlc-springboot\pom.xml

<dependency><groupId>org.apache.tomcat</groupId><artifactId>tomcat-jasper</artifactId><version>8.5.75</version>
</dependency>

😄总结

  1. 如果启动包异常出现上述异常, 引入对应版本的jasper 包就可以解决。
  2. 前面配置的application context可以根据自己的需求修改。
  3. 指定项目的目录要根据自己的项目情况进行修改,否则会出现FileNotFoundException(系统找不到指定的文件)或NoSuchFileException(没有此类文件)。

😁热门专栏推荐
SpringBoot篇
SpringBoot 底层机制分析[上]
SpringBoot容器–注解的使用
SpringBoot 自动配置–常用配置
SpringBoot 依赖管理和自动配置—带你了解什么是版本仲裁
Spring Boot介绍–快速入门–约定优于配置

文章到这里就结束了,如果有什么疑问的地方请指出,诸大佬们一起来评论区一起讨论😁
希望能和诸大佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞

相关文章:

SpringBoot 底层机制分析【Tomcat 启动+Spring 容器初始化+Tomcat 如何关联Spring 容器】【下】

&#x1f600;前言 本篇博文是关于SpringBoot 底层机制分析实现&#xff0c;希望能够帮助你更好的了解SpringBoot &#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章可以帮助到大…...

NLP(六十五)LangChain中的重连(retry)机制

关于LangChain入门&#xff0c;读者可参考文章NLP&#xff08;五十六&#xff09;LangChain入门 。   本文将会介绍LangChain中的重连机制&#xff0c;并尝试给出定制化重连方案。   本文以LangChain中的对话功能&#xff08;ChatOpenAI&#xff09;为例。 LangChain中的重…...

C字符串与C++ string 类:用法万字详解(上)

目录 引言 一、C语言字符串 1.1 创建 C 字符串 1.2 字符串长度 1.3 字符串拼接 1.4 比较字符串 1.5 复制字符串 二、C字符串string类 2.1 解释 2.2 string构造函数 2.2.1 string() 默认构造函数 2.2.2 string(const char* s) 从 C 风格字符串构造 2.2.3 string(co…...

async/await函数需要trycatch吗?

前言 写异步函数的时候&#xff0c;promise 和 async 两种方案都非常常见&#xff0c;甚至同一个项目里&#xff0c;不同的开发人员都使用不同的习惯, 不过关于两者的比较不是本文关注的重点&#xff0c;只总结为一句话&#xff1a;“async 是异步编程的终极解决方案”。 当使…...

Jenkins集成appium自动化测试(Windows篇)

一&#xff0c;引入问题 自动化测试脚本绝大部分用于回归测试&#xff0c;这就需要制定执行策略&#xff0c;如每天、代码更新后、项目上线前定时执行&#xff0c;才能达到最好的效果&#xff0c;这时就需要进行Jenkins集成。 不像web UI自动化测试可以使用无痕浏览器做到无界…...

MongoDB:切换log日志文件

可以不重启MongoDB&#xff0c;切换日志文件 use admin db.runCommand({logRotate:1})参考 MongoDB 日志切割三种方式...

代码随想录第三十五天

代码随想录第三十五天 Leetcode 860. 柠檬水找零Leetcode 406. 根据身高重建队列Leetcode 452. 用最少数量的箭引爆气球 Leetcode 860. 柠檬水找零 题目链接: 柠檬水找零 自己的思路:我的垃圾思路&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;复…...

块、行内块水平垂直居中

1.定位实现水平垂直居中 <div class"outer"><div class"test inner1">定位实现水平垂直居中</div></div><style>.outer {width: 300px;height: 300px;border: 1px solid gray;margin: 100px auto 0;position: relative;}.te…...

Mybatis引出的一系列问题-动态 SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架&#xff0c;你应该能理解根据不同条件拼接 SQL 语句有多痛苦&#xff0c;例如拼接时要确保不能忘记添加必要的空格&#xff0c;还要注意去掉列表最后一个列名的逗号。利用动态 SQL&#xff0c;可以彻底…...

Docker学习之构建Base Image

构建Base Image 目标是构建一个类似官方Hello world的镜像&#xff0c;需要配置好Docker运行环境。 创建目录&#xff0c;编写代码 创建并进入docker目录。 mkdir docker cd dockertouch hello.cvim hello.chello.c文件的内容如下&#xff1a; #include <stdio.h>in…...

SFM(Structure from Motion)和NeRF(Neural Radiance Fields)

SFM&#xff08;Structure from Motion&#xff09;和NeRF&#xff08;Neural Radiance Fields&#xff09;都是计算机视觉领域中的重要算法&#xff0c;用于不同的任务和应用。 SFM&#xff08;Structure from Motion&#xff09;&#xff1a; SFM是一种从图像序列中重建三维场…...

[Vue] Vue2和Vue3的生命周期函数

vue2有11个生命周期钩子, vue3有8个生命周期钩子 从vue创建、运行、到销毁总是伴随着各种事件, 创建、挂载、更新到销毁。 1.vue2系列生命周期 ⑴【beforecreate】实例创建前。 vue完全创建之前&#xff0c;会自动执行这个函数。 ⑵【Created】实例创建后。 这也是个生命…...

springboot集成分布式任务调度系统xxl-job(调度器和执行器)

一、部署xxl-job服务端 下载xxl-job源码 下载地址&#xff1a; https://gitee.com/xuxueli0323/xxl-job 二、导入项目、创建xxl_job数据库、修改配置文件为自己的数据库 三、启动项目、访问首页 访问地址&#xff1a; http://localhost:8080/xxl-job-admin/ 账号&#xff1…...

11_Vue3中的新的组件

1. Fragment 在Vue2中&#xff1a;组件必须要有一个跟标签在Vue3中&#xff1a;组件可以没有根标签&#xff0c;内部会将多个标签包含在一个Fragment虚拟元素中好处&#xff1a;减少标签层级&#xff0c;减少内存占用 2. Teleport 什么是Teleport?——Teleport 是一种能够将…...

详解推送Git分支时发生的 cannot lock ref 错误

在码云上建了一个项目仓库,分支模型使用 git-flow ,并在本地新建了一个功能分支 feature/feature-poll。后来在推送时发生错误,提示 cannot lock ref ...... 这样的错误信息。下面复盘一下具体过程和解决办法,以供参考。 在码云中建立仓库时,考虑到想按照 GitFlow 的模式…...

[国产MCU]-BL602开发实例-PWM

PWM 文章目录 PWM1、BL602的PWM介绍2、PWM驱动API介绍3、PWM使用示例脉冲宽度调制(Pulse width modulation,简称PWM)是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳定电源输出的改变。这种方…...

【JMeter】 使用Synchronizing Timer设置请求集合点,实现绝对并发

目录 布局设置说明 Number of Simulated Users to Group Timeout in milliseconds 使用时需要注意的点 集合点作用域 实际运行 资料获取方法 布局设置说明 参数说明&#xff1a; Number of Simulated Users to Group 每次释放的线程数量。如果设置为0&#xff0c;等同…...

无法对watchdog.sys等系统文件删除,弯道修复,这里解决办法很简单

右击360强力删除...

ClickHouse(九):Clickhouse表引擎 - Log系列表引擎

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…...

3.1 计算机网络和网络设备

数据参考&#xff1a;CISP官方 目录 计算机网络基础网络互联设备网络传输介质 一、计算机网络基础 1、ENIAC&#xff1a;世界上第一台计算机的诞生 1946年2月14日&#xff0c;宾夕法尼亚大学诞生了世界上第一台计算机&#xff0c;名为电子数字积分计算机&#xff08;ENIAC…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...