SpringBoot基础篇(二)

二、SpringBoot 基础配置

入门案例做完了,下面就要研究 SpringBoot 的用法了。通过入门案例,各位小伙伴能够感知到一个信息,SpringBoot 没有具体的功能,它在辅助加快 Spring 程序的开发效率。我们发现现在几乎不用做任何的配置,功能就有了,确实很好用。但是仔细想想,没有做配置意味着什么?意味着配置已经做好了,不用你自己写了。但是新的问题又来了,如果不想用已经写好的默认配置,该如何干预呢?这就是这一章咱们要研究的问题。

如果我们想修改默认的配置,这个信息应该写在什么位置呢?目前我们接触的入门案例中一共有 3 个文件,第一是pom.xml 文件,设置项目依赖的,这个没什么好研究的,相关的高级内容咱们到原理篇再说。第二是引导类,这个是执行 SpringBoot 程序的入口,也不像是做配置的地方。其实还有一个信息,就是在 resources 目录下面有一个空白的文件,叫做 application.properties。一看就是个配置文件,咱们这一章就来说说配置文件怎么写,能写什么,怎么干预 SpringBoot 的默认配置,修改成自己的配置。

教你一招:复制工程

原则:

  • 保留工程基础结构
  • 抹掉原始工程痕迹

步骤:

  1. 在工作空间中复制对应工程,并修改工程名称
  2. 删除与 IDEA 相关配置文件,仅保留 src 目录与 pom.xml 文件
  3. 修改 pom.xml 文件中的 artifactId 与新工程 / 模块名相同
  4. 删除 name 标签(可选)
  5. 保留备份工程供后期使用

1、属性配置

SpringBoot 通过配置文件 application.properties 就可以修改默认的配置,那咱们就先找个简单的配置下手,当前访问 Tomcat 的默认端口是 8080,好熟悉的味道,但是不便于书写,我们先改成 80,通过这个操作来熟悉一下SpringBoot 的配置格式是什么样的

image20

那该如何写呢?SpringBoot 默认配置文件是 application.properties,通过键值对配置对应属性,即properties 格式的文件书写规范是 key=value,如:

name=itheima

这个格式肯定是不能颠覆的,那就尝试性的写就行了,改端口,写 port。当你输入 port 后,神奇的事情就发生了,这玩意儿带提示,太好了

image21

根据提示敲回车,输入 80 端口,搞定

# 修改服务器端口
server.port=80

下面就可以直接运行程序,测试效果了。

我们惊奇的发现 SpringBoot 这玩意儿狠啊,以前修改端口在哪里改?Tomcat 服务器的配置文件中改,现在呢?SpringBoot 专用的配置文件中改,是不是意味着以后所有的配置都可以写在这一个文件中呢?是的,简化开发者配置的书写位置,集中管理。

其实到这里我们应该得到如下三个信息:

  1. SpringBoot 程序可以在 application.properties 文件中进行属性配置
  2. application.properties 文件中只要输入要配置的属性关键字就可以根据提示进行设置
  3. SpringBoot 将配置信息集中在一个文件中写,不管你是服务器的配置,还是数据库的配置,总之都写在一起,逃离一个项目十几种配置文件格式的尴尬局面

做完了端口的配置,趁热打铁,再做几个配置,目前项目启动时会显示一些日志信息,就来改一改这里面的一些设置。

关闭运行日志图表(banner)

spring.main.banner-mode=off

修改 banner

spring.banner.image.location=logo.png

设置运行日志的显示级别

# logging.level.root=debug
# logging.level.root=error
logging.level.root=info
# logging.level.com.itheima=warn

你会发现,现在这么搞配置太爽了,以前你做配置怎么做?不同的技术有自己专用的配置文件,文件不同格式也不统一,现在呢?不用东奔西走的找配置文件写配置了,统一格式了,这就是大秦帝国啊,统一六国。SpringBoot 比大秦狠,因为未来出现的技术还没出现呢,但是现在已经确认了,配置都写这个文件里面。

我们现在配置了 3 个信息,但是又有新的问题了。这个配置是随便写的吗?什么都能配?有没有一个东西显示所有能配置的项呢?此外这个配置和什么东西有关呢?会不会因为我写了什么东西以后才可以写什么配置呢?比如我现在没有写数据库相关的东西,能否配置数据呢?一个一个来,先说第一个问题,都能配置什么。

打开 SpringBoot 的官网,找到 SpringBoot 官方文档,打开查看附录中的 Application Properties 就可以获取到对应的配置项了,网址奉上:https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties

能写什么的问题解决了,再来说第二个问题,这个配置项和什么有关。在 pom 中注释掉导入的 spring-boot-starter-web,然后刷新工程,你会发现配置的提示消失了。闹了半天是设定使用了什么技术才能做什么配置。也合理,不然配置的东西都没有使用对应技术,配了也是白配。

温馨提示

所有的 starter 中都会依赖下面这个 starter,叫做 spring-boot-starter。这个 starter 是所有的 SpringBoot 的 starter 的基础依赖,里面定义了 SpringBoot 相关的基础配置,关于这个 starter 我们到开发应用篇和原理篇中再深入讲解。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
    <version>2.7.12</version>
    <scope>compile</scope>
</dependency>

总结

  1. SpringBoot 中导入对应 starter 后,提供对应配置属性
  2. 书写 SpringBoot 配置采用关键字+提示形式书写

2、配置文件分类

三种配置文件

现在已经能够进行 SpringBoot 相关的配置了,但是 properties 格式的配置写起来总是觉得看着不舒服,所以就期望存在一种书写起来更简便的配置格式提供给开发者使用。有吗?还真有,SpringBoot 除了支持 properties 格式的配置文件,还支持另外两种格式的配置文件。分别如下:

  • properties 格式
  • yml 格式
  • yaml 格式

一看到全新的文件格式,各位小伙伴肯定想,这下又要学习新的语法格式了。怎么说呢?从知识角度来说,要学,从开发角度来说,不用学。为什么呢?因为 SpringBoot 的配置在 IDEA 工具下有提示啊,跟着提示走就行了。下面列举三种不同文件格式配置相同的属性范例,先了解一下

  • application.properties(properties 格式)
server.port=80
  • application.yml(yml 格式)
server:
  port: 81
  • application.yaml(yaml 格式)
server:
  port: 82

仔细看会发现 yml 格式和 yaml 格式除了文件名后缀不一样,格式完全一样。是这样的,yml 和 yaml 文件格式就是一模一样的,只是文件后缀不同,所以可以合并成一种格式来看。那对于这三种格式来说,以后用哪一种比较多呢?记清楚,以后基本上都是用 yml 格式的,本课程后面的所有知识都是基于 yml 格式来制作的,以后在企业开发过程中用这个格式的机会也最多,一定要重点掌握。

总结

  1. SpringBoot 提供了 3 种配置文件的格式
    • properties(传统格式 / 默认格式)
    • yml(主流格式)
    • yaml

思考

现在我们已经知道使用三种格式都可以做配置了,那万一我三个都写了,他们三个谁说了算呢?

配置文件优先级

其实三个文件如果共存的话,谁生效说的就是配置文件加载的优先级别。先说一点,虽然以后这种情况很少出现,但是这个知识还是可以学习一下的。我们就让三个配置文件书写同样的信息,比如都配置端口,然后我们让每个文件配置的端口号都不一样,最后启动程序后看启动端口是多少就知道谁的加载优先级比较高了。

  • application.properties(properties 格式)
server.port=80
  • application.yml(yml 格式)
server:
  port: 81
  • application.yaml(yaml 格式)
server:
  port: 82

启动后发现目前的启动端口为 80,把 80 对应的文件删除掉,然后再启动,现在端口又改成了 81。现在我们就已经知道了 3 个文件的加载优先顺序是什么

application.properties > application.yml > application.yaml

虽然得到了一个知识结论,但是我们实际开发的时候还是要看最终的效果为准。也就是你要的最终效果是什么自己是明确的,上述结论只能帮助你分析结论产生的原因。这个知识了解一下就行了,因为以后同时写多种配置文件格式的情况实在是较少。

最后我们把配置文件内容给修改一下

  • application.properties(properties 格式)
server.port=80
spring.main.banner-mode=off
  • application.yml(yml 格式)
server:
  port: 81
logging:
  level:
    root: debug
  • application.yaml(yaml 格式)
server:
  port: 82

我们发现不仅端口生效了,最终显示 80,同时其他两条配置也生效了,看来每个配置文件中的项都会生效,只不过如果多个配置文件中有相同类型的配置会优先级高的文件覆盖优先级的文件中的配置。如果配置项不同的话,那所有的配置项都会生效。

总结

  1. 配置文件间的加载优先级:properties(最高)> yml > yaml(最低)
  2. 不同配置文件中相同配置按照加载优先级相互覆盖,不同配置文件中不同配置全部保留

教你一招:自动提示功能消失解决方案

