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

news2025/1/9 15:21:18

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

 

目录

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

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

说明:

分析+代码实现 

修改pom.xml

创建WyxSpringApplication.java

创建WyxMainApp

完成测试

1、运行效果

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

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

代码实现 

创建Monster.java , 做一个测试Bean

创建HiController.java, 作为Controller

创建WyxConfig.java , 作为Spring 的配置文件.

创建WyxWebApplicationInitializer.java , 作为Spring 的Initializer: 初始化器

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

代码实现

创建WyxSpringApplication.java

2. debug 一下

完成测试 

启动项目, 运行WyxMainApp

运行的效果 

​编辑注意事项和细节 

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


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

说明:

创建Tomcat, 并启动

分析+代码实现 

修改pom.xml

    <!-- 导入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-tomcat
        3. 否则会出现包冲突, 提示GenericServlet Not Found 类似错误
        -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.75</version>
        </dependency>
    </dependencies>
</project>

创建WyxSpringApplication.java

public class WyxSpringApplication {
    public static void run() {
        try {
            Tomcat tomcat = new Tomcat();
            tomcat.setPort(9090);
            //启动Tomcat
            tomcat.start();
            //等待请求接入
            System.out.println("=====9090====等待请求");
            tomcat.getServer().await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

创建WyxMainApp

public class WyxMainApp {
    public static void main(String[] args) {
        //启动HspSpringBoot项目/程序
        WyxSpringApplication.run();
    }
}

完成测试

1、运行效果

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

 

 


 

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

代码实现 

创建Monster.java , 做一个测试Bean

public class Monster {
}

创建HiController.java, 作为Controller

@RestController
public class WyxHiController {

    @RequestMapping("/wyxhi")
    public String hi() {
        return "hi,wyx WyxHiController";
    }
}

创建WyxConfig.java , 作为Spring 的配置文件.

/**
 * WyxConfig:配置类-作为Spring的配置文件
 * 这里有一个问题,容器怎么知道要扫描哪些包? =>一会代码会体现
 *
 * 在配置类可以指定要扫描包: @ComponentScan("com.wyxedu.wyxspringboot")
 */
@Configuration
@ComponentScan("com.wyxedu.wyxspringboot")
public class WyxConfig {

    //注入Bean - monster 对象到Spring容器.
    @Bean
    public Monster monster() {
        return new Monster();
    }
}

创建WyxWebApplicationInitializer.java , 作为Spring 的Initializer: 初始化器


/**
 * Initializer: 初始化器
 */

/**
 * 解读
 * 1. 创建我们的Spring 容器
 * 2. 加载/关联Spring容器的配置-按照注解的方式
 * 3. 完成Spring容器配置的bean的创建, 依赖注入
 * 4. 创建前端控制器 DispatcherServlet , 并让其持有Spring容器
 * 5. 当DispatcherServlet 持有容器, 就可以进行分发映射, 请小伙伴回忆我们实现SpringMVC底层机制
 * 6. 这里onStartup 是Tomcat调用, 并把ServletContext 对象传入
 */
public class WyxWebApplicationInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        System.out.println("startup ....");
        //加载Spring web application configuration => 容器
        //自己 写过 WyxSpringApplicationContext
        AnnotationConfigWebApplicationContext ac =
                new AnnotationConfigWebApplicationContext();
        //在ac中注册 WyxConfig.class 配置类
        ac.register(WyxConfig.class);
        ac.refresh();//完成bean的创建和配置

        //1. 创建注册非常重要的前端控制器 DispatcherServlet
        //2. 让DispatcherServlet 持有容器
        //3. 这样就可以进行映射分发, 回忆一下SpringMvc机制[自己实现过]
        //HspDispatcherServlet
        DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
        //返回了ServletRegistration.Dynamic对象
        ServletRegistration.Dynamic registration =
                servletContext.addServlet("app", dispatcherServlet);
        //当tomcat启动时,加载 dispatcherServlet
        registration.setLoadOnStartup(1);
        //拦截请求,并进行分发处理
        //这里在提示 / 和 /* => 在 java web专题的web工程路径博客 不知道的朋友可以去看看
        registration.addMapping("/");

    }
}

 


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

代码实现

创建WyxSpringApplication.java

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

    }
}

2. debug 一下

看看是否进行Spring 容器的初始化工作, 可以看到ac.refresh() 会将WyxConfig.class 中配置Bean 实例化装入到容器中.

 

 

完成测试 

启动项目, 运行WyxMainApp

运行的效果 

注意事项和细节 

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

