写点什么

SpringBoot 到底是什么

  • 2022 年 7 月 20 日
  • 本文字数:3934 字

    阅读完需:约 13 分钟

SpringBoot到底是什么

本文分享自华为云社区《SpringBoot到底是什么?如何理解parent、starter、引导类以及内嵌Tomcat?》,作者:我是一棵卷心菜 。


Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot 致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

简化开发


从百度百科中可以看出,其目的是用来简化 Spring!那么到底简化在什么地方呢?


让我们想想在学习 SSM 时,做过原始 SpringMVC 程序的小伙伴应该知道,写 SpringMVC 程序,最基础的 spring-web 和 spring-webmvc 这两个坐标是必须的,这些还不包含我们使用的 json 啊等等坐标,现在呢?一个坐标搞定!


以前写配置类或者配置文件,然后用什么东西就要自己写加载 bean 这些东西,现在呢?什么都没写,照样能用。


有以下优点:


  • 简化依赖配置

  • 简化常用工程相关配置

  • 内置服务器,比如 Tomcat


别着急,让我们慢慢来探讨探讨其中的奥秘~

parent 介绍


打开创建好的 springboot 程序,可以看见 pom.xml 文件中的<parent> </parent>


<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/>
</parent>
复制代码


这里的<version>2.6.4<version>就是自己使用的 springboot 版本,打开后可以发现其中又继承了一个坐标,引入了很多依赖



<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.6.4</version>
</parent>
复制代码


再次点击打开,就可以找到其中的奥秘了。



从下图我们可以发现各式各样的依赖版本号属性,下面列出依赖版本属性的局部,可以看的出来,定义了若干个技术的依赖版本号



再看看下图,各式各样的的依赖坐标信息,可以看出依赖坐标定义中没有具体的依赖版本号,而是引用了第一组信息中定义的依赖版本属性值



注意:上面的依赖坐标定义是出现在<dependencyManagement>标签中的,其实是对引用坐标的依赖管理,并不是实际使用的坐标。因此当我们的项目中继承了这组 parent 信息后,在不使用对应坐标的情况下,前面的这组定义是不会具体导入某个依赖的。


最后来看看使用不同的 springboot 版本时,其对应的 pom 依赖文件有什么不同。我这里对比的是 springboot2.5.6 版本和 springboot2.6.4



从图中可以清楚的看到,当我们使用不同的 springboot 版本时,他们的依赖版本就会不同。这也确保了,在使用 springboot 时,我们可以在某种程度上避免版本冲突的复杂问题,方便了程序员们的开发!

starter 介绍


SpringBoot 关注到开发者在实际开发时,对于依赖坐标的使用往往都有一些固定的组合方式,比如使用 spring-webmvc 就一定要使用 spring-web。每次都要固定搭配着写,非常繁琐,而且格式固定,没有任何技术含量。


​SpringBoot 一看这种情况,把所有的技术使用的固定搭配格式都给开发出来,以后我们使用某个技术,就不用一次写一堆依赖了,直接用 springboot 做好的这个东西就好了,对于这样的固定技术搭配,SpringBoot 给它起了个名字叫做 starter


​starter 定义了使用某种技术时对于依赖的固定搭配格式,也是一种最佳解决方案,使用 starter 可以帮助开发者减少依赖配置


<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
复制代码


比如我想开发 web 应用,就需要引入上面的 web 对应的 starter 依赖,并没有写 SpringMVC 的坐标,点击 spring-boot-starter-web



我们会发现在 spring-boot-starter-web 中又定义了若干个具体依赖的坐标



通过上图我们可以细心的发现叫做 spring-boot-starter-json 的名字中也有 starter,打开看看里面有什么?



我们可以发现,这个 starter 中又包含了若干个坐标,其实就是使用 SpringMVC 开发通常都会使用到 Json,使用 json 又离不开这里面定义的这些坐标,看来还真是方便,SpringBoot 把我们开发中使用的东西能用到的都给提前做好了。仔细看完会发现,里面有一些我们没用过的。的确会出现这种过量导入的可能性,不过没关系,可以通过 maven 中的排除依赖剔除掉一部分。不过你不管它也没事,大不了就是过量导入呗。

​到这里基本上得到了一个信息,使用 starter 可以帮开发者快速配置依赖关系

starter 与 parent 的区别


朦朦胧胧中感觉 starter 与 parent 好像都是帮助我们简化配置的,但是功能又不一样:


starter 是一个坐标中定了若干个坐标,以前写多个的,现在写一个,是用来减少依赖配置的书写量的