可能有些小伙伴会基于各种各样的原因导致配置文件中没有提示,这个确实很让人头疼,所以下面给大家说一下如果自动提示功能消失了怎么解决。

先要明确一个核心,就是自动提示功能不是 SpringBoot 技术给我们提供的,是我们在 IDEA 工具下编程,这个编程工具给我们提供的。明白了这一点后,再来说为什么会出现这种现象。其实这个自动提示功能消失的原因还是蛮多的,如果想解决这个问题,就要知道为什么会消失,大体原因有如下3种:

  1. IDEA 认为你现在写配置的文件不是个配置文件,所以拒绝给你提供提示功能
  2. IDEA 认定你是合理的配置文件,但是 IDEA 加载不到对应的提示信息

这里我们主要解决第一个现象,第二种现象到原理篇再讲解。第一种现象的解决方式如下:

步骤 ①:打开设置,【Files】→【Project Structure…】

image22

步骤 ②:在弹出窗口中左侧选择【Facets】,右侧选中 Spring 路径下对应的模块名称,也就是你自动提示功能消失的那个模块

image23

image24

步骤 ③:点击 Customize Spring Boot 按钮,此时可以看到当前模块对应的配置文件是哪些了。如果没有你想要称为配置文件的文件格式,就有可能无法弹出提示

image25

image26

步骤 ④:选择添加配置文件,然后选中要作为配置文件的具体文件就 OK 了

image27

image28

到这里就做完了,其实就是 IDEA 的一个小功能

image29

总结

  1. 指定 SpringBoot 配置文件
    • Setting → Project Structure → Facets
    • 选中对应项目 / 工程
    • Customize Spring Boot
    • 选择配置文件

3、yaml 文件

SpringBoot 的配置以后主要使用 yml 结尾的这种文件格式,并且在书写时可以通过提示的形式加载正确的格式。但是这种文件还是有严格的书写格式要求的。下面就来说一下具体的语法格式。

YAML(YAML Ain’t Markup Language),一种数据序列化格式。具有容易阅读、容易与脚本语言交互、以数据为核心,重数据轻格式的特点。常见的文件扩展名有两种:

  • .yml 格式(主流)
  • .yaml 格式

对于文件自身在书写时,具有严格的语法格式要求,具体如下:

  1. 大小写敏感
  2. 属性层级关系使用多行描述,每行结尾使用冒号结束
  3. 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
  4. 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
  5. # 表示注释

上述规则不要死记硬背,按照书写习惯慢慢适应,并且在 IDEA 下由于具有提示功能,慢慢适应着写格式就行了。核心的一条规则要记住,数据前面要加空格与冒号隔开

下面列出常见的数据书写格式,熟悉一下

字面值表现方式:

boolean: TRUE # TRUE,true,True,FALSE,false,False均可
float: 3.14   # 6.8523015e+5  #支持科学计数法
int: 123      # 0b1010_0111_0100_1010_1110    #支持二进制、八进制、十六进制
null: ~       # 使用~表示null
string: HelloWorld     # 字符串可以直接书写
string2: "Hello World" # 可以使用双引号包裹特殊字符,字符串中间有空格时必须加引号
date: 2018-02-17       # 日期必须使用yyyy-MM-dd格式
datetime: 2018-02-17T15:02:31+08:00 # 时间和日期之间使用T连接,最后使用+代表时区

此外,yaml 格式中也可以表示数组,在属性名书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔

server:
  port: 81

country: china
province: beijing
city: beijing
area: haidian
party: true
birthday: 1949-10-01

# 对象
user:
  username: itcast
  age: 16

user2:
  username: itcast
  age: 16

# 数组
likes:
  - game
  - music
  - sleep

# 数组书写缩略格式
likes2: [game, music, sleep]

# 对象数组格式一
users: 
  - name: zhangsan
    age: 18
  - name: lisi
    age: 17

# 对象数组格式二
users2: 
  -
    name: zhangsan
    age: 18
  -
    name: lisi
    age: 17

# 对象数组缩略格式
users3: [{name:zhangsan, age:18}, {name:lisi, age:17}]

enterprise:
  name: itcast
  age: 16
  subject2:
    - Java
    - 前端
    - 大数据

总结

  1. yaml 语法规则
    • 大小写敏感
    • 属性层级关系使用多行描述,每行结尾使用冒号结束
    • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用 Tab 键)
    • 属性值前面添加空格(属性名与属性值之间使用冒号 + 空格作为分隔)
    • # 表示注释
  2. 注意属性名冒号后面与数据之间有一个空格
  3. 字面值、对象数据格式、数组数据格式

