展望篇-Spring与SpringBoot

从 0 开始深入学习 Spring 专栏目录总览

小册的正篇最后一章,咱来展望一下 SpringFramework 与它的衍生品 SpringBoot 。

可能有的小伙伴了解过 SpringBoot 了,知道使用它开发应用的方便、快速。也不乏在其中会产生一些疑问:SpringBoot 这么厉害,为啥一开始咱不学习 SpringBoot 呢?而是先从这个学起来并不轻松的 SpringFramework 开始呢?对于这种疑问,我觉得有一种说法挺好的:你先学习 SpringFramework ,一来这是 SpringBoot 的基础,没有基础,当使用 SpringBoot 编写应用时,出现问题时你不会那么容易找到解决方案和思路;二来,学习好 SpringFramework 之后,再学习 SpringBoot ,你会发现其实 SpringBoot 还是大量使用 SpringFramework 的东西,并在此基础之上进行扩展和增强,仅此而已,它并没有改变 SpringFramework 的东西。

所以,作为小册正篇的最后,小册也带你快速的了解一下 SpringBoot ,并且指引小伙伴一个宏观的学习思路和方向吧。当然,也仅仅是指引和参考。

1. SpringBoot概述

SpringBoot 可以说是近几年来最最受欢迎的开源框架,恐怕没有之一了。SpringBoot 的出现,被绝大多数开发者称为 “构建基于 SpringFramework 应用中最强大的基础框架”。

1.1 SpringBoot的强大特性

SpringBoot 构建之初的目的,就是为了简化原生 SpringFramework 的工程搭建和开发过程,注意它只是简化,而不是 SpringFramework 的替代品。它提供了一些非常强大又便捷的特性:

  • 约定大于配置:SpringBoot 对日常开发中比较常见的场景都提供了约定的默认配置,并基于自动装配机制,将场景中通常必需的组件都注册好,以此来达到少配置、甚至不配置都能正常启动项目的效果;
  • starter :SpringBoot 对常用的场景都进行了整合,将这些场景中需要的依赖都收集整理到一个依赖中,并在其中添加了默认的配置,使项目开发中只需要导入一个依赖,即可实现场景技术的整合;
  • 自动装配:SpringBoot 基于 SpringFramework 的模块装配 + 条件装配,可以在具体的场景下,自动引入需要的配置类并解析执行,并且它可以根据工程代码中已经配置的内容,动态注册缺少 / 必要的组件,以此实现约定大于配置的效果;
  • 嵌入式 Web 容器:SpringBoot 在运行时可以不依赖外部的 Web 容器,而是使用内部嵌入式的 Web 容器来支撑应用的运行。也正是如此,基于 SpringBoot 的应用可以直接以一个单体应用的 jar 包运行;
  • 生产级别的特性:SpringBoot 提供了一些很有用的生产运维型的功能特性,比如健康检查、监控指标、外部化配置等。

由此我们可以了解到,SpringBoot 真的好强大,那它的出现一定是为了解决什么问题吧。

1.2 SpringBoot解决的问题

SpringBoot 之所以会流行的如此之火,其背后一定是给我们开发者带来了足够的方便或者利好。总体来看,使用 SpringBoot 开发应用后,我们至少可以体会到如下好处:

  • 配置的内容大幅减少
    • 约定大于配置的特性,使得我们不再需要每次搭建工程时都写那么多程式化的配置,这些东西都让 SpringBoot 的自动配置去做了。
  • 工程的依赖管理和依赖版本控制
    • SpringBoot 的 starter 已经帮我们管理好了依赖的包和对应的版本,可以保障我们在开发时直接引入 starter 即可,不需要再在依赖上纠结。

除此之外,开箱即用、嵌入式 Web 容器等,这些也都是 SpringBoot 解决的一些巨大问题。

1.3 SpringBoot与Spring的关系

咱前面刚说了,SpringBoot 只是简化了基于 SpringFramework 的应用的开发,并不是 SpringFramework 的替代品,所以本质上讲,基于 SpringBoot 的应用仍然是一个 Spring 的应用,SpringBoot 做的只是帮我们整合不同场景下的依赖、提供默认的配置等等。

另外,SpringBoot 对于 SpringWebMvc 来讲也只是一个整合而已,webmvc 对于 SpringBoot 而言只是一个模块而已,通过引入 webmvc 的依赖,可以使工程中支持 SpringWebMvc 的开发,同时也会引入对应的嵌入式 Web 容器来支撑项目的运行。

