实现SpringBoot底层机制

Tomcat底层启动分析+Spring容器初始化+Tomcat关联Spring容器

1.任务1-创建Tomcat,并启动

(1)创建一个Maven项目,修改pom.xml文件:我们需要自己创建Tomcat对象,因此在引入的场景启动器中排除SpringBoot内嵌的Tomcat,并引入tomcat依赖库

<!--导入SpringBoot父工程-规定写法-->
<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.5.3</version>
</parent>
<dependencies>
<!--导入web项目场景启动器:会自动导入和web开发相关的所有依赖[jar包]-->
<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.指定版本为8.5.75
2.如果我们引入了自己指定的tomcat,一定要记住把前面的spring-boot-starter-tomcat排除
3.否则会出现GenericServletNotFound错误-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.75</version>
</dependency>
</dependencies>

(2)创建LiSpringApplication.java

package com.li.lispringboot;

import org.apache.catalina.startup.Tomcat;

/**
* @author 李
* @version 1.0
*/
public class LiSpringApplication {
//创建tomcat对象,并关联spring容器,然后启动tomcat
public static void run() {
try {
//创建tomcat对象
Tomcat tomcat = new Tomcat();
//设置默认端口-9090
tomcat.setPort(9090);
//启动,就会在指定端口监听
tomcat.start();
//等待请求接入
System.out.println("======9090端口等待请求接入======");
tomcat.getServer().await();
} catch (Exception e) {
e.printStackTrace();
}
}
}

(3)LiMainApp

package com.li.lispringboot;

/**
* @author 李
* @version 1.0
*/
public class LiMainApp {
public static void main(String[] args) {
//启动LiSpringBoot项目/程序
LiSpringApplication.run();
}
}

(4)测试启动main方法,后台输出如下:


打开浏览器,访问9090端口,页面一片空白,因为这时候还没有接入其他组件。

2.任务2-创建Spring容器

(1)创建Monster.java,做一个测试bean

package com.li.lispringboot.bean;

/**
* @author 李
* @version 1.0
*/
public class Monster {
}

(2)创建HelloController.java,做一个测试Controller

package com.li.lispringboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; /**
* @author 李
* @version 1.0
*/
@RestController
public class HelloController {
@RequestMapping("/hello")
public String Hello() {
return "Hello,I'm HelloController!";
}
}

(3)创建LiConfig.java,作为Spring的配置文件

package com.li.lispringboot.config;

import com.li.lispringboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; /**
* @author 李
* @version 1.0
* 配置类-作为Spring的配置文件
* 这里有一个问题,容器怎么知道要扫描哪些包?
*/
@Configuration
@ComponentScan("com.li.lispringboot")//指定要配置类扫描哪些包
public class LiConfig {
//注入Bean-Monster对象到Spring容器
@Bean
public Monster monster() {
return new Monster();
}
}

(4)LiWebApplicationInitializer.java

package com.li.lispringboot;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet; import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration; /**
* @author 李
* @version 1.0
* LiWebApplicationInitializer容器初始化类的任务:
* 1.创建spring容器
* 2.加载/关联spring容器的配置-按照注解方式
* 3.完成spring容器配置的bean的创建,依赖注入
* 4.创建前端控制器(DispatcherServlet),让其持有spring容器
* 5.这的onStartup()方法是tomcat来调用,并把ServletContext对象传入
*/
public class LiWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println("onStartup ...");
//加载-Spring Web Application Configuration
AnnotationConfigWebApplicationContext ac =
new AnnotationConfigWebApplicationContext(); //在ac中注册配置类LiConfig
ac.register(LiConfig.class);
ac.refresh();//完成bean的创建和配置 /*
创建注册非常重要的前端控制器-DispatchServlet
让 DispatchServlet持有spring容器-ac
这样就可以进行映射分发
*/
DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
//返回ServletRegistration.Dynamic对象
ServletRegistration.Dynamic registration
= servletContext.addServlet("app", dispatcherServlet);
//设置前端控制器的加载顺序(这里设置为当tomcat启动时,就加载)
registration.setLoadOnStartup(1);
//设置前端控制器拦截所有请求,并进行分发处理
registration.addMapping("/");
}
}

3.任务3-将Tomcat和Spring容器关联,并启动Spring容器

(1)修改LiSpringApplication,将tomcat和Spring容器关联

package com.li.lispringboot;

import org.apache.catalina.startup.Tomcat;

/**
* @author 李
* @version 1.0
*/
public class LiSpringApplication {
//创建tomcat对象,并关联spring容器,然后启动tomcat
public static void run() {
try {
//创建tomcat对象
Tomcat tomcat = new Tomcat();
/*
1.让tomcat能够将请求转发到SpringWeb容器,因此需要关联
2."/liboot" 就是我们的项目的 application context,即原来配置tomcat时的项目名称
3."D:\\IDEA-workspace\\li-springboot" 指定项目的路径
*/
tomcat.addWebapp("/liboot", "D:\\IDEA-workspace\\li-springboot");
//设置默认端口-9090
tomcat.setPort(9090);
//启动,就会在指定端口监听
tomcat.start();
//等待请求接入
System.out.println("======9090端口等待请求接入======");
tomcat.getServer().await();
} catch (Exception e) {
e.printStackTrace();
}
}
}

(2)在LiMainApp.java中重新启动项目,在浏览器中访问测试Controller,访问成功:

3.1注意事项和细节

如果启动时报异常,如下:

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

解决方案是:引入对应版本的 Jasper包即可。

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