思考

现在我们已经知道了 yaml 具有严格的数据格式要求,并且已经可以正确的书写 yaml 文件了,那这些文件书写后其实是在定义一些数据。这些数据时给谁用的呢?大部分是 SpringBoot 框架内部使用,但是如果我们想配置一些数据自己使用,能不能用呢?答案是可以的,那如何读取 yaml 文件中的数据呢?咱们下一节再说。

4、yaml 数据读取

对于 yaml 文件中的数据,其实你就可以想象成这就是一个小型的数据库,里面保存有若干数据,每个数据都有一个独立的名字,如果你想读取里面的数据,肯定是支持的,下面就介绍 3 种读取数据的方式

读取单一数据

yaml 中保存的单个数据,可以使用 Spring 中的注解直接读取,使用 @Value 注解可以读取单个数据,属性名引用方式:${一级属性名.二级属性名……}

image30

记得使用 @Value 注解时,要将该注入写在某一个指定的 Spring 管控的 Bean 的属性名上方。现在就可以读取到对应的单一数据行了。

@RestController
@RequestMapping("/books")
public class BookController {
    // 读取yaml数据中的单一数据
    @Value("{country}")
    private String country1;

    @Value("{user.username}")
    private String name1;

    @Value("{likes[1]}")
    private String likes1;

    @Value("{users[1].age}")
    private String age1;

    @Value("${server.port}")
    private String port;

    @GetMapping
    public String getById() {
        System.out.println("springboot is running...");
        System.out.println("country1 ===>" + country1);
        System.out.println("name1 ===>" + name1);
        System.out.println("likes1 ===>" + likes1);
        System.out.println("age1 ===>" + age1);
        System.out.println("port ===>" + port);
        return "springboot is running...";
    }
}

总结

  1. 使用 @Value 配合 SpEL 读取单个数据
  2. 如果数据存在多层级,依次书写层级名称即可

读取全部数据

读取单一数据可以解决读取数据的问题,但是如果定义的数据量过大,这么一个一个书写肯定会累死人的,SpringBoot 提供了一个对象,能够把所有的数据都封装到这一个对象中,这个对象叫做 Environment,使用自动装配注解可以将所有的 yaml 数据封装到这个对象中

image31

数据封装到了 Environment 对象中,获取属性时,通过 Environment 的接口操作进行,具体方法是 getProperties(String),参数填写属性名即可

总结

  1. 使用 Environment 对象封装全部配置信息
  2. 使用 @Autowired 自动装配数据到 Environment 对象中

读取对象数据

单一数据读取书写比较繁琐,全数据封装又封装的太厉害了,每次拿数据还要一个一个地 getProperties(),总之用起来都不是很舒服。由于 Java 是一个面向对象的语言,很多情况下,我们会将一组数据封装成一个对象。SpringBoot 也提供了可以将一组 yaml 对象数据封装成一个 Java 对象的操作

首先定义一个对象,并将该对象纳入 Spring 管控的范围,也就是定义成一个 Bean,即使用 @Component 注解。然后使用注解 @ConfigurationProperties 指定该对象加载哪一组 yaml 中配置的信息。

image32

这个 @ConfigurationProperties 必须告诉他加载的数据前缀是什么,这样当前前缀下的所有属性就封装到这个对象中。记得数据属性名要与对象的变量名一一对应,不然没法封装。其实以后如果你要定义一组数据自己使用,就可以先写一个对象,然后定义好属性,下面到配置中根据这个格式书写即可。

image33

温馨提示

细心的小伙伴会发现一个问题,自定义的这种数据在 yaml 文件中书写时没有弹出提示,是这样的,咱们到原理篇再揭秘如何弹出提示。

总结

  1. 使用 @ConfigurationProperties 注解绑定配置信息到封装类中
  2. 封装类需要定义为 Spring 管理的 Bean,否则无法进行属性注入

yaml 文件中的数据引用

如果你在书写 yaml 数据时,经常出现如下现象,比如很多个文件都具有相同的目录前缀

center:
  dataDir: /usr/local/fire/data
  tmpDir: /usr/local/fire/tmp
  logDir: /usr/local/fire/log
  msgDir: /usr/local/fire/msgDir

或者

center:
  dataDir: D:/usr/local/fire/data
  tmpDir: D:/usr/local/fire/tmp
  logDir: D:/usr/local/fire/log
  msgDir: D:/usr/local/fire/msgDir

