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

news2024/11/25 13:53:00

实现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容器
    @Bean
    public 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 {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        System.out.println("startup ...");

        //加载Spring web application configuration => 容器
        //自己实现的Spring容器叫做 ZzwSpringApplicationContext
        AnnotationConfigWebApplicationContext 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启动时,加载 dispatcherServlet
        registration.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.coloradmin.cn/o/1879253.html

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

相关文章

isdigit()方法——判断字符串是否只由数字组成

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 isdigit()方法用于判断字符串是否只由数字组成。isdigit()方法的语法格式如下&#xff1a; str.isdigit() 如果字符串只包含数字则返回T…

路径规划 | 基于蜣螂优化算法的栅格地图机器人路径规划(Matlab)

目录 效果一览基本介绍程序设计参考文献 效果一览 基本介绍 路径规划 | 基于蜣螂优化算法的栅格地图机器人路径规划&#xff08;Matlab&#xff09; 1.利用蜣螂算法DBO优化栅格地图机器人路径规划&#xff0c;效果如图所示&#xff0c;包括迭代曲线图、栅格地图等等&#xff5e…

014、Flask模板在数据可视化中的深度应用

目录 Flask模板在数据可视化中的深度应用 1. Flask模板系统简介 1.1 Jinja2模板语法基础 1.2 Flask中渲染模板 2. 静态图表生成 2.1 使用Matplotlib生成图表 3. 交互式图表&#xff1a;使用Charts.js 3.1 创建柱状图 3.2 创建折线图 4. 高级交互式可视化&#xff1a;…

记某次攻防演练:大战UEditor并突破

前言 最近参与某次攻防演练&#xff0c;通过前期信息收集&#xff0c;发现某靶标单位存在某域名备案。 通过fofa搜索子域名站点&#xff0c;发现存在一个子域名的61000端口开放着一个后台&#xff0c;于是开始进行渗透。 目录扫描 进行目录扫描吗&#xff0c;发现/bin.rar路径…

Vue3实现点击按钮实现文字变色

1.动态样式实现 1.1核心代码解释&#xff1a; class"power-station-perspective-item-text"&#xff1a; 为这个 span 元素添加了一个 CSS 类&#xff0c;以便对其样式进行定义。 click"clickItem(item.id)"&#xff1a; 这是一个 Vue 事件绑定。当用户点…

Springboot与xxl-job

一、下载xxl-job项目 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 从GitHub上面将项目clone下来&#xff0c;如果网络问题导致速度慢也可以从Gitee上面拉…

Apache POI Excel 处理最佳实践

1、需求背景 问题的背景是在需求设计的时候 &#xff0c;我们在业务专家的配合下设计了一些表&#xff0c;但是为了方便的和他们讨论我们把表结构的描述通过Excel文件的方式记录了下来&#xff0c;然后我们需要根据excel文件中的内容生成对应的DDL。今天就给大家分享一下我们的…

python-求出 e 的值

[题目描述] 利用公式 e11/1!1/2!1/3!⋯1/&#x1d45b;!&#xff0c;求 e 的值&#xff0c;要求保留小数点后 10 位。输入&#xff1a; 输入只有一行&#xff0c;该行包含一个整数 n&#xff0c;表示计算 e 时累加到1/n!。输出&#xff1a; 输出只有一行&#xff0c;该行包含计…

解锁数据资产的无限潜能:深入探索创新的数据分析技术,挖掘其在实际应用场景中的广阔价值,助力企业发掘数据背后的深层信息,实现业务的持续增长与创新

目录 一、引言 二、创新数据分析技术的发展 1、大数据分析技术 2、人工智能与机器学习 3、可视化分析技术 三、创新数据分析技术在实际应用场景中的价值 1、市场洞察与竞争分析 2、客户细分与个性化营销 3、业务流程优化与风险管理 4、产品创新与研发 四、案例分析 …

单片机的学习(15)--LCD1602

LCD1602 14.1LCD1602的基础知识1.LCD1602介绍2.引脚及应用电路3.内部结构框图4.时序结构5.LCD1602指令集6.字符值7.LCD1602操作流程 14.2LCD1602功能函数代码1.显示一个字符&#xff08;1&#xff09;工程目录&#xff08;2&#xff09;main.c函数&#xff08;3&#xff09;LCD…

mysql8.0-学习

文章目录 mysql8.0基础知识-学习安装mysql_8.0登录mysql8.0的体系结构与管理体系结构图连接mysqlmysql8.0的 “新姿势” mysql的日常管理用户安全权限练习查看用户的权限回收:revoke角色 mysql的多种连接方式socket显示系统中当前运行的所有线程 tcp/ip客户端工具基于SSL的安全…

error: Sandbox: rsync.samba in Xcode project

在Targets 的 Build Settings 搜索&#xff1a;User script sandboxing 设置为NO

什么是TOGAF?TOGAF应用场景有哪些?TOGAF优缺点

一、什么是TOGAF&#xff1f; TOGAF&#xff0c;全称The Open Group Architecture Framework&#xff0c;即开放组体系结构框架&#xff0c;是由国际开放标准组织The Open Group制定的一套企业架构&#xff08;Enterprise Architecture, EA&#xff09;框架。 The TOGAF Libra…

Mysql基本知识点

1.数据库的基本操作 显示当前的数据库 show databases;创建一个数据库 直接创建数据库 create database 数据库名字;如果系统没有 test2 的数据库&#xff0c;则创建一个名叫 test2 的数据库&#xff0c;如果有则不创建 create database if not exists test2;如果系统没有 db…

在navicat对mysql声明无符号字段

1.无符号设置 在 MySQL 中&#xff0c;我们可以使用 UNSIGNED 属性来设置列的无符号属性&#xff0c;这意味着该列只能存储非负整数值。对于一些需要存储正整数的列&#xff0c;比如年龄、数量等&#xff0c;使用 UNSIGNED 属性可以提高数据存储和查询的效率&#xff0c;并且能…

【启明智显分享】乐鑫ESP32-S3R8方案2.8寸串口屏:高性能低功耗,WIFI/蓝牙无线通信

近年来HMI已经成为大量应用聚焦的主题&#xff0c;在消费类产品通过创新的HMI设计带来增强的连接性和更加身临其境的用户体验之际&#xff0c;工业产品却仍旧在采用物理接口。这些物理接口通常依赖小型显示器或是简单的LED&#xff0c;通过简单的机电开关或按钮来实现HMI交互。…

【云原生】Prometheus 使用详解

目录 一、前言 二、服务监控概述 2.1 什么是微服务监控 2.2 微服务监控指标 2.3 微服务监控工具 三、Prometheus概述 3.1 Prometheus是什么 3.2 Prometheus 特点 3.3 Prometheus 架构图 3.3.1 Prometheus核心组件 3.3.2 Prometheus 工作流程 3.4 Prometheus 应用场景…

代码托管服务:GitHub、GitLab、Gitee

目录 引言GitHub&#xff1a;全球最大的代码托管平台概述功能特点适用场景 GitLab&#xff1a;一体化的开发平台概述功能特点适用场景 Gitee&#xff08;码云&#xff09;&#xff1a;中国本土化的代码托管服务概述功能特点适用场景 功能对比结论 引言 在现代软件开发中&#…

江协科技51单片机学习- p21 LED点阵屏(8*8)

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

15.数据库简介+MySQl使用+SQL语句

文章目录 数据库简述一.数据库简介DB1.定义:2.DBMS数据库管理系统3.数据库分类 二.MySQL的安装1.安装步骤2.MySQL数据库图形管理工具3.mysql程序常用命令4.MySQL字符集及字符序5.Navicat快捷键操作 三.MySQL数据库基本操作 .........................................表管理一.…