严重: Servlet [jsp] in web application [/hspboot] threw load() exception
java.lang.ClassNotFoundException: org.apache.jasper.servlet.JspServlet

解决方案, 引入对应版本的jasper 包即可, 修改pom.xml 

<!-- https://mvnrepository.com/artifact/org.apache.tomcat/tomcat-jasper -->
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jasper</artifactId>
    <version>8.5.75</version>
</dependency>

到这里就完成了感谢大家的阅读

因为我之前的博客有手写Tomato Spring SpringMVC MyBits 机制所以这里就手写了Spring-boot这么去启动tomato的代码过程和他的原理。

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

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

相关文章

Android源码之Application与Activity创建时机分析

前言 我们知道App进程是由SystemServer启动的Android启动流程 那App对应的Application以及第一个Activity又是如何创建的呢&#xff1f; 源码分析(API 30为例) 我们从ActivityThread.main函数入手&#xff1b; public static void main(String[] args) {...ActivityThread t…

第八章结构型模式—装饰者模式

文章目录 装饰者模式解决的问题概念结构 案例使用装配者进行改进 使用场景JDK源码分析 静态代理和装饰者的区别 结构型模式描述如何将类或对象按某种布局组成更大的结构&#xff0c;有以下两种&#xff1a; 类结构型模式&#xff1a;采用继承机制来组织接口和类。对象结构型模式…

【Linux】volatile | SIGCHLD | 多线程概念

文章目录 1. volatile编译器优化 2.SIGCHLD信号验证SIGCHLD的存在 3. 多线程多线程概念理解概念什么是多线程调度成本低局部性原理 什么叫做进程 1. volatile 在vscode中&#xff0c;创建signal.c文件 故意在while中没有写代码块&#xff0c;让编译器认为在main中&#xff0c;…

爬虫+可视化 | 动态展示2020东京奥运会奖牌世界分布

文章目录 前言1. 导入模块2. 数据爬取3. 地图展示 3.1 2020东京奥运会奖牌数世界分布3.2 2020东京奥运会金牌世界分布3.3 2020东京奥运会金、银、铜世界分布 前言 2020东京奥运会已落下帷幕&#xff0c;中国军团共获得88枚奖牌&#xff0c;其中38枚金牌、32枚银牌、18枚铜牌…

基于RV1126平台检测模型全流程部署(附工程)

基于RV1126平台检测模型全流程部署 模型训练ONNX导出ONNX模型简化Python部署C部署 本工程地址&#xff1a;https://github.com/liuyuan000/Rv1126_YOLOv5-Lite 模型训练 这次选用的是方便部署的YOLOv5 Lite模型&#xff0c;是一种更轻更快易于部署的YOLOv5&#xff0c;主要摘…

嵌入式通信协议【Modbus】modbus RTU的帧格式

modbus的帧格式 设备地址功能代码数据格式CRC校验LCRC校验H8bit8bitN*8bit8bit8bit 1 主机对从机单个寄存器写数据操作&#xff08;0x06&#xff09; 从机地址功能代码数据格式&#xff08;数据地址&#xff09;数据格式&#xff08;数据&#xff09;CRC校验LCRC校验H010600…

动态规划:万变不离其宗,带你吃透股票系列问题

前言&#xff1a; 对于买卖股票问题而言&#xff0c;最关键的是我们对问题的处理方式&#xff08;对于每一天而言&#xff0c;我们应该描述当天买入卖出还是只描述每天股票的只有或者不持有的状态呢&#xff1f;&#xff09;我们应该描述每天股票是否持有的状态&#xff0c;因…

中科院发布多模态 ChatGPT,图片、语言、视频都可以 Chat ?中文多模态大模型力作

作者 | 小戏、ZenMoore 在 GPT-4 的发布报道上&#xff0c;GPT-4 的多模态能力让人印象深刻&#xff0c;它可以理解图片内容给出图片描述&#xff0c;甚至能在图片内容的基础上理解其中的隐喻或推断下一时刻的发展。无疑&#xff0c;面向所谓的 AGI&#xff08;通用人工智能&am…

数据结构初阶(1)(一些学习数据结构所需掌握的先导知识:包装类、装箱与拆箱、泛型、List简介)

包装类 基本数据类型和包装类是Java中处理数据的两种不同方式。 基本数据类型&#xff08;Primitive Types&#xff09;&#xff1a; Java的基本数据类型是直接存储数据的原始类型&#xff0c;包括以下8种类型&#xff1a; byte&#xff1a;1字节&#xff0c;用于表示整数 …