这个时候你可以使用引用格式来定义数据,在配置文件中使用属性名引用方式引用属性。其实就是搞了个变量名,然后引用变量了,格式如下:

baseDir: /usr/local/fire

center:
  dataDir: {baseDir}/data
  tmpDir:{baseDir}/tmp
  logDir: {baseDir}/log
  msgDir:{baseDir}/msgDir

还有一个注意事项,在书写字符串时,如果需要使用转义字符,需要将数据字符串使用双引号包裹起来

lesson: "Spring\tboot\nlesson"

总结

  1. 在配置文件中可以使用 ${属性名} 方式引用属性值
  2. 如果属性中出现特殊字符,可以使用双引号包裹起来作为字符解析

到这里有关 yaml 文件的基础使用就先告一段落,在实用篇中再继续研究更深入的内容。

三、基于 SpringBoot 实现 SSMP 整合

重头戏来了,SpringBoot 之所以好用,就是它能方便快捷的整合其他技术,这一部分咱们就来聊聊一些技术的整合方式,通过这一章的学习,大家能够感受到 SpringBoot 到底有多酷炫。这一章咱们学习如下技术的整合方式

  • 整合 JUnit
  • 整合 MyBatis
  • 整合 MyBatis-Plus
  • 整合 Druid

上面这些技术都整合完毕后,我们做一个小案例,也算是学有所用吧。涉及的技术比较多,综合运用一下。

1、整合 JUnit

SpringBoot 技术的定位用于简化开发,再具体点是简化 Spring 程序的开发。所以在整合任意技术的时候,如果你想直观感触到简化的效果,你必须先知道使用非 SpringBoot 技术时对应的整合是如何做的,然后再看基于 SpringBoot 的整合是如何做的,才能比对出来简化在了哪里。

我们先来看一下不使用 SpringBoot 技术时,Spring 整合 JUnit 的制作方式

// 加载spring整合junit专用的类运行器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定对应的配置信息
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTestCase {
    // 注入你要测试的对象
    @Autowired
    private AccountService accountService;

    @Test
    public void testGetById() {
        // 执行要测试的对象对应的方法
        System.out.println(accountService.findById(2));
    }
}

其中核心代码是前两个注解,第一个注解 @RunWith 是设置 Spring 专用于测试的类运行器,简单说就是 Spring 程序执行程序有自己的一套独立的运行程序的方式,不能使用 JUnit 提供的类运行方式了,必须指定一下。但是格式是固定的,琢磨一下,每次都指定一样的东西,这个东西写起来没有技术含量啊。第二个注解 @ContextConfiguration 是用来设置 Spring 核心配置文件或配置类的,简单说就是加载 Spring 的环境你要告诉 Spring 具体的环境配置是在哪里写的,虽然每次加载的文件都有可能不同,但是仔细想想,如果文件名是固定的,这个貌似也是一个固定格式。既然有可能是固定格式,那就有可能每次都写一样的东西,也是一个没有技术含量的内容书写

SpringBoot 就抓住上述两条没有技术含量的内容书写进行开发简化,能走默认值的走默认值,能不写的就不写,具体格式如下

@SpringBootTest
class Springboot04JunitApplicationTests {
    // 注入你要测试的对象
    @Autowired
    private BookDao bookDao;

    @Test
    void contextLoads() {
        // 执行要测试的对象对应的方法
        bookDao.save();
        System.out.println("two...");
    }
}

看看这次简化成什么样了,一个注解就搞定了,而且还没有参数,再体会 SpringBoot 整合其他技术的优势在哪里,就两个字——简化。使用一个测试类注解 @SpringBootTest 替换了前面两个注解。至于内部是怎么回事?和之前一样,只不过都走默认值。

@SpringBootTest 注解的位置:测试类定义上方,作用:设置 JUnit 加载的 SpringBoot 启动类。

这个时候有人就问了,你加载的配置类或者配置文件是哪一个?就是我们前面启动程序使用的引导类。如果想手工指定引导类有两种方式:

第一种方式使用属性的形式进行,在注解 @SpringBootTest 中添加 classes 属性指定配置类

如果测试类在 SpringBoot 启动类的包或子包中,可以省略启动类的设置,也就是省略 classes 的设定

@SpringBootTest(classes = Springboot04JunitApplication.class)
class Springboot04JunitApplicationTests {
    // 注入你要测试的对象
    @Autowired
    private BookDao bookDao;

    @Test
    void contextLoads() {
        // 执行要测试的对象对应的方法
        bookDao.save();
        System.out.println("two...");
    }
}

