springboot系列六: springboot底层机制实现 下

实现SpringBoot底层机制[Tomcat启动分析 + Spring容器初始化 + Tomcat如何关联Spring容器]

  • 实现任务阶段1-创建Tomcat, 并启动
    • 🥦说明:创建Tomcat, 并启动
    • 🥦分析+代码实现
    • 🥦完成测试
  • 实现任务阶段2-创建Spring容器
    • 🥦说明:创建Spring容器
    • 🥦分析+代码实现
  • 实现任务阶段3-将Tomcat 和 Spring容器关联, 并启动Spring容器
    • 🥦说明:将Tomcat 和 Spring容器关联, 并启动Spring容器
    • 🥦分析+代码实现
    • 🥦完成测试
    • 🥦注意事项和细节
    • 在这里插入图片描述

在这里插入图片描述


⬅️ 上一篇: springboot系列五: springboot底层机制实现 上


🎉 欢迎来到 springboot系列六: springboot底层机制实现 下 🎉

在本篇文章中,我们将继续深入探讨 Spring Boot 的底层机制。通过进一步理解这些底层机制,您可以更加全面地掌握 Spring Boot 的工作原理,并在实际项目中灵活运用。


🔧 本篇需要用到的项目: zzw-springboot项目


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

🥦说明:创建Tomcat, 并启动

🥦分析+代码实现

1.修改E:\idea_project\zzw_springboot\zzw-springboot\pom.xml

<!--导入web项目场景启动器: 会自动导入和web开发相关的所有依赖[库/jar]
后面还会说明spring-boot-starter-web 到底引入哪些相关依赖-->
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!--因为我们自己要创建Tomcat对象, 并启动.因此我们先排除 内嵌的 spring-boot-starter-tomcat--><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></exclusion></exclusions></dependency><!--我们指定tomcat版本, 引入tomcat依赖/库1.使用指定的tomcat 8.5.75, 请小伙伴也引入这个版本2.如果我们引入自己指定的tomcat, 一定要记住把前面spring-boot-starter-tomcat排除3.如果你不排除, 会出现 GenericServlet Not Found 的错误提示.--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-core</artifactId><version>8.5.75</version></dependency>
</dependencies>

2.创建src/main/java/com/zzw/zzwspringboot/ZzwSpringApplication.java

public class ZzwSpringApplication {//这里我们会创建Tomcat对象, 并关联Spring容器, 并启动public static void run() {try {//创建Tomcat对象Tomcat tomcat = new Tomcat();//设置9090端口tomcat.setPort(9090);//启动, 就会在9090端口监听tomcat.start();//等待请求接入System.out.println("====9090 等待请求接入====");tomcat.getServer().await();} catch (Exception e) {throw new RuntimeException(e);}}
}

3.主程序src/main/java/com/zzw/zzwspringboot/ZzwMainApp.java

//主程序
public class ZzwMainApp {public static void main(String[] args) {//启动ZzwSpringBoot项目/程序ZzwSpringApplication.run();}
}

🥦完成测试

1.运行效果
在这里插入图片描述

2.浏览器请求 http://localhost:9090/, 这时没有返回信息, 因为还没有写Controller.
在这里插入图片描述

3.管理员权限运行cmd窗口, 输入netstat -anb. 证明9090端口真的在监听.

在这里插入图片描述

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

🥦说明:创建Spring容器

🥦分析+代码实现

1.新建src/main/java/com/zzw/zzwspringboot/bean/Monster.java, 做一个测试Bean

public class Monster {
}

2.新建src/main/java/com/zzw/zzwspringboot/controller/ZzwHiController.java, 作为Controller

@RestController
public class ZzwHiController {@RequestMapping("/hi")public String hi() {return "hi ZzwHiController";}
}

3.新建src/main/java/com/zzw/zzwspringboot/config/ZzwConfig.java, 作为Spring的配置文件

/*** ZzwConfig 配置类 作为Spring的配置文件* 这里有一个问题, 容器怎么知道要扫描哪些包 ?=> 一会代码体现** 在配置类中可以指定要扫描的包: @ComponentScan("com.zzw.zzwspringboot")*/
@Configuration
@ComponentScan("com.zzw.zzwspringboot")
public class ZzwConfig {//注入Bean - monster 对象到Spring容器@Beanpublic Monster monster() {return new Monster();}
}

4.新建src/main/java/com/zzw/zzwspringboot/ZzwWebApplicationInitializer.java

/*** 解读* 1.创建我们的Spring容器, Initializer-初始化器* 2.加载/关联Spring容器的配置-按照注解的方式* 3.完成Spring容器配置的bean的创建, 依赖注入* 4.创建前端控制器 DispatcherServlet, 并让其持有Spring容器* 5.当 DispatcherServlet 持有容器, 就可以进行分发映射, 回忆实现SpringMVC底层机制* 6.这里onStartup 是Tomcat调用, 并把ServletContext 对象传入*/
public class ZzwWebApplicationInitializer implements WebApplicationInitializer {@Overridepublic void onStartup(ServletContext servletContext) throws ServletException {System.out.println("startup ...");//加载Spring web application configuration => 容器//自己实现的Spring容器叫做 ZzwSpringApplicationContextAnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();//在ac中, 注册 ZzwConfig.class配置类ac.register(ZzwConfig.class);//刷新ac.refresh();//完成bean的创建和配置//1.创建注册非常重要的前端控制器 DispatcherServlet//2.让DispatcherServlet 持有容器//3.这样就可以进行映射分发, 回忆一下我们自己实现的SpringMVC的机制DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);//返回了ServletRegistration.Dynamic 对象ServletRegistration.Dynamic registration= servletContext.addServlet("app", dispatcherServlet);//当tomcat启动时,加载 dispatcherServletregistration.setLoadOnStartup(1);//拦截请求, 并进行分发处理//这里再提示一下 / 和 /* 的区别registration.addMapping("/");}
}

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

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

🥦分析+代码实现

1.修改src/main/java/com/zzw/zzwspringboot/ZzwSpringApplication.java

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

2.debug运行一下, 这时会报错, 解决方案

在这里插入图片描述

refresh()负责注入初始化相关bean, 在未执行refresh方法前, spring容器是没有bean的

在这里插入图片描述

初始化后, 容器中有了bean文件

在这里插入图片描述

🥦完成测试

1.拿掉断点, 运行程序

2.浏览器请求 http://localhost:9090/zzwboot/hi
在这里插入图片描述

🥦注意事项和细节

1.如果启动包异常, 如下:
严重: Servlet [jsp] in web application [/zzwboot] threw load() exception
java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet

2.解决方案: 引入对应版本的jasper包即可, 修改E:\idea_project\zzw_springboot\zzw-springboot\pom.xml

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

在这里插入图片描述

🔜 下一篇预告: springboot系列七: Lombok注解,Spring Initializr,yaml语法


📚 目录导航 📚