day04-实现SpringBoot底层机制的更多相关文章

  1. [转]STL 容器一些底层机制

    1.vector 容器 vector 的数据安排以及操作方式,与 array 非常相似.两者的唯一区别在于空间的运用的灵活性.array 是静态空间,一旦配置了就不能改变,vector 是动态数组.在 ...

  2. C++ STL容器底层机制

    1.vector容器 vector的数据安排以及操作方式,与array非常相似.两者的唯一区别在于空间的运用的灵活性.array是静态空间,一旦配置了就不能改变.vector是动态空间,随着元素的加入 ...

  3. 探索C++的底层机制

    探索C++的底层机制 在看这篇文章之前,请你先要明白一点:那就是c++为我们所提供的各种存取控制仅仅是在编译阶段给我们的限制,也就是说是编译器确保了你在完成任务之前的正确行为,如果你的行为不正确,那么 ...

  4. tensorflow入门教程和底层机制简单解说——本质就是图计算,自动寻找依赖,想想spark机制就明白了

    简介 本章的目的是让你了解和运行 TensorFlow! 在开始之前, 让我们先看一段使用 Python API 撰写的 TensorFlow 示例代码, 让你对将要学习的内容有初步的印象. 这段很短 ...

  5. 20191031:Python底层机制

    20191031:Python底层机制 python底层从3个方面来说,分别是: 引用计数机制 垃圾回收机制 内存池机制 引用计数机制 使用引用计数来追踪内存中的对象,所有对象都有引用计数,并且这个引 ...

  6. php-浅谈php底层机制

    php-浅谈php底层机制 1. PHP的设计理念及特点 多进程模型:由于PHP是多进程模型,不同请求间互不干涉,这样保证了一个请求挂掉不会对全盘服务造成影响,当然,随着时代发展,PHP也早已支持多线 ...

  7. 深入理解SpringBoot核心机制《spring-boot-starter》

    深入理解SpringBoot核心机制<spring-boot-starter> 前言: 对于这几年java火爆天的springBoot我相信大家都有所使用过,在springBoot的项目中 ...

  8. day12-实现Spring底层机制-02

    实现Spring底层机制-02 3.实现任务阶段1 3.1知识拓展-类加载器 Java的类加载器有三种: Bootstrap类加载器 ----- 对应路径 jre/lib Ext类加载器 ----- ...

  9. day13-实现Spring底层机制-03

    实现Spring底层机制-03 7.实现任务阶段5 7.1分析 阶段5目标:bean后置处理器的实现 7.2代码实现 新增: 1.创建 InitializingBean 接口,实现该接口的 Bean ...

  10. day05-SpringMVC底层机制简单实现-01

    SpringMVC底层机制简单实现-01 主要完成:核心分发控制器+Controller和Service注入容器+对象自动装配+控制器方法获取参数+视图解析+返回JSON格式数据 1.搭建开发环境 创 ...

随机推荐

  1. 谁更适合搭配甜点显卡?i7-13700KF、锐龙7 7800X3D对比:游戏相当 生产力Intel强了50%

    一.前言:如果搭配2000元甜点显卡 i7-13700KF和锐龙7 7800X3D谁更有性价比? 现在AMD最受欢迎的处理器无疑是拥有96MB三级缓存的锐龙7 7800X3D,这是一颗专为游戏而生的处 ...

  2. 内存池是什么原理?|内存池简易模拟实现|为学习高并发内存池tcmalloc做准备

    前言 那么这里博主先安利一些干货满满的专栏了! 这两个都是博主在学习Linux操作系统过程中的记录,希望对大家的学习有帮助! 操作系统Operating Syshttps://blog.csdn.ne ...

  3. 离线解锁 CodeCombat 全关卡教程 使用docker安装实现

    前期准备 下载安装docker desktop https://www.123pan.com/s/fmvUVv-HqApH, 这个安装不会的随便搜一个教程,挺多的.我随便找了一个知乎的 Windows ...

  4. JS 这一次彻底理解冒泡排序

    壹 ❀ 引 在面试环节中,算法总是逃不掉的一关,对于我这种非班科出生且大学不接触数学的人来说,逻辑思维方面确实较为欠缺,昨晚跟百度的同学聊到凌晨,自我感觉差距较大,受了不小打击,所以决心抓一抓算法,做 ...

  5. NC26253 小石的妹子

    题目链接 题目 题目描述 小石有 n 个妹子,每个妹子都有一个细心程度 \(a_i\)和一个热心程度 \(b_i\) , 小石想给她们一个重要程度 \(t_i\)​(重要程度为 1 表示最重要,重要程 ...

  6. NC24416 [USACO 2013 Nov G]No Change

    题目链接 题目 题目描述 Farmer John is at the market to purchase supplies for his farm. He has in his pocket K ...

  7. python常用的搜索字符内容函数详解:re.findall/findfiter

    区别findall返回listfinditer返回一个MatchObject类型的iterator详细举例介绍1.findall在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹 ...

  8. 【Unity3D】VideoPlayer组件

    1 简介 ​ AudioSource组件中介绍了音频的播放,本文将介绍基于 VideoPlayer 组件实现视频播放. ​ VideoPlayer 属性面板如下: Source:视频源类型,有 2 种 ...

  9. Swoole从入门到入土(25)——多进程[进程间无锁计数器]

    Atomic 是 Swoole 底层提供的原子计数操作类,可以方便整数的无锁原子增减.原子计数器有如下特点: - 使用共享内存,可以在不同的进程之间操作计数 - 基于 gcc/clang 提供的 CP ...

  10. Swoole从入门到入土(1)——入坑

    入坑一个话题,总得有入坑的理由.有好多话题可供选择,但是思来想去,对于PHPer进阶与其急着去掌握一门新的语言,匆忙地踏足一个新的知识体系,还不如先把php圈子的技能点攒齐了. 话说Swoole诞生之 ...