2. SpringBoot快速体验

接下来,咱利用一个简单的例子,来快速体验一下,基于 SpringBoot 的应用在开发起来有多么的快速便捷。

本章源码均在 spring-06-boot 项目下。

2.1 工程搭建

首先,对于 SpringBoot 工程的搭建,可以选用好几种方法,但最后都是殊途同归。小册介绍比较常用的几种方式。

2.1.1 借助SpringInitializer

在 SpringBoot 的官方文档中,最底下有一个 Spring 项目的初始化向导 start.spring.io/ ,使用它可以快速初始化一个基于 SpringBoot 的项目。

截止小册编写该章的时候,SpringBoot 2.4.0 已经发布了,所以打开初始化向导的时候看到的应该是这样:

展望篇-Spring与SpringBoot

左边的选项可以选择创建工程时用的构建工具、语言、编译等级,以及项目的工程名等信息,右边可以直接选择要导入的场景依赖。由于我们只是在这里用一个简单示例,所以这里我们只导入两个依赖:webmvc 和 dao 吧:

展望篇-Spring与SpringBoot

这样写完之后,直接点击下面的 generate ,即可获得一个打好包的 SpringBoot 工程。解压之后,利用 IDEA 或者 eclipse 即可打开工程。

2.1.2 借助IDE

其实 IDEA 和 eclipse 都可以借助 SpringInitializer 来创建基于 SpringBoot 的应用(eclipse 需要安装额外的 Spring Tools 插件),下面小册以 IDEA 为例,介绍初始化 SpringBoot 项目的方法。

在 IDEA 中,直接选择菜单 File → new → Project ,就可以弹出下面的对话框,选择 SpringInitializer 之后,就可以呈现出下面的内容:

展望篇-Spring与SpringBoot

然后直接下一步,新的界面会让你配置工程的一些细节,包括开发语言、打包方式、编译版本等。

展望篇-Spring与SpringBoot

我们直接在这里选择好,之后继续下一步:

展望篇-Spring与SpringBoot

接下来的这一步就很舒服了,我们需要导入哪些场景的依赖,可以直接在左边的目录中查找,并勾选需要的依赖。比方说我们可以勾选 Spring Web 模块,来导入 SpringWebMvc 的那一套依赖:

展望篇-Spring与SpringBoot

完成之后,继续点 next ,接下来就是选择工程的创建路径了,这里我们随便选择一个路径,确定即可。

创建完成之后,会在 IDEA 中加载初始化好的工程。

2.1.3 Maven工程搭建

如果是使用 Maven 的话,那就再简单不过了,因为再怎么折腾,最终的 pom.xml 里内容都是那些。下面我们也来用 Maven 搭建一下。

groupid 和 artifactid 咱都随便写得了,主要是写 pom.xml 。

首先,在上面添加父依赖:(小册这里使用的是 2.2.9 ,它依赖的 SpringFramework 版本是 5.2.8 )

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.9.RELEASE</version>
    </parent>

然后,添加坐标依赖,这里我们只添加一个 web 场景的依赖吧:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

最后,添加一个 SpringBoot 与 Maven 的整合插件:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

好了,这样就算创建完了。

2.2 快速使用SpringBoot

接下来,我们用上面刚刚用 Maven 创建的工程,来写一个简单的 Demo ,快速体会一下 SpringBoot 的强大之处。

我们来创建一个 com.linkedbear.spring.boot.BootQuickstartApplication 的类,并在这里面编写如下代码:

@SpringBootApplication
public class BootQuickstartApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(BootQuickstartApplication.class, args);
    }
}

可以发现这里面两部分:类上标注了一个 @SpringBootApplication 注解,main 方法中我们把当前类传入了 SpringApplication 的 run 方法中。

这样写完之后,什么别的事情也不用干,直接运行 main 方法,我们会惊奇的发现,项目正常启动,并且还启动了一个 Tomcat ,暴露在 8080 端口上!

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.8.RELEASE)