第二种方式回归原始配置方式,仍然使用 @ContextConfiguration 注解进行,效果是一样的

@SpringBootTest
@ContextConfiguration(classes = Springboot04JunitApplication.class)
class Springboot04JunitApplicationTests {
    // 注入你要测试的对象
    @Autowired
    private BookDao bookDao;

    @Test
    void contextLoads() {
        // 执行要测试的对象对应的方法
        bookDao.save();
        System.out.println("two...");
    }
}

温馨提示

使用 SpringBoot 整合 JUnit 需要保障导入 test 对应的 starter,由于初始化项目时此项是默认导入的,所以此处没有提及,其实和之前学习的内容一样,用什么技术导入对应的 starter 即可。

总结

  1. 导入测试对应的 starter
  2. 测试类使用 @SpringBootTest 修饰
  3. 使用自动装配的形式添加要测试的对象
  4. 测试类如果存在于引导类所在包或子包中无需指定引导类
  5. 测试类如果不存在于引导类所在的包或子包中需要通过 classes 属性指定引导类

2、整合 MyBatis

整合完 JUnit 下面再来说一下整合 MyBatis,这个技术是大部分公司都要使用的技术,务必掌握。如果对 Spring 整合 MyBatis 不熟悉的小伙伴好好复习一下,下面列举出原始整合的全部内容,以配置类的形式为例进行

  • 导入坐标,MyBatis 坐标不能少,Spring 整合 MyBatis 还有自己专用的坐标,此外 Spring 进行数据库操作的 jdbc 坐标是必须的,剩下还有 mysql 驱动坐标,本例中使用了 Druid 数据源,这个倒是可以不要
<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.6</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>

    <!--1.导入mybatis与spring整合的jar包-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.0</version>
    </dependency>

    <!--导入spring操作数据库必选的包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>
</dependencies>
  • Spring 核心配置
@Configuration
@ComponentScan("com.itheima")
@PropertySource("jdbc.properties")
public class SpringConfig {
}
  • MyBatis 要交给 Spring 接管的 Bean
// 定义MyBatis专用的配置类
@Configuration
public class MyBatisConfig {
    // 定义创建SqlSessionFactory对应的Bean
    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
        // SqlSessionFactoryBean是由mybatis-spring包提供的,专用于整合用的对象
        SqlSessionFactoryBean sfb = new SqlSessionFactoryBean();
        // 设置数据源替代原始配置中的environments的配置
        sfb.setDataSource(dataSource);
        // 设置类型别名替代原始配置中的typeAliases的配置
        sfb.setTypeAliasesPackage("com.itheima.domain");
        return sfb;
    }

    // 定义加载所有的映射配置
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }
}
  • 数据源对应的 Bean,此处使用 Druid 数据源
@Configuration
public class JdbcConfig {
    @Value("{jdbc.driver}")
    private String driver;

    @Value("{jdbc.url}")
    private String url;

    @Value("{jdbc.username}")
    private String userName;

    @Value("{jdbc.password}")
    private String password;

    @Bean("dataSource")
    public DataSource dataSource() {
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}
  • 数据库连接信息(properties 格式)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root

上述格式基本上是简格式了,要写的东西还真不少。下面看看 SpringBoot 整合 MyBaits 格式

步骤 ①:创建新模块,选择 Spring 初始化,并配置模块相关基础信息。

image34

步骤 ②:勾选要使用的技术 MyBatis,由于要操作数据库,还要勾选对应数据库

image35

或者手工导入对应技术的 starter,和对应数据库的坐标

<dependencies>
    <!--1.导入对应的starter-->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

步骤 ③:配置数据源相关信息,没有这个信息你连接哪个数据库都不知道

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db
    username: root
    password: root

完了,就这么多,没了。有人就很纳闷,这就结束了?对,这就结束了,SpringBoot 把配置中所有可能出现的通用配置都简化了。下面就可以写一下 MyBatis 程序运行需要的 Dao(或者 Mapper )就可以运行了

实体类

public class Book {
    private Integer id;
    private String type;
    private String name;
    private String description;

    // getter、setter、toString方法省略
}

映射接口(Dao):定义数据层接口与映射配置

@Mapper
public interface BookDao {
    @Select("select * from tbl_book where id = #{id}")
    Book getById(Integer id);
}

测试类:测试类中注入 Dao 接口,测试功能

@SpringBootTest
class Springboot05MybatisApplicationTests {
    @Autowired
    private BookDao bookDao;