IEEE编写LaTeX时在作者后添加ORCID标志及链接(简单方案,一行代码)

IEEE的一些论文&#xff0c;如Trans系列惯例是要在作者后添加ORCID标志及链接&#xff0c;但是其How to里面没有相关latex代码案例。 1. 可以用但复杂的方案 CSDN中不少博主也给出了挺漂亮但是比较复杂的方案&#xff0c;如这个的一大串&#xff1a; \documentclass[letters…

Linux文本之awk编译器

一、awk介绍 1&#xff09;awk概述 AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言&#xff0c;尽管 AWK 具有完全属于其本身的语法。它的设计思想来源于 SNOBOL4 、sed 、Marc Rochkind设计的有效性语言、语言工具 yacc 和 lex &#xff0c;当…

尚硅谷大数据技术NiFi教程-笔记02【NiFi(使用案例,同步文件、离线同步mysql数据到hdfs、实时监控kafka数据到hdfs)】

尚硅谷大数据技术-教程学习路线-笔记汇总表【课程资料下载】 视频地址&#xff1a;尚硅谷大数据NiFi教程&#xff08;从部署到开发&#xff09;_哔哩哔哩_bilibili 尚硅谷大数据技术NiFi教程-笔记01【NiFi&#xff08;基本概念、安装、使用&#xff09;】尚硅谷大数据技术NiFi教…

探索古文明,玛雅文明衰落的原因

说起玛雅文明&#xff0c;大家在各种小说或者电影中或多或少的都有听说过&#xff0c;那么这个文明到底是怎么一回事呢&#xff1f;今天老铁就带大家好好的了解下。 玛雅文明存在的时间大致是在公元前2000年至公元1500年之间&#xff0c;这个文明见证了中美洲地区的一段辉煌的…

Cefsharp109.1.110(winfrom)最新支持H264-MP3-MP4功能体验,导出pdf和下载方法有变调整

最新版的支持H264版本(109.1.11,109.1.18)5154分支,也是win7/8/8.1最后一个支持版本 此贴仅分项版本变化和注意事项,本篇文章不提供dll编译文件,有需要单独联系,仅供学习参考 109版本体验测试(音频和视频功能),版本较100.0.230变化提醒及注意变更的内容。 上视频支…

C++每日一练:难题-大数加法

文章目录 前言一、题目二、代码及思路总结 前言 这题好像是指定了C&#xff0c;那就用C来做嘛&#xff0c;确实在C/C中一不小心就超出范围了&#xff0c;说实在的&#xff0c;C这个语言有时候真的很让人无语。很显然这是要用字符串来计算了。这题坑比较多&#xff0c;笔者这也…

数据库使用自增ID好还是UUID好?为什么?

数据库使用自增ID好还是UUID好&#xff1f;为什么&#xff1f; 答&#xff1a; 自增ID 优点&#xff1a; 数字类型&#xff0c;占用空间小数据库自动增量排序&#xff0c;对检索有利&#xff0c;读写速度快&#xff08;聚簇索引的优势&#xff09;系统编码过程中&#xff0…

知识推理学习笔记

OWL本体语言 基于RDF语法&#xff0c;最规范&#xff0c;最严谨&#xff0c;表达能力最强 一 语法 三元组 二 逻辑基础 描述逻辑&#xff1a;基于对象的知识表示的形式化&#xff0c;是一阶谓词逻辑的一个可判定子集 三 描述逻辑系统 一个描述逻辑包含4个基本组成部分 …

【Python数据存储】零基础也能轻松掌握的学习路线与参考资料

Python是一种高级编程语言&#xff0c;被广泛应用于数据科学中。数据存储是数据科学中至关重要的一环&#xff0c;因为人们需要将收集到的数据保存在一些地方。Python中的数据存储有很多种&#xff0c;因此在学习过程中需要明确自己的需求&#xff0c;掌握不同数据存储方式的优…

深入理解 python 虚拟机:多继承与 mro

深入理解 python 虚拟机&#xff1a;多继承与 mro 在本篇文章当中将主要给大家介绍 python 当中的多继承和 mro&#xff0c;通过介绍在多继承当中存在的问题就能够理解在 cpython 当中引入 c3 算法的原因了&#xff0c;从而能够帮助大家更好的了理解 mro 。 python 继承的问题…

【Linux】shell编程之—函数

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、概述二、函数的查看和删除1.查看 declare2.删除 declare 三、函数的返回值1.return 返回值2.echo 返回值 四、函数的参数传入与变量范围五、函数的应用1.阶乘2.…