2020-01-01 12:00:00 000  INFO 18180 --- [           main] c.l.s.boot.BootQuickstartApplication     : Starting BootQuickstartApplication on LinkedBear with PID 18180
2020-01-01 12:00:00 000  INFO 18180 --- [           main] c.l.s.boot.BootQuickstartApplication     : No active profile set, falling back to default profiles: default
2020-01-01 12:00:00 000  INFO 18180 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-01-01 12:00:00 000  INFO 18180 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-01-01 12:00:00 000  INFO 18180 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.36]
2020-01-01 12:00:00 000  INFO 18180 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-01-01 12:00:00 000  INFO 18180 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 678 ms
2020-01-01 12:00:00 000  INFO 18180 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-01-01 12:00:00 000  INFO 18180 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-01-01 12:00:00 000  INFO 18180 --- [           main] c.l.s.boot.BootQuickstartApplication     : Started BootQuickstartApplication in 1.156 seconds (JVM running for 1.636)

有木有那种很强的感觉,果然 SpringBoot 是约定大于配置,因为我们在实际搭建环境的时候,很多内容都是固定的,SpringBoot 直接帮我们做好了,所以我们也就不需要再折腾了。

2.2.1 约定大于配置的体现

如果我们需要修改 SpringBoot 默认的配置,则我们可以在工程的 src/resources 目录下新建一个 application.properties 或者 application.yml 的配置文件,并在其中声明配置即可。

比方说,我们需要 Tomcat 暴露在 8989 端口上,则只需要在 application.properties 中声明如下一行配置:

server.port=8989

重新运行 BootQuickstartApplication 的 main 方法,可以发现控制台中真的打印了 Tomcat 运行在 8989 端口上了:

Tomcat started on port(s): 8989 (http) with context path ''

这就是约定大于配置:你配置了,那就用你的;你不配置,那就用我约定好的。

2.2.2 编写Controller

下面我们来编写一个简单的 Controller ,并使用 json 数据的响应形式,快速体验一下 Controller 层的开发:

@RestController
public class DemoController {
    
    @GetMapping("/test")
    public String test() {
        return "test";
    }
}

编写完成之后,重新运行 main 方法重启工程,并访问 http://localhost:8989/test ,可以发现 test 已经成功响应在浏览器上了:

展望篇-Spring与SpringBoot

然而这期间我们根本没有配置任何东西,一切的一切都已经自动帮我们做好了。

2.3 快速整合jdbc

接下来我们快速的体会一下 SpringBoot 整合 jdbc 。

整合 jdbc ,只需要在 pom 中添加两个依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>

之后在 application.properties 中配置一下数据源:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring-webmvc?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456

这样就可以用了。接下来我们回到 DemoController 中,直接注入一个 JdbcTemplate 并使用:

    @Autowired
    JdbcTemplate jdbcTemplate;
    
    @GetMapping("/findAll")
    public List<Map<String, Object>> findAll() {
        return jdbcTemplate.query("select * from tbl_dept", new ColumnMapRowMapper());
    }

不要怀疑 jdbcTemplate 会不会不存在,SpringBoot 能考虑不到这一点吗?人家肯定都帮我们都配置好了呀。

重启项目,浏览器访问 http://localhost:8989/findAll ,可以发现浏览器可以成功返回数据了:

[{"id":"6ded6d3bdc8f4fc70bcc4347822a5ca3","name":"haha","tel":"12321"},{"id":"84fef077c8dd97be89b2dff7de601073","name":"gege","tel":"32123"}]

这样 SpringBoot 就已经跟 jdbc 整合成功了。

可能部分小伙伴没有用 5.1 版本的 MySQL 驱动包,在运行的时候会报一个异常:

The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone.

这种情况只需要把 application.properties 中的 spring.datasource.url 改一下就可以了:

spring.datasource.url=jdbc:mysql://localhost:3306/spring-webmvc?characterEncoding=utf8&serverTimezone=Asia/Shanghai

好啦,有关 SpringBoot 的展望,小册就带各位到这里。至于更多的 SpringBoot 的使用和奥秘,就交给小伙伴们自行探索啦。

免责声明:
1.本站所有内容由本站原创、网络转载、消息撰写、网友投稿等几部分组成。
2.本站原创文字内容若未经特别声明,则遵循协议CC3.0共享协议,转载请务必注明原文链接。
3.本站部分来源于网络转载的文章信息是出于传递更多信息之目的,不意味着赞同其观点。
4.本站所有源码与软件均为原作者提供,仅供学习和研究使用。
5.如您对本网站的相关版权有任何异议,或者认为侵犯了您的合法权益,请及时通知我们处理。
火焰兔 » 展望篇-Spring与SpringBoot