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();}
}
完成测试
运行效果
浏览器请求, http://localhost:9090/ , 这时没有返回信息
实现任务阶段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 容器
● 代码实现
- 修改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();}}
}
- debug 一下, 看看是否进行Spring 容器的初始化工作, 可以看到ac.refresh() 会将NlcConfig.class 中配置Bean 实例化装入到容器中…
里面有很多,可以自己看看
完成测试
1、启动项目, 运行NlcMainApp
public class NlcMainApp {public static void main(String[] args) {//启动NlcSpringBoot项目/程序NlcSpringApplication.run();}
}
2、运行的效果
注意事项和细节
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>
😄总结
- 如果启动包异常出现上述异常, 引入对应版本的jasper 包就可以解决。
- 前面配置的application context可以根据自己的需求修改。
- 指定项目的目录要根据自己的项目情况进行修改,否则会出现FileNotFoundException(系统找不到指定的文件)或NoSuchFileException(没有此类文件)。
😁热门专栏推荐
SpringBoot篇
SpringBoot 底层机制分析[上]
SpringBoot容器–注解的使用
SpringBoot 自动配置–常用配置
SpringBoot 依赖管理和自动配置—带你了解什么是版本仲裁
Spring Boot介绍–快速入门–约定优于配置
文章到这里就结束了,如果有什么疑问的地方请指出,诸大佬们一起来评论区一起讨论😁
希望能和诸大佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞
相关文章:
![](https://img-blog.csdnimg.cn/img_convert/1b3b4f60f46c8c5b9a8f07f629a64258.png)
SpringBoot 底层机制分析【Tomcat 启动+Spring 容器初始化+Tomcat 如何关联Spring 容器】【下】
😀前言 本篇博文是关于SpringBoot 底层机制分析实现,希望能够帮助你更好的了解SpringBoot 😊 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以帮助到大…...
![](https://www.ngui.cc/images/no-images.jpg)
NLP(六十五)LangChain中的重连(retry)机制
关于LangChain入门,读者可参考文章NLP(五十六)LangChain入门 。 本文将会介绍LangChain中的重连机制,并尝试给出定制化重连方案。 本文以LangChain中的对话功能(ChatOpenAI)为例。 LangChain中的重…...
![](https://img-blog.csdnimg.cn/fea83837f9654547a5faa44274291f52.png)
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…...
![](https://www.ngui.cc/images/no-images.jpg)
async/await函数需要trycatch吗?
前言 写异步函数的时候,promise 和 async 两种方案都非常常见,甚至同一个项目里,不同的开发人员都使用不同的习惯, 不过关于两者的比较不是本文关注的重点,只总结为一句话:“async 是异步编程的终极解决方案”。 当使…...
![](https://img-blog.csdnimg.cn/131ac920a7a84ae4a06b53249ff63f4f.png)
Jenkins集成appium自动化测试(Windows篇)
一,引入问题 自动化测试脚本绝大部分用于回归测试,这就需要制定执行策略,如每天、代码更新后、项目上线前定时执行,才能达到最好的效果,这时就需要进行Jenkins集成。 不像web UI自动化测试可以使用无痕浏览器做到无界…...
![](https://www.ngui.cc/images/no-images.jpg)
MongoDB:切换log日志文件
可以不重启MongoDB,切换日志文件 use admin db.runCommand({logRotate:1})参考 MongoDB 日志切割三种方式...
![](https://www.ngui.cc/images/no-images.jpg)
代码随想录第三十五天
代码随想录第三十五天 Leetcode 860. 柠檬水找零Leetcode 406. 根据身高重建队列Leetcode 452. 用最少数量的箭引爆气球 Leetcode 860. 柠檬水找零 题目链接: 柠檬水找零 自己的思路:我的垃圾思路!!!!!!复…...
![](https://img-blog.csdnimg.cn/8718fcf474644b6b864d347e69b2be47.png)
块、行内块水平垂直居中
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…...
![](https://www.ngui.cc/images/no-images.jpg)
Mybatis引出的一系列问题-动态 SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底…...
![](https://www.ngui.cc/images/no-images.jpg)
Docker学习之构建Base Image
构建Base Image 目标是构建一个类似官方Hello world的镜像,需要配置好Docker运行环境。 创建目录,编写代码 创建并进入docker目录。 mkdir docker cd dockertouch hello.cvim hello.chello.c文件的内容如下: #include <stdio.h>in…...
![](https://www.ngui.cc/images/no-images.jpg)
SFM(Structure from Motion)和NeRF(Neural Radiance Fields)
SFM(Structure from Motion)和NeRF(Neural Radiance Fields)都是计算机视觉领域中的重要算法,用于不同的任务和应用。 SFM(Structure from Motion): SFM是一种从图像序列中重建三维场…...
![](https://img-blog.csdnimg.cn/6fb8a4e983ea4fc6ae691fc3f3662fc0.png)
[Vue] Vue2和Vue3的生命周期函数
vue2有11个生命周期钩子, vue3有8个生命周期钩子 从vue创建、运行、到销毁总是伴随着各种事件, 创建、挂载、更新到销毁。 1.vue2系列生命周期 ⑴【beforecreate】实例创建前。 vue完全创建之前,会自动执行这个函数。 ⑵【Created】实例创建后。 这也是个生命…...
springboot集成分布式任务调度系统xxl-job(调度器和执行器)
一、部署xxl-job服务端 下载xxl-job源码 下载地址: https://gitee.com/xuxueli0323/xxl-job 二、导入项目、创建xxl_job数据库、修改配置文件为自己的数据库 三、启动项目、访问首页 访问地址: http://localhost:8080/xxl-job-admin/ 账号࿱…...
![](https://img-blog.csdnimg.cn/9f8ace6a2f0b440e96392f8cf1e96b0f.png)
11_Vue3中的新的组件
1. Fragment 在Vue2中:组件必须要有一个跟标签在Vue3中:组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中好处:减少标签层级,减少内存占用 2. Teleport 什么是Teleport?——Teleport 是一种能够将…...
![](https://img-blog.csdnimg.cn/27350bb5985b489198e270c24774a854.jpeg)
详解推送Git分支时发生的 cannot lock ref 错误
在码云上建了一个项目仓库,分支模型使用 git-flow ,并在本地新建了一个功能分支 feature/feature-poll。后来在推送时发生错误,提示 cannot lock ref ...... 这样的错误信息。下面复盘一下具体过程和解决办法,以供参考。 在码云中建立仓库时,考虑到想按照 GitFlow 的模式…...
![](https://www.ngui.cc/images/no-images.jpg)
[国产MCU]-BL602开发实例-PWM
PWM 文章目录 PWM1、BL602的PWM介绍2、PWM驱动API介绍3、PWM使用示例脉冲宽度调制(Pulse width modulation,简称PWM)是一种模拟控制方式,根据相应载荷的变化来调制晶体管基极或MOS管栅极的偏置,来实现晶体管或MOS管导通时间的改变,从而实现开关稳定电源输出的改变。这种方…...
![](https://img-blog.csdnimg.cn/f3fc05e2702843eea3e2d1a384ee94ef.png)
【JMeter】 使用Synchronizing Timer设置请求集合点,实现绝对并发
目录 布局设置说明 Number of Simulated Users to Group Timeout in milliseconds 使用时需要注意的点 集合点作用域 实际运行 资料获取方法 布局设置说明 参数说明: Number of Simulated Users to Group 每次释放的线程数量。如果设置为0,等同…...
![](https://img-blog.csdnimg.cn/29d52d2a67cb48f4971c61aeab87baf8.png#pic_center)
无法对watchdog.sys等系统文件删除,弯道修复,这里解决办法很简单
右击360强力删除...
![](https://img-blog.csdnimg.cn/862d1137bc13469bb3fb3740ffcc0636.png)
ClickHouse(九):Clickhouse表引擎 - Log系列表引擎
进入正文前,感谢宝子们订阅专题、点赞、评论、收藏!关注IT贫道,获取高质量博客内容! 🏡个人主页:含各种IT体系技术,IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…...
![](https://img-blog.csdnimg.cn/e9ba1569e81348fbb458bcdf4efd962e.png)
3.1 计算机网络和网络设备
数据参考:CISP官方 目录 计算机网络基础网络互联设备网络传输介质 一、计算机网络基础 1、ENIAC:世界上第一台计算机的诞生 1946年2月14日,宾夕法尼亚大学诞生了世界上第一台计算机,名为电子数字积分计算机(ENIAC…...
![](https://www.ngui.cc/images/no-images.jpg)
值得中国人民大学与加拿大女王大学金融硕士中的金融人观看的五部电影
积金累玉的机会每个人都会把握,那么学习可以实现,生活娱乐一样可以。当电影遇见金融会产生怎样的化学变化呢?今天我们就带着这样的疑问来一起走进英国时报发布的经典电影,也是最值得中国人民大学与加拿大女王大学金融硕士中的金融…...
![](https://img-blog.csdnimg.cn/eb5cf967c2674e7e8016dd452654e851.png)
【数据库】Redis可以替代Mysql吗
Redis和Mysql的搭配 Redis可以替代Mysql吗什么是RedisRedis适用的场景以及优点Redis的缺点 什么是MysqlMysql的优点Mysql缺点 总结 Redis可以替代Mysql吗 Redis不能代替MySQL, Redis和MySQL只能是一种互补。 什么是Redis Redis是一种非关系型数据库,也…...
![](https://www.ngui.cc/images/no-images.jpg)
5 指针与多维数组:多维数组在内存中的存储与指针的关系
推荐最近在工作学习用的一款好用的智能助手AIRight 网址是www.airight.fun。 指针与多维数组:多维数组在内存中的存储与指针的关系 引言 多维数组是数据结构中常见且重要的概念,它是由多个一维数组组成的数据集合。在计算机内存中,多维数组…...
![](https://www.ngui.cc/images/no-images.jpg)
Spring 创建 Bean 的三种方式
在使用 Spring 框架后,对象以 Bean 的形式统一交给 IOC 容器去创建和管理。现阶段主流的方式是基于 SpringBoot 框架,基于注解的方式实现 Bean 的创建,但在原生 Spring 框架中其实存在三种创建 Bean 的方式。 一、基础类 BeanProcess 实体类…...
![](https://img-blog.csdnimg.cn/e926fac8b03b46349860763813a1ca1e.png)
软工导论知识框架(五)面向对象方法学
传统软件工程方法学适用于中小型软件产品开发; 面向对象软件工程方法学适用于大型软件产品开发。 一.四要素 对象+类+继承+传递消息实现通信 二.概念 1.对象:具有相同状态的一组操作的集合,对状态和操作…...
![](https://www.ngui.cc/images/no-images.jpg)
MyBatisPlus代码生成器
首先需要mybaits-plus依赖和自动代码生成器依赖 <!-- mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version></dependency><!-…...
![](https://img-blog.csdnimg.cn/img_convert/32454d40c415a7a00d181f0ffaec30ba.png)
文件传输软件常见问题解决办法大全
文件传输软件是我们工作中不可缺少的一种工具,它可以帮助我们快速、安全、稳定地传输各种文件,如文档、图片、视频等。但是在使用文件传输软件的过程中,我们也可能会遇到一些问题,影响我们的工作效率和传输质量。那么,…...
![](https://www.ngui.cc/images/no-images.jpg)
springboot工程测试临时数据修改技巧
目录 properties临时属性测试注入 args临时参数测试注入 bean配置类属性注入(Import) SpringBootTest是一个注解,用于测试Spring Boot应用程序。它可用于指示Spring Boot测试应用程序的启动点,并为测试提供一个可用的Spring应用…...
![](https://www.ngui.cc/images/no-images.jpg)
Echarts 清空画布空白以及鼠标悬浮提示信息格式化问题
清空画布用clear()会导致图表空白 const option1 = this.myEchart1.getOption()const option2 = this.myEchart2.getOption()const option3 = this.myEchart3.getOption()// 清空数据option1.series = []option1.xAxis[0].data = []option2.series = []option2.xAxis[0].data …...
![](https://img-blog.csdnimg.cn/4aa738e19b544b39aac376849d04a149.png)
数据结构入门:栈
目录 前言 1. 栈 1.1栈的概念及结构 1.2 栈的实现 1.2.1 栈的定义 1.2.2 栈的初始化 1.2.3 入栈 1.2.4 出栈 1.2.5 栈的元素个数 1.2.6 栈顶数据 1.2.7 栈的判空 2.栈的应用 2.1 题目一:括号匹配 2.1.1 思路 2.1.2 分析 2.1.3 题解 总结 前言 无论你是计算机科学专…...
![](https://img-blog.csdnimg.cn/img_convert/305ddf50b2ded32ddfe6a312ba8ca36d.png)
设计素材网站永久/百度指数关键词工具
两种Controller层接口鉴权方式 最近在做一个即时通讯服务时,要求对每个接口的入参进行鉴权处理,这里我整理出来了两种方式:1.基于注解和拦截器鉴权 2.基于注解和AOP鉴权 这里我在采用的是aop的方式,拦截器这里只完成了伪代码…...
![](https://img-blog.csdnimg.cn/img_convert/0e041a79fd2bae1835491b3e482d4c2b.png)
静态网站开发课程模板/拼多多关键词排名查询
知名苹果分析师郭明錤预测苹果今年的iPhone14没有重大升级,它搭载的A16处理器将继续如A15那样小修小补,并且继续使用N5P工艺,原因在于它认为包括中国手机在内的众多安卓手机对它已完全没有威胁。A16处理器将与A15处理器一样采用台积电的N5P工…...
![](/images/no-images.jpg)
wordpress 未找到/google seo实战教程
液体青贮添加剂市场的企业竞争态势 该报告涉及的主要国际市场参与者有Volac (UK)、Trouw Nutrition (Netherlands)、Schaumann BioEnergy (Germany)、ADDCON (Germany)、Chr. Hansen (Denmark)、BASF (Germany)、Lallemand (US)、DuPont Pioneer (US)、Micron Bio-Systems (US)…...
![](/images/no-images.jpg)
汕头网站公司/今日军事新闻头条
昨天做了什么 设计APP 今天打算做什么 修改错误 遇到的问题 APP中按钮关联错误转载于:https://www.cnblogs.com/liulala2017/p/8185604.html...
![](https://img-blog.csdnimg.cn/img_convert/c7c9b910ec8af27813b0c10a43376422.png)
wordpress 删除 下载文件/营销型网站名词解释
Win7网络图标不见了怎么办?我们在上网的时候,右下角都会有一个网络连接图标,看到这个图标就说明已经连接上网络了,可以上网了。但最近有Win7系统用户反应,他开电脑进入系统桌面时,发现网络连接图标不见了。…...
台州做企业网站/seo怎么收费的
题目链接: Online JudgeOnline Judgehttps://onlinejudge.org/index.php?optioncom_onlinejudge&Itemid8&pageshow_problem&problem780 思路: 自底向上,依次判断各个子天平是否平衡,对于父天平,要判断…...