parent 是定义了几百个依赖版本号,以前写依赖需要自己手工控制版本,现在由 SpringBoot 统一管理,这样就不存在版本冲突了,是用来减少依赖冲突的


温馨提示


​ SpringBoot 官方给出了好多个 starter 的定义,方便我们使用,而且名称都是如下格式


命名规则:spring-boot-starter-技术名称

引导类介绍


配置说完了,我们发现 SpringBoot 确实帮助我们减少了很多配置工作,下面说一下程序是如何运行的。目前程序运行的入口就是 SpringBoot 工程创建时自带的那个类了,带有 main 方法的那个类,运行这个类就可以启动 SpringBoot 工程的运行,我的是这个:


@SpringBootApplication
public class Springboot0101Application {
public static void main(String[] args) {
SpringApplication.run(Springboot0101Application.class, args);
}
复制代码


写代码测试一下,先创建一个 User 类,把它放在容器中


@Component
public class User {
}
复制代码


然后再写一个 BookController 类,也把它放在容器中


@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping("/getBooks")
public String getBooks() {
System.out.println("springboot程序正在运行呢~");
return "Hello,SpringBoot is running";
}
}
复制代码


看看我对应类的目录结构:



最后写代码测试一下:


@SpringBootApplication
public class Springboot0101Application {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext
= SpringApplication.run(Springboot0101Application.class, args);
BookController bookBean = applicationContext.getBean(BookController.class);
System.out.println("The message of bookBean : " + bookBean);
User userBean = applicationContext.getBean(User.class);
System.out.println("The message of userBean : " + userBean);
}
}
复制代码


运行结果:



看到结果,小伙伴们不难猜想了——SpringBoot 程序启动是创建了一个 Spring 容器对象吧?答案就是如此!


Springboot0101Application 这个类在 SpringBoot 程序中是所有功能的入口,称这个类为引导类


​作为一个引导类最典型的特征就是当前类上方声明了一个注解 @SpringBootApplication

点击进入 @SpringBootApplication,我们可以看到:



这里面有我们之前学习 SSM 时用到的包扫描注解,再点击进入 @SpringBootConfiguration 内:



我们可以发现,它最终使用了 @Configuration 注解,所以,归根到底,我们使用的引用类,也是一个配置类。

内嵌 Tomcat

1、Tomcat 定义位置


程序现在已经运行了,通过引导类的 main 方法运行了起来。但是运行 java 程序不应该是执行完就结束了吗?但是我们现在明显是启动了一个 web 服务器啊,不然网页怎么能正常访问呢?这个服务器是在哪里写的呢?


认真想一想,它就在我们引入的 spring-boot-starter-web 场景 starter 中,我们打开它来看一看:



这里面有一个核心的坐标,tomcat-embed-core,叫做 tomcat 内嵌核心。就是这个东西把 tomcat 功能引入到了我们的程序中。


2、Tomcat 运行原理


再来说第二个问题,这个服务器是怎么运行的?


Tomcat 服务器是一款软件,而且是一款使用 java 语言开发的软件,既然是使用 java 语言开发的,运行的时候肯定符合 java 程序运行的原理,java 程序运行靠的是什么?对象呀,一切皆对象,万物皆对象。那 tomcat 运行起来呢?也是对象。


如果是对象,那 Spring 容器是用来管理对象的,这个对象能不能交给 Spring 容器管理呢?答案是可以的!tomcat 服务器运行其实是以对象的形式在 Spring 容器中运行的,怪不得我们没有安装这个 tomcat,而且还能用。闹了白天这东西最后是以一个对象的形式存在,保存在 Spring 容器中悄悄运行的。具体运行的是什么呢?其实就是上前面提到的那个 tomcat 内嵌核心


具体内嵌核心依赖如下:


<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.58</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<artifactId>tomcat-annotations-api</artifactId>
<groupId>org.apache.tomcat</groupId>
</exclusion>
</exclusions>
</dependency>
复制代码

3、更换内嵌 Tomcat


那既然是个对象,如果把这个对象从 Spring 容器中去掉是不是就没有 web 服务器的功能呢?当然可以,通过依赖排除可以去掉这个 web 服务器功能。根据 SpringBoot 的工作机制,用什么技术,加入什么依赖就行了。我选择的是 SpringBoot 提供的内置服务器 jetty


更换代码如下:


<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
复制代码


让我们运行一下看看是什么样的结果:



输出结果是没有问题的,但是服务器就不是默认的 Tomcat 了,而是我选择的 jetty 服务器。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 3
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
SpringBoot到底是什么_开发_华为云开发者联盟_InfoQ写作社区