    @Test
    void contextLoads() {
        System.out.println(bookDao.getById(1));
    }
}

完美,开发从此变的就这么简单。再体会一下 SpringBoot 如何进行第三方技术整合的,是不是很优秀?具体内部的原理到原理篇再展开讲解

注意:当前使用的 SpringBoot 版本是 2.5.4,对应的坐标设置中 MySQL 驱动使用的是 8.x 版本。当 SpringBoot 2.4.3(不含)版本之前会出现一个小 BUG,就是 MySQL 驱动升级到 8 以后要求强制配置时区,如果不设置会出问题。解决方案很简单,驱动 url 上面添加上对应设置就行了

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    username: root
    password: root

这里设置的 UTC 是全球标准时间,你也可以理解为是英国时间,中国处在东八区,需要在这个基础上加上 8 小时,这样才能和中国地区的时间对应的,也可以修改配置不写 UTC,写 Asia/Shanghai 也可以解决这个问题。

# 2.配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=Asia/Shanghai
    username: root
    password: root

如果不想每次都设置这个东西,也可以在 MySQL 数据库端配置时区解决此问题。去修改 MySQL 中的配置文件 mysql.ini,在 mysqld 项中添加 default-time-zone=+8:00 就可以解决这个问题。其实方式方法很多,这里就说这么多吧。

此外在运行程序时还会给出一个提示,说数据库驱动过时的警告,根据提示修改配置即可,弃用com.mysql.jdbc.Driver,换用 com.mysql.cj.jdbc.Driver。前面的例子中已经更换了驱动了,在此说明一下。

Loading class `com.mysql.jdbc.Driver'. This is deprecated. 
The new driver class is `com.mysql.cj.jdbc.Driver'. 
The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

总结

  1. 整合操作需要勾选 MyBatis 技术,也就是导入 MyBatis 对应的 starter

  2. 数据库连接相关信息转换成配置

  3. 数据库 SQL 映射需要添加 @Mapper 被容器识别到

  4. MySQL 8.x 驱动强制要求设置时区

    • 修改 url,添加 serverTimezone 设定
    • 修改 MySQL 数据库配置
  5. 驱动类过时,提醒更换为 com.mysql.cj.jdbc.Driver

3、整合 MyBatis-Plus

做完了两种技术的整合了,各位小伙伴要学会总结,我们做这个整合究竟哪些是核心?总结下来就两句话

  • 导入对应技术的 starter 坐标
  • 根据对应技术的要求做配置

虽然看起来有点虚,但是确实是这个理儿,下面趁热打铁,再换一个技术,看看是不是上面这两步。

接下来在 MyBatis 的基础上再升级一下,整合 MyBaits-Plus(简称 MP ),国人开发的技术,符合中国人开发习惯,谁用谁知道。来吧,一起做整合。

MyBatis-Plus 与 MyBatis 区别:

  • 导入坐标不同
  • 数据层实现简化

步骤 ①:导入对应的 starter,手动添加 SpringBoot 整合 MyBatis-Plus 的坐标,坐标可以通过 mvnrepository 获取

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

注意:由于 SpringBoot 中未收录 MyBatis-Plus 的坐标版本,需要指定对应的 Version

关于这个坐标,此处要说明一点,之前我们看的 starter 都是 spring-boot-starter-xxxxx,也就是说都是下面的格式

spring-boot-starter-***

而这个坐标的名字书写比较特殊,是第三方技术名称在前,boot 和 starter 在后。此处简单提一下命名规范,后期原理篇会再详细讲解

starter 所属 命名规则 示例
官方提供 spring-boot-starter-技术名称 spring-boot-starter-web
spring-boot-starter-test
第三方提供 第三方技术名称-spring-boot-starter druid-spring-boot-starter
第三方提供 第三方技术名称-boot-starter(第三方技术名称过长,简化命名) mybatis-plus-boot-starter

温馨提示

有些小伙伴在创建项目时想通过勾选的形式找到这个名字,别翻了,没有。截止目前,SpringBoot 官网还未收录此坐标,而我们 IDEA 创建模块时读取的是 SpringBoot 官网的 Spring Initializr,所以也没有。如果换用阿里云的 url 创建项目可以找到对应的坐标

步骤 ②:配置数据源相关信息

# 配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db
    username: root
    password: root

没了,就这么多,剩下的就是写 MyBaits-Plus 的程序了

映射接口(Dao):定义数据层接口与映射配置,继承 BaseMapper

@Mapper
public interface BookDao extends BaseMapper<Book> {
}

核心在于 Dao 接口继承了一个 BaseMapper 的接口,这个接口中帮助开发者预定了若干个常用的 API 接口,简化了通用 API 接口的开发工作。

image36

下面就可以写一个测试类进行测试了

@SpringBootTest
public class Springboot06MybatisPlusApplicationTests {
    @Autowired
    private BookDao bookDao;