  1. springboot系列一: springboot初步入门
  2. springboot系列二: sprintboot依赖管理
  3. springboot系列三: sprintboot自动配置
  4. springboot系列四: sprintboot容器功能
  5. springboot系列五: springboot底层机制实现 上
  6. springboot系列六: springboot底层机制实现 下
  7. springboot系列七: Lombok注解,Spring Initializr,yaml语法

💬 读者互动 💬
在探索 Spring Boot 底层机制的过程中,您有哪些新的发现或疑问?欢迎在评论区留言,让我们一起讨论吧!😊


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

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

相关文章

H5项目使用vant组件的手机号校验

前言&#xff1a; 在开发h5项目的时候遇到手机号校验&#xff0c;原本想采用后台管理那种校验方式&#xff08;validator函数写校验手机号逻辑&#xff09;猛然间发现&#xff0c;可以在使用行内使用pattern属性 用法如下 <van-form submit"onSubmit"><van-…

bug,属性注入时为null

因为在使用拦截器时使用的是new的这个类放容器的 解决方法&#xff1a; 使用有参构造器&#xff0c;在new对象时传入值

鸿蒙开发设备管理:【@ohos.sensor (传感器)】

传感器 说明&#xff1a; 本模块首批接口从API version 8开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import sensor from ohos.sensor;sensor.on ACCELEROMETER on(type: SensorType.SENSOR_TYPE_ID_ACCELEROMETER, callback: C…

HexPlane: A Fast Representation for Dynamic Scenes(总结图)

图1。用于动态三维场景的 Hex刨面。我们没有从深度 MLP 中回归颜色和不透明度&#xff0c;而是通过 HexPlann 显式地计算时空点的特征。配对一个微小的 MLP&#xff0c;它允许以上100倍加速匹配的质量。 图2。方法概述。Hex刨包含六个特征平面&#xff0c;跨越每对坐标轴(例如…

PyTorch计算机视觉实战:目标检测、图像处理与深度学习

本书基于真实数据集&#xff0c;全面系统地阐述现代计算机视觉实用技术、方法和实践&#xff0c;涵盖50多个计算机视觉问题。全书分为四部分&#xff1a;一部分介绍神经网络和PyTorch的基础知识&#xff0c;以及如何使用PyTorch构建并训练神经网络&#xff0c;包括输入数据缩放…

【前端VUE】VUE3第一节—vite创建vue3工程

什么是VUE Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。无论是简单还是复杂的界面&#xff0…

深入了解自动化:聊聊什么项目适合做自动化测试?

自动化测试 什么是自动化测 什么是自动化测试&#xff1f; 随着软件产业的不断发展&#xff0c;市场对软件周期的要求越来越高&#xff0c;于是催生了各种开发模式&#xff0c;如大家熟知的敏捷开发&#xff0c;从而对测试提出了更高的要求。此时&#xff0c;产生了自动化测试…

Linux高并发服务器开发(十)反应堆模型和线程池模型

文章目录 1 epoll反应堆2 线程池流程代码 3 复杂版本线程池代码 1 epoll反应堆 文件描述符 监听事件 回调函数 进行封装 创建socket设置端口复用绑定监听创建epoll树将监听文件描述符lfd上epoll树&#xff0c;对应的事件节点包括&#xff1a;文件描述符&#xff0c;事件epoll…

Taogogo Taocms v3.0.2 远程代码执行漏洞(CVE-2022-25578)

前言 CVE-2022-25578 是一个存在于 Taogogo Taocms v3.0.2 中的代码注入漏洞。此漏洞允许攻击者通过任意编辑 .htaccess 文件来执行代码注入。 漏洞详情 漏洞描述&#xff1a;攻击者可以利用此漏洞上传一个 .htaccess 文件到网站&#xff0c;并在文件中注入恶意代码&#xf…

苹果手机怎么刷机?适合小白的刷机办法!

自己的苹果手机用时间长了&#xff0c;有些人想要为自己的手机重新刷新一下&#xff0c;但又不知道怎么刷机。不要慌现在就来给大家详细介绍一下苹果手机怎么刷机&#xff0c;希望可以帮助到大家。 iPhone常见的刷机方式&#xff0c;分为iTunes官方和第三方软件两种刷机方式。 …

【elementui】记录解决el-tree开启show-checkbox后,勾选一个叶结点后会自动折叠的现象

第一种解决方案&#xff1a;设置default-expand-keys的值为当前选中的key值即可 <el-treeref"tree"class"checkboxSelect-wrap":data"treeData"show-checkboxnode-key"id":expand-on-click-node"true":props"defau…

第T3周:天气识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、前期工作 本文将采用CNN实现多云、下雨、晴、日出四种天气状态的识别。较上篇文章&#xff0c;本文为了增加模型的泛化能力&#xff0c;新增了Dropout层并…

拉曼光谱入门:1.光谱的分类与散射光谱发展史

一、光谱是什么&#xff1f; 在一个宁静的午后&#xff0c;年轻的艾萨克牛顿坐在他母亲花园里的一棵苹果树下&#xff0c;手握一块精致的三棱镜。他沉思着光的奥秘&#xff0c;意识到光并非单一的白色&#xff0c;而是一种由多彩色组成的复杂结构。 他决心进行一次实验&#xf…

浅析C++函数重载

浅析C函数重载 C语言和C函数调用的不同 C语言会进行报错 C能成功运行并且自动识别类型 由此可以看出&#xff0c;C在函数调用时进行了调整&#xff0c;使其支持函数重载&#xff0c;那么我们就来看看进行了哪些调整吧&#x1f60e; 分析函数调用 首先我们要知道&#xff0c…

2024企业数据资产化及数据资产入表方案梳理

01 数据资产入表&#xff1a;是一个将组织的各类数据资产进行登记、分类、评估和管理的流程。 数据资产包括&#xff1a;客户信息、交易记录、产品数据、财务数据等。 做个比喻吧&#xff1a;数据资产入表就像是给公司的数据资产做“人口普查”—— ①找出公司有哪些数据找…

macos m2 百度paddleocr文字识别 python

创建了一个虚拟环境&#xff1a;conda create -n orc python3.11.7 进入虚拟环境后执行2条命令 pip install paddleocr -i https://pypi.tuna.tsinghua.edu.cn/simple pip install paddlepaddle -i https://pypi.tuna.tsinghua.edu.cn/simple​ ​ 安装好后&#xff0c;在网…

204.贪心算法:分发饼干(力扣)

以下来源于代码随想录 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {// 对孩子的胃口进行排序sort(g.begin(), g.end());// 对饼干的尺寸进行排序sort(s.begin(), s.end());int index s.size() - 1; // 从最大的饼…

严蔚敏数据结构(C语言版)吴伟民宁编著清华大学计算机系列教材+题集+配套题库+笔记+习题PDF电子版

今天分享的是 严蔚敏数据结构&#xff08;C语言版&#xff09;题集配套题库笔记习题PDF电子版 注&#xff1a;本资源搜集于网络&#xff0c;仅供学习交流&#xff0c;严禁用于商业用途 内容简介&#xff1a; “数据结构”是计算机程序设计的重要理论技术基础&#xff0c;它…

ArcTs布局入门04——相对布局 媒体查询

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧 扫描下面的二维码关注公众号。 本文将探讨相对布局与媒体查询&#xff0c;为啥把他们放到一起呢&#xff1f;主要是因为相对布局在响应式的场景下做得不太好&#xff0c;一般情况下和媒体查询&#xff08;不同尺…

MySQL之备份与恢复(二)

备份与恢复 定义恢复需求 如果一切正常&#xff0c;那么永远也不需要考虑恢复。但是&#xff0c;一旦需要恢复&#xff0c;只有世界上最好的备份系统是没用的&#xff0c;还需要一个强大的恢复系统。 不幸的是&#xff0c;让备份系统平滑工作比构造良好的恢复过程和工具更容易…