    @Test
    void contextLoads() {
        System.out.println(bookDao.selectById(2));
    }

    @Test
    void testGetAll() {
        System.out.println(bookDao.selectList(null));
    }
}

温馨提示

目前数据库的表名定义规则是 tbl_模块名称,为了能和实体类相对应,需要做一个配置,相关知识各位小伙伴可以到 MyBatis-Plus 课程中去学习,此处仅给出解决方案。配置 application.yml 文件,添加如下配置即可,设置所有表名的通用前缀名

mybatis-plus:
  global-config:
    db-config:
      table-prefix: tbl_ # 设置所有表的通用前缀名称为tbl_

总结

  1. 手工添加 MyBatis-Plus 对应的 starter
  2. 数据层接口使用 BaseMapper 简化开发
  3. 需要使用的第三方技术无法通过勾选确定时,需要手工添加坐标

4、整合 Druid

使用 SpringBoot 整合了 3 个技术了,发现套路基本相同,导入对应的 starter,然后做配置,各位小伙伴需要一直强化这套思想。下面再整合一个技术,继续深入强化此思想。

前面整合 MyBatis 和 MyBatis-Plus 的时候,使用的数据源对象都是 SpringBoot 默认的数据源对象,下面我们手工控制一下,自己指定了一个数据源对象 Druid。

在没有指定数据源时,我们的配置如下:

# 配置相关信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=Asia/Shanghai
    username: root
    password: root

此时虽然没有指定数据源,但是根据 SpringBoot 的德行,肯定帮我们选了一个它认为最好的数据源对象,这就是 HiKari。通过启动日志可以查看到对应的身影。

2021-11-29 09:39:15.202  INFO 12260 --- [main] com.zaxxer.hikari.HikariDataSource      : HikariPool-1 - Starting...
2021-11-29 09:39:15.208  WARN 12260 --- [main] com.zaxxer.hikari.util.DriverDataSource : Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.
2021-11-29 09:39:15.551  INFO 12260 --- [main] com.zaxxer.hikari.HikariDataSource      : HikariPool-1 - Start completed.

上述信息中每一行都有 HiKari 的身影,如果需要更换数据源,其实只需要两步即可。

  1. 导入对应的技术坐标
  2. 配置使用指定的数据源类型

下面就切换一下数据源对象

步骤 ①:导入对应的坐标(注意,是坐标,此处不是 starter)

<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
</dependencies>

步骤 ②:修改配置,在数据源配置中有一个 type 属性,专用于指定数据源类型

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

这里其实要提出一个问题的,目前的数据源配置格式是一个通用格式,不管你换什么数据源都可以用这种形式进行配置。但是新的问题又来了,如果对数据源进行个性化的配置,例如配置数据源对应的连接数量,这个时候就有新的问题了。每个数据源技术对应的配置名称都一样吗?肯定不是啊,各个厂商不可能提前商量好都写一样的名字啊,怎么办?就要使用专用的配置格式了。这个时候上面这种通用格式就不能使用了,怎么办?还能怎么办?按照 SpringBoot 整合其他技术的通用规则来套啊,导入对应的 starter,进行相应的配置即可。

步骤 ①:导入 Druid 对应的 starter

<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.8</version>
    </dependency>
</dependencies>

步骤 ②:修改配置

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
      username: root
      password: root

注意观察,配置项中,在 datasource 下面并不是直接配置 url 这些属性的,而是先配置了一个 druid 节点,然后再配置的 url 这些东西。言外之意,url 这个属性是 druid 下面的属性,那你能想到吗?除了这 4 个常规配置外,还有druid 专用的其他配置。通过提示功能可以打开 druid 相关的配置查阅

image37

与 druid 相关的配置超过 200 条以上,这就告诉你,如果想做 druid 相关的配置,使用这种格式就可以了,这里就不展开描述了,太多了。

这是我们做的第 4 个技术的整合方案,还是那两句话:导入对应 starter,使用对应配置。没了,SpringBoot 整合其他技术就这么简单粗暴。

总结

  1. 整合 Druid 需要导入 Druid 对应的 starter
  2. 根据 Druid 提供的配置方式进行配置
  3. 整合第三方技术通用方式
    • 导入对应的 starter
    • 根据提供的配置格式,配置非默认值对应的配置项
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