Spring Boot基础篇

2023年 9月 26日 62.2k 0

SpringBoot

文档更新日志

版本 更新日期 操作 描述
v1.0 2021/11/14 A 基础篇
v1.0.1 2021/11/30 U 更新基础篇错别字若干,不涉及内容变更
v2.0 2021/12/01 A 运维实用篇
V3.0 2022/2/21 A 开发实用篇
V4.0 2022/3/29 A 原理篇

前言

​很荣幸有机会能以这样的形式和互联网上的各位小伙伴一起学习交流技术课程,这次给大家带来的是Spring家族中比较重要的一门技术课程——SpringBoot。一句话介绍这个技术,应该怎么说呢?现在如果开发Spring程序不用SpringBoot那就是给自己过不去,SpringBoot为我们开发Spring程序提供了太多的帮助,在此借这个机会给大家分享这门课程,希望各位小伙伴学有所得,学有所用,学有所成。

​正如上面提到的,这门技术是用来加速开发Spring程序的,因此学习这门技术是有一定的门槛的。你可以理解为你现在是一门传统的手工艺人,现在工艺升级,可以加速你的生产制作过程,但是前提是你要会原始工艺,然后才能学习新的工艺。嗯,怎么说呢?有一定的门槛,至少Spring怎么回事,与Spring配合在一起工作的一堆技术又是怎么回事,这些搞明白才能来看这个技术,不然就只能学个皮毛,或者学着学着就开始因为其他技术不太过关,然后就学不下去了,然后,就没有然后了,果断弃坑了。不管怎么说,既来之则安之,加油学习吧,投资自己肯定是没毛病的。

课程内容说明

​SpringBoot这门技术课程所包含的技术点其实并不是很多,但是围绕着SpringBoot的周边知识,也就是SpringBoot整合其他技术,这样的知识量很大,例如SpringBoot整合MyBatis等等。因此为了能够将本课程制作的能够适应于各个层面的学习者进行学习,本套课程会针对小白,初学者,开发者三种不同的人群来设计全套课程。具体这三种人群如何划分,就按照我的描述形式来分吧,各位小伙伴可以对号入座,每种人群看课程的起始位置略有差别。

学习者 归类方式
小白 完全没有用过SpringBoot技术
初学者 能使用SpringBoot技术完成基础的SSM整合
开发者 能使用SpringBoot技术实现常见的技术整合工作

​简单说就是你能用SpringBoot做多少东西,一点不会就是小白,会一点就是初学者,大部分都会就是开发者。其实这个划分也不用过于纠结,这个划分仅仅是为了帮助你对本技术课程所包含的阶段模块划分做一个清晰认知,因为本课程中会将SpringBoot技术划分成4个单元,每个单元是针对不同的学习者准备的。

学习者 课程单元
小白 基础篇
初学者 应用篇( 运维实用篇 & 开发实用篇 )
开发者 原理篇

​看完这个划分你就应该有这么个概念,我没有用过SpringBoot技术,所以从基础篇开始学习;或者我会一点SpringBoot技术,那我从实用篇开始学就好了,就是这个意思。

​每个课程单元内容设置不同,目标也不一样,作为学习者如果想达成最佳的学习效果,最好明确自己的学习目标再进行学习,这样目标明确,学习的时候能够更轻松,你就不会在学习的时候纠结如下的问题了。比如学着基础篇在那想,这个东西是个什么原理啊?这个东西是这么用的,那个东西该怎么用啊?因为原理性的内容统一放置到了原理篇讲解了,应用相关的内容统一放到应用篇里面讲解,你在基础篇阶段纠结也没有用,这一部分不讲这些知识,在基础篇先把SpringBoot的基础使用掌握完再说后面的知识吧。

​此外还有一点需要说明的是,目前SpringBoot技术发展速度很快,更新速度也很快,因此后续还会对本套课程进行持续更新,特此在三个课程单元的基础上追加一个番外篇。番外篇的设置为了解决如下问题:

  • 持续更新SpringBoot后续发展出现的新技术
  • 讲解部分知识点规模较大的支线知识(例如WebFlux)
  • 扩展非实用性知识,扩展学习者视野

​每一个课程单元的学习目标如下,请各位查收,在学习的过程中可以阶段性的给自己提个问题,下面列出来的这些学习目标你是否达成了,可以检验你的学习成果。

课程单元 学习目标
基础篇 能够创建SpringBoot工程基于SpringBoot实现ssm/ssmp整合
应用篇 能够掌握SpringBoot程序多环境开发能够基于Linux系统发布SpringBoot工程能够解决线上灵活配置SpringBoot工程的需求能够基于SpringBoot整合任意第三方技术
原理篇 掌握SpringBoot内部工作流程理解SpringBoot整合第三方技术的原理实现自定义开发整合第三方技术的组件
番外篇 掌握SpringBoot整合非常见的第三方技术掌握相同领域的更多的解决方案,并提升同领域方案设计能力

​整体课程包含的内容就是这些啦,要想完成前面这些内容的学习,顺利的达成学习目标,有些东西还是要提前和大家说清楚的。SpringBoot课程不像是Java基础,不管你有没有基础,都可以听一听,这个课程还真不行,需要一定的前置知识。下面给大家列表一些前置知识,如果还有不太会的,需要想办法快速补救一下。

课程前置知识说明

课程单元 前置知识 要求
基础篇 Java基础语法 面向对象,封装,继承,多态,类与接口,集合,IO,网络编程等
基础篇 Spring与SpringMVC 知道Spring是用来管理bean,能够基于Restful实现页面请求交互功能
基础篇 Mybatis与Mybatis-Plus 基于Mybatis和MybatisPlus能够开发出包含基础CRUD功能的标准Dao模块
基础篇 数据库MySQL 能够读懂基础CRUD功能的SQL语句
基础篇 服务器 知道服务器与web工程的关系,熟悉web服务器的基础配置
基础篇 maven 知道maven的依赖关系,知道什么是依赖范围,依赖传递,排除依赖,可选依赖,继承
基础篇 web技术(含vue,ElementUI) 知道vue如何发送ajax请求,如何获取响应数据,如何进行数据模型双向绑定
应用篇 Linux(CenterOS7) 熟悉常用的Linux基础指令,熟悉Linux系统目录结构
应用篇 实用开发技术 缓存:Redis、MongoDB、……消息中间件:RocketMq、RabbitMq、……
原理篇 Spring 了解Spring加载bean的各种方式知道Spring容器底层工作原理,能够阅读简单的Spring底层源码

​看着略微有点多,其实还好吧,如果个别技术真的不会,在学习课程的时候多用心听就好,基础篇是可以跟着学下来了,后面的实用篇和原理篇就比较难了。比如我要在Linux系统下操作,命令我就直接使用了,然后你看不懂可能学习起来就比较心累了。

课程安排就说到这里了,下面进入到SpringBoot基础篇的学习

SpringBoot基础篇

在基础篇中,我给学习者的定位是先上手,能够使用SpringBoot搭建基于SpringBoot的web项目开发,所以内容设置较少,主要包含如下内容:

  • SpringBoot快速入门
  • SpringBoot基础配置
  • 基于SpringBoot整合SSMP

JC-1.快速上手SpringBoot

学习任意一项技术,首先要知道这个技术的作用是什么,不然学完以后,你都不知道什么时候使用这个技术,也就是技术对应的应用场景。SpringBoot技术由Pivotal团队研发制作,功能的话简单概括就是加速Spring程序的开发,这个加速要从如下两个方面来说

  • Spring程序初始搭建过程
  • Spring程序的开发过程

​ 通过上面两个方面的定位,我们可以产生两个模糊的概念:

  • SpringBoot开发团队认为原始的Spring程序初始搭建的时候可能有些繁琐,这个过程是可以简化的,那原始的Spring程序初始搭建过程都包含哪些东西了呢?为什么觉得繁琐呢?最基本的Spring程序至少有一个配置文件或配置类,用来描述Spring的配置信息,莫非这个文件都可以不写?此外现在企业级开发使用Spring大部分情况下是做web开发,如果做web开发的话,还要在加载web环境时加载时加载指定的spring配置,这都是最基本的需求了,不写的话怎么知道加载哪个配置文件/配置类呢?那换了SpringBoot技术以后呢,这些还要写吗?谜底稍后揭晓,先卖个关子
  • SpringBoot开发团队认为原始的Spring程序开发的过程也有些繁琐,这个过程仍然可以简化。开发过程无外乎使用什么技术,导入对应的jar包(或坐标)然后将这个技术的核心对象交给Spring容器管理,也就是配置成Spring容器管控的bean就可以了。这都是基本操作啊,难道这些东西SpringBoot也能帮我们简化?
  • ​ 带着上面这些疑问我们就着手第一个SpringBoot程序的开发了,看看到底使用SpringBoot技术能简化开发到什么程度。

    温馨提示

    如果对Spring程序的基础开发不太懂的小伙伴,看到这里可以弃坑了,下面的内容学习需要具备Spring技术的知识,硬着头皮学不下去的。

    JC-1-1.SpringBoot入门程序制作(一)

    下面让我们开始做第一个SpringBoot程序吧,本课程基于Idea2020.3版本制作,使用的Maven版本为3.6.1,JDK版本为1.8。如果你的环境和上述环境不同,可能在操作界面和操作过程中略有不同,只要软件匹配兼容即可(说到这个Idea和Maven,它们两个还真不是什么版本都能搭到一起的,说多了都是泪啊)。

    下面使用SpringBoot技术快速构建一个SpringMVC的程序,通过这个过程体会简化二字的含义。

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

    image-20211116125259385.png

    特别关注:第3步点击Next时,Idea需要联网状态才可以进入到后面那一页,如果不能正常联网,就无法正确到达右面那个设置页了,会一直联网转转转。

    特别关注:第5步选择java版本和你计算机上安装的JDK版本匹配即可,但是最低要求为JDK8或以上版本,推荐使用8或11。

    步骤②:选择当前模块需要使用的技术集

    image-20211116125615728.png

    按照要求,左侧选择web,然后在中间选择Spring Web即可,选完右侧就出现了新的内容项,这就表示勾选成功了。

    关注:此处选择的SpringBoot的版本使用默认的就可以了,需要说一点,SpringBoot的版本升级速度很快,可能昨天创建工程的时候默认版本是2.5.4,今天再创建工程默认版本就变成2.5.5了,差别不大,无需过于纠结,并且还可以到配置文件中修改对应的版本。

    步骤③:开发控制器类

    //Rest模式
    @RestController
    @RequestMapping("/books")
    public class BookController {
        @GetMapping
        public String getById(){
            System.out.println("springboot is running...");
            return "springboot is running...";
        }
    }
    

    入门案例制作的SpringMVC的控制器基于Rest风格开发,当然此处使用原始格式制作SpringMVC的程序也是没有问题的,上例中的@RestController与@GetMapping注解是基于Restful开发的典型注解。

    关注:做到这里SpringBoot程序的最基础的开发已经做完了,现在就可以正常的运行Spring程序了。可能有些小伙伴会有疑惑,Tomcat服务器没有配置,Spring也没有配置,什么都没有配置这就能用吗?这就是SpringBoot技术的强大之处。关于内部工作流程后面再说,先专心学习开发过程。

    步骤④:运行自动生成的Application类

    image-20211116130152452.png

    使用带main方法的java程序的运行形式来运行程序,运行完毕后,控制台输出上述信息。

    不难看出,运行的信息中包含了8080的端口,Tomcat这种熟悉的字样,难道这里启动了Tomcat服务器?是的,这里已经启动了。那服务器没有配置,哪里来的呢?后面再说。现在你就可以通过浏览器访问请求的路径,测试功能是否工作正常了。

    访问路径:	http://localhost:8080/books
    

    是不是感觉很神奇?当前效果其实依赖的底层逻辑还是很复杂的,但是从开发者角度来看,目前只有两个文件展现到了开发者面前。

    • pom.xml

      这是maven的配置文件,描述了当前工程构建时相应的配置信息。

      
      
          4.0.0
      
          
              org.springframework.boot
              spring-boot-starter-parent
              2.5.4
          
      
          com.itheima
          springboot_01_01_quickstart
          0.0.1-SNAPSHOT
      
          
              
                  org.springframework.boot
                  spring-boot-starter-web
              
      
              
                  org.springframework.boot
                  spring-boot-starter-test
                  test
              
          
      
      

      配置中有两个信息需要关注,一个是parent,也就是当前工程继承了另外一个工程,干什么用的后面再说,还有依赖坐标,干什么用的后面再说。

    • Application类

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

      这个类功能很简单,就一句代码,前面运行程序就是运行的这个类。

    ​ 到这里我们可以大胆推测一下,如果上面这两个文件没有的话,SpringBoot肯定没法玩,看来核心就是这两个文件了。由于是制作第一个SpringBoot程序,先不要关注这两个文件的功能,后面详细讲解内部工作流程。

    ​ 通过上面的制作,我们不难发现,SpringBoot程序简直太好写了,几乎什么都没写,功能就有了,这也是SpringBoot技术为什么现在这么火的原因,和Spring程序相比,SpringBoot程序在开发的过程中各个层面均具有优势。

    类配置文件 Spring SpringBoot
    pom文件中的坐标 手工添加 勾选添加
    web3.0配置类 手工制作
    Spring/SpringMVC配置类 手工制作
    控制器 手工制作 手工制作

    一句话总结一下就是能少写就少写,能不写就不写,这就是SpringBoot技术给我们带来的好处,行了,现在你就可以动手做一做SpringBoot程序了,看看效果如何,是否真的帮助你简化开发了。

    总结

  • 开发SpringBoot程序在Idea工具中基于联网的前提下可以根据向导快速制作
  • SpringBoot程序需要依赖JDK,版本要求最低为JDK8
  • SpringBoot程序中需要使用某种功能时可以通过勾选的形式选择技术,也可以手工添加对应的要使用的技术(后期讲解)
  • 运行SpringBoot程序通过运行Application程序进行
  • 思考

    前面制作的时候说过,这个过程必须联网才可以进行,但是有些时候你会遇到一些莫名其妙的问题,比如基于Idea开发时,你会发现你配置了一些坐标,然后Maven下载对应东西的时候死慢死慢的,甚至还会失败。其实这种现象和Idea这款IDE工具有关,万一Idea不能正常访问网络的话,我们是不是就无法制作SpringBoot程序了呢?咱们下一节再说。

    JC-1-2.SpringBoot入门程序制作(二)

    如果Idea不能正常联网,这个SpringBoot程序就无法制作了吗?开什么玩笑,世上IDE工具千千万,难道SpringBoot技术还必须基于Idea来做了?这是不可能的。开发SpringBoot程序可以不基于IDE工具进行,在SpringBoot官网中可以直接创建SpringBoot程序。

    SpringBoot官网和Spring的官网是在一起的,都是 spring.io 。你可以通过项目一级一级的找到SpringBoot技术的介绍页,然后在页面中间部位找到如下内容

    image-20211122150444816.png

    步骤①:点击Spring Initializr后进入到创建SpringBoot程序界面,接下来就是输入信息的过程,和在Idea中制作是一样的,只是界面发生了变化,根据自己的要求,在左侧选择对应信息和输入对应的信息。

    image-20211122150608039.png 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,同时其他两条配置也生效了,看来每个配置文件中的项都会生效,只不过如果多个配置文件中有相同类型的配置会优先级高的文件覆盖优先级的文件中的配置。如果配置项不同的话,所有的配置项都会生效。

    总结

  • 配置文件间的加载优先级 properties(最高)> yml > yaml(最低)
  • 不同配置文件中相同配置按照加载优先级相互覆盖,不同配置文件中不同配置全部保留
  • 教你一招:自动提示功能消失解决方案

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

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

  • Idea认为你现在写配置的文件不是个配置文件,所以拒绝给你提供提示功能

  • Idea认定你是合理的配置文件,但是Idea加载不到对应的提示信息

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

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

    image-20211126160548690.png

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

    Spring Boot基础篇-1

    Spring Boot基础篇-2

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

    Spring Boot基础篇-3

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

    image-20211126161145082.png
    Spring Boot基础篇-4

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

    Spring Boot基础篇-5

    总结

  • 指定SpringBoot配置文件

    • Setting → Project Structure → Facets

    • 选中对应项目/工程

    • Customize Spring Boot

    • 选择配置文件

  • JC-2-3.yaml文件

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

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

    • .yml格式(主流)

    • .yaml格式

      具体的语法格式要求如下:

  • 大小写敏感
  • 属性层级关系使用多行描述,每行结尾使用冒号结束
  • 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
  • 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
  • #号 表示注释
  • 上述规则不要死记硬背,按照书写习惯慢慢适应,并且在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格式中也可以表示数组,在属性名书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔。

    subject:
    	- Java
    	- 前端
    	- 大数据
    enterprise:
    	name: itcast
        age: 16
        subject:
        	- Java
            - 前端
            - 大数据
    likes: [王者荣耀,刺激战场]			#数组书写缩略格式
    users:							 #对象数组格式一
      - name: Tom
       	age: 4
      - name: Jerry
        age: 5
    users:							 #对象数组格式二
      -  
        name: Tom
        age: 4
      -   
        name: Jerry
        age: 5			    
    users2: [ { name:Tom , age:4 } , { name:Jerry , age:5 } ]	#对象数组缩略格式
    

    总结

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

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

    JC-2-4.yaml数据读取

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

    读取单一数据

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

    image-20211126180433356.png

    ​记得使用@Value注解时,要将该注解写在某一个指定的Spring管控的bean的属性名上方,这样当bean进行初始化时候就可以读取到对应的单一数据了。

    总结

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

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

    image-20211126180738569.png

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

    总结

  • 使用Environment对象封装全部配置信息
  • 使用@Autowired自动装配数据到Environment对象中
  • 读取对象数据

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

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

    Spring Boot基础篇-6

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

    Spring Boot基础篇-7

    温馨提示

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

    总结

  • 使用@ConfigurationProperties注解绑定配置信息到封装类中
  • 封装类需要定义为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: "Springtbootnlesson"
    

    总结

  • 在配置文件中可以使用${属性名}方式引用属性值
  • 如果属性中出现特殊字符,可以使用双引号包裹起来作为字符解析
  • 到这里有关yaml文件的基础使用就先告一段落,实用篇中再继续研究更深入的内容。

    JC-3.基于SpringBoot实现SSMP整合

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

    • 整合JUnit

    • 整合MyBatis

    • 整合MyBatis-Plus

    • 整合Druid

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

    JC-3-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中添加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即可。

    总结

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

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

    • 导入坐标,MyBatis坐标不能少,Spring整合MyBatis还有自己专用的坐标,此外Spring进行数据库操作的jdbc坐标是必须的,剩下还有mysql驱动坐标,本例中使用了Druid数据源,这个倒是可以不要

      
          
              com.alibaba
              druid
              1.1.16
          
          
              org.mybatis
              mybatis
              3.5.6
          
          
              mysql
              mysql-connector-java
              5.1.47
          
          
          
              org.mybatis
              mybatis-spring
              1.3.0
          
          
          
              org.springframework
              spring-jdbc
              5.2.10.RELEASE
          
      
      
    • 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格式

    步骤①:创建模块

    image-20211129092156020.png

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

    Spring Boot基础篇-8

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

    
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.2.0
        
    
        
            mysql
            mysql-connector-java
            runtime
        
    
    

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

    #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;
    }
    

    映射接口(Dao)

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

    测试类

    @SpringBootTest
    class Springboot05MybatisApplicationTests {
        @Autowired
        private BookDao bookDao;
        @Test
        void contextLoads() {
            System.out.println(bookDao.getById(1));
        }
    }
    

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

    注意:当前使用的SpringBoot版本是2.5.4,对应的坐标设置中Mysql驱动使用的是8x版本。使用SpringBoot2.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小时,这样才能和中国地区的时间对应的,也可以修改配置为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.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.
    

    总结

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

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

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

  • MySQL 8.X驱动强制要求设置时区

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

  • JC-3-3.整合MyBatis-Plus

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

    • 导入对应技术的starter坐标

    • 根据对应技术的要求做配置

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

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

    步骤①:导入对应的starter

    
        com.baomidou
        mybatis-plus-boot-starter
        3.4.3
    
    

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

    Spring-boot-start-***
    

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

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

    温馨提示

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

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

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

    ​ 没了,就这么多,剩下的就是写MyBaitsPlus的程序了

    映射接口(Dao)

    @Mapper
    public interface BookDao extends BaseMapper {
    }
    

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

    image-20211129100313919.png

    ​ 下面就可以写一个测试类进行测试了,此处省略。

    温馨提示

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

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

    总结

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

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

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

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

    #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
    

    此时虽然没有指定数据源,但是根据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的身影,如果需要更换数据源,其实只需要两步即可。

  • 导入对应的技术坐标

  • 配置使用指定的数据源类型

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

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

    
        
            com.alibaba
            druid
            1.1.16
        
    
    

    步骤②:修改配置,在数据源配置中有一个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,进行相应的配置即可。

    步骤①:导入对应的starter

    
        
            com.alibaba
            druid-spring-boot-starter
            1.2.6
        
    
    

    步骤②:修改配置

    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相关的配置查阅

    Spring Boot基础篇-9

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

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

    总结

  • 整合Druid需要导入Druid对应的starter
  • 根据Druid提供的配置方式进行配置
  • 整合第三方技术通用方式
    • 导入对应的starter
    • 根据提供的配置格式,配置非默认值对应的配置项
  • JC-3-5.SSMP整合综合案例

    SpringBoot能够整合的技术太多太多了,对于初学者来说慢慢来,一点点掌握。前面咱们做了4个整合了,下面就通过一个稍微综合一点的案例,将所有知识贯穿起来,同时做一个小功能,体会一下。不过有言在先,这个案例制作的时候,你可能会有这种感觉,说好的SpringBoot整合其他技术的案例,为什么感觉SpringBoot整合其他技术的身影不多呢?因为这东西书写太简单了,简单到瞬间写完,大量的时间做的不是这些整合工作。

    先看一下这个案例的最终效果

    主页面

    Spring Boot基础篇-10

    添加

    image-20211129113522459.png

    删除

    Spring Boot基础篇-11

    修改

    image-20211129113610966.png

    分页

    Spring Boot基础篇-12

    条件查询

    Spring Boot基础篇-13

    ​ 整体案例中需要采用的技术如下,先了解一下,做到哪一个说哪一个

  • 实体类开发————使用Lombok快速制作实体类
  • Dao开发————整合MyBatisPlus,制作数据层测试
  • Service开发————基于MyBatisPlus进行增量开发,制作业务层测试类
  • Controller开发————基于Restful开发,使用PostMan测试接口功能
  • Controller开发————前后端开发协议制作
  • 页面开发————基于VUE+ElementUI制作,前后端联调,页面数据处理,页面消息处理
    • 列表
    • 新增
    • 修改
    • 删除
    • 分页
    • 查询
  • 项目异常处理
  • 按条件查询————页面功能调整、Controller修正功能、Service修正功能
  • 可以看的出来,东西还是很多的,希望通过这个案例,各位小伙伴能够完成基础开发的技能训练。整体开发过程采用做一层测一层的形式进行,过程完整,战线较长,希望各位能跟紧进度,完成这个小案例的制作。

    0.模块创建

    对于这个案例如果按照企业开发的形式进行应该制作后台微服务,前后端分离的开发。

    Spring Boot基础篇-14

    我知道这个对初学的小伙伴要求太高了,咱们简化一下。后台做单体服务器,前端不使用前后端分离的制作了。

    Spring Boot基础篇-15

    一个服务器即充当后台服务调用,又负责前端页面展示,降低学习的门槛。

    下面我们创建一个新的模块,加载要使用的技术对应的starter,修改配置文件格式为yml格式,并把web访问端口先设置成80。

    pom.xml

    
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    
    

    application.yml

    server:
      port: 80
    

    1.实体类开发

    本案例对应的模块表结构如下:

    -- ----------------------------
    -- Table structure for tbl_book
    -- ----------------------------
    DROP TABLE IF EXISTS `tbl_book`;
    CREATE TABLE `tbl_book`  (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB AUTO_INCREMENT = 51 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
    
    -- ----------------------------
    -- Records of tbl_book
    -- ----------------------------
    INSERT INTO `tbl_book` VALUES (1, '计算机理论', 'Spring实战 第5版', 'Spring入门经典教程,深入理解Spring原理技术内幕');
    INSERT INTO `tbl_book` VALUES (2, '计算机理论', 'Spring 5核心原理与30个类手写实战', '十年沉淀之作,手写Spring精华思想');
    INSERT INTO `tbl_book` VALUES (3, '计算机理论', 'Spring 5 设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式');
    INSERT INTO `tbl_book` VALUES (4, '计算机理论', 'Spring MVC+MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手');
    INSERT INTO `tbl_book` VALUES (5, '计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握Java基础的读者');
    INSERT INTO `tbl_book` VALUES (6, '计算机理论', 'Java核心技术 卷I 基础知识(原书第11版)', 'Core Java 第11版,Jolt大奖获奖作品,针对Java SE9、10、11全面更新');
    INSERT INTO `tbl_book` VALUES (7, '计算机理论', '深入理解Java虚拟机', '5个维度全面剖析JVM,大厂面试知识点全覆盖');
    INSERT INTO `tbl_book` VALUES (8, '计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉');
    INSERT INTO `tbl_book` VALUES (9, '计算机理论', '零基础学Java(全彩版)', '零基础自学编程的入门图书,由浅入深,详解Java语言的编程思想和核心技术');
    INSERT INTO `tbl_book` VALUES (10, '市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
    INSERT INTO `tbl_book` VALUES (11, '市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍');
    INSERT INTO `tbl_book` VALUES (12, '市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');
    

    根据上述表结构,制作对应的实体类

    实体类

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

    实体类的开发可以自动通过工具手工生成get/set方法,然后覆盖toString()方法,方便调试,等等。不过这一套操作书写很繁琐,有对应的工具可以帮助我们简化开发,介绍一个小工具,lombok。

    Lombok,一个Java类库,提供了一组注解,简化POJO实体类开发,SpringBoot目前默认集成了lombok技术,并提供了对应的版本控制,所以只需要提供对应的坐标即可,在pom.xml中添加lombok的坐标。

    
        
        
            org.projectlombok
            lombok
        
    
    

    使用lombok可以通过一个注解@Data完成一个实体类对应的getter,setter,toString,equals,hashCode等操作的快速添加

    import lombok.Data;
    @Data
    public class Book {
        private Integer id;
        private String type;
        private String name;
        private String description;
    }
    

    到这里实体类就做好了,是不是比不使用lombok简化好多,这种工具在Java开发中还有N多,后面遇到了能用的实用开发技术时,在不增加各位小伙伴大量的学习时间的情况下,尽量多给大家介绍一些。

    总结

  • 实体类制作
  • 使用lombok简化开发
    • 导入lombok无需指定版本,由SpringBoot提供版本
    • @Data注解
  • 2.数据层开发——基础CRUD

    数据层开发本次使用MyBatisPlus技术,数据源使用前面学习的Druid,学都学了都用上。

    步骤①:导入MyBatisPlus与Druid对应的starter,当然mysql的驱动不能少

    
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.3
        
        
            com.alibaba
            druid-spring-boot-starter
            1.2.6
        
        
            mysql
            mysql-connector-java
            runtime
        
    
    

    步骤②:配置数据库连接相关的数据源配置

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

    步骤③:使用MyBatisPlus的标准通用接口BaseMapper加速开发,别忘了@Mapper和泛型的指定

    @Mapper
    public interface BookDao extends BaseMapper {
    }
    

    步骤④:制作测试类测试结果,这个测试类制作是个好习惯,不过在企业开发中往往都为加速开发跳过此步,且行且珍惜吧

    package com.itheima.dao;
    
    import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.baomidou.mybatisplus.core.metadata.IPage;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.itheima.domain.Book;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    public class BookDaoTestCase {
    
        @Autowired
        private BookDao bookDao;
    
        @Test
        void testGetById(){
            System.out.println(bookDao.selectById(1));
        }
    
        @Test
        void testSave(){
            Book book = new Book();
            book.setType("测试数据123");
            book.setName("测试数据123");
            book.setDescription("测试数据123");
            bookDao.insert(book);
        }
    
        @Test
        void testUpdate(){
            Book book = new Book();
            book.setId(17);
            book.setType("测试数据abcdefg");
            book.setName("测试数据123");
            book.setDescription("测试数据123");
            bookDao.updateById(book);
        }
    
        @Test
        void testDelete(){
            bookDao.deleteById(16);
        }
    
        @Test
        void testGetAll(){
            bookDao.selectList(null);
        }
    }
    

    温馨提示

    MyBatisPlus技术默认的主键生成策略为雪花算法,生成的主键ID长度较大,和目前的数据库设定规则不相符,需要配置一下使MyBatisPlus使用数据库的主键生成策略,方式嘛还是老一套,做配置。在application.yml中添加对应配置即可,具体如下

    server:
      port: 80
    
    spring:
      datasource:
        druid:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
          username: root
          password: root
    
    mybatis-plus:
      global-config:
        db-config:
          table-prefix: tbl_		#设置表名通用前缀
          id-type: auto				#设置主键id字段的生成策略为参照数据库设定的策略,当前数据库设置id生成策略为自增
    
    查看MyBatisPlus运行日志

    在进行数据层测试的时候,因为基础的CRUD操作均由MyBatisPlus给我们提供了,所以就出现了一个局面,开发者不需要书写SQL语句了,这样程序运行的时候总有一种感觉,一切的一切都是黑盒的,作为开发者我们啥也不知道就完了。如果程序正常运行还好,如果报错了,这个时候就很崩溃,你甚至都不知道从何下手,因为传递参数、封装SQL语句这些操作完全不是你开发出来的,所以查看执行期运行的SQL语句就成为当务之急。

    SpringBoot整合MyBatisPlus的时候充分考虑到了这点,通过配置的形式就可以查阅执行期SQL语句,配置如下

    mybatis-plus:
      global-config:
        db-config:
          table-prefix: tbl_
          id-type: auto
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    

    再来看运行结果,此时就显示了运行期执行SQL的情况。

    Creating a new SqlSession
    SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2c9a6717] was not registered for synchronization because synchronization is not active
    JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@6ca30b8a] will not be managed by Spring
    ==>  Preparing: SELECT id,type,name,description FROM tbl_book
    ==> Parameters: 
    {
            //如果操作成功,关闭弹层,显示数据
            if(res.data.flag){
                this.dialogFormVisible = false;
                this.$message.success("添加成功");
            }else {
                this.$message.error(res.data.msg);			//消息来自于后台传递过来,而非固定内容
            }
        }).finally(()=>{
            this.getAll();
        });
    },
    

    总结

  • 使用注解@RestControllerAdvice定义SpringMVC异常处理器用来处理异常的
  • 异常处理器必须被扫描加载,否则无法生效
  • 表现层返回结果的模型类中添加消息属性用来传递消息到页面
  • 11.页面功能开发

    F-5.分页功能

    分页功能的制作用于替换前面的查询全部,其中要使用到elementUI提供的分页组件。

    
    
        
        
    
    

    为了配合分页组件,封装分页对应的数据模型。

    data:{
    	pagination: {	
    		//分页相关模型数据
    		currentPage: 1,	//当前页码
    		pageSize:10,	//每页显示的记录数
    		total:0,		//总记录数
    	}
    },
    

    修改查询全部功能为分页查询,通过路径变量传递页码信息参数。

    getAll() {
        axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res) => {
        });
    },
    

    后台提供对应的分页功能。

    @GetMapping("/{currentPage}/{pageSize}")
    public R getAll(@PathVariable Integer currentPage,@PathVariable Integer pageSize){
        IPage pageBook = bookService.getPage(currentPage, pageSize);
        return new R(null != pageBook ,pageBook);
    }
    

    页面根据分页操作结果读取对应数据,并进行数据模型绑定。

    getAll() {
        axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize).then((res) => {
            this.pagination.total = res.data.data.total;
            this.pagination.currentPage = res.data.data.current;
            this.pagination.pagesize = res.data.data.size;
            this.dataList = res.data.data.records;
        });
    },
    

    对切换页码操作设置调用当前分页操作。

    //切换页码
    handleCurrentChange(currentPage) {
        this.pagination.currentPage = currentPage;
        this.getAll();
    },
    

    总结

  • 使用el分页组件
  • 定义分页组件绑定的数据模型
  • 异步调用获取分页数据
  • 分页数据页面回显
  • F-6.删除功能维护

    由于使用了分页功能,当最后一页只有一条数据时,删除操作就会出现BUG,最后一页无数据但是独立展示,对分页查询功能进行后台功能维护,如果当前页码值大于最大页码值,重新执行查询。其实这个问题解决方案很多,这里给出比较简单的一种处理方案。

    @GetMapping("{currentPage}/{pageSize}")
    public R getPage(@PathVariable int currentPage,@PathVariable int pageSize){
        IPage page = bookService.getPage(currentPage, pageSize);
        //如果当前页码值大于了总页码值,那么重新执行查询操作,使用最大页码值作为当前页码值
        if( currentPage > page.getPages()){
            page = bookService.getPage((int)page.getPages(), pageSize);
        }
        return new R(true, page);
    }
    
    F-7.条件查询功能

    最后一个功能来做条件查询,其实条件查询可以理解为分页查询的时候除了携带分页数据再多带几个数据的查询。这些多带的数据就是查询条件。比较一下不带条件的分页查询与带条件的分页查询差别之处,这个功能就好做了

    • 页面封装的数据:带不带条件影响的仅仅是一次性传递到后台的数据总量,由传递2个分页相关数据转换成2个分页数据加若干个条件

    • 后台查询功能:查询时由不带条件,转换成带条件,反正不带条件的时候查询条件对象使用的是null,现在换成具体条件,差别不大

    • 查询结果:不管带不带条件,出来的数据只是有数量上的差别,其他都差别,这个可以忽略

      经过上述分析,看来需要在页面发送请求的格式方面做一定的修改,后台的调用数据层操作时发送修改,其他没有区别。

      页面发送请求时,两个分页数据仍然使用路径变量,其他条件采用动态拼装url参数的形式传递。

      页面封装查询条件字段

      pagination: {		
      //分页相关模型数据
      	currentPage: 1,		//当前页码
      	pageSize:10,		//每页显示的记录数
      	total:0,			//总记录数
      	name: "",
      	type: "",
      	description: ""
      },
      

      页面添加查询条件字段对应的数据模型绑定名称

      
          
          
          
          查询
          新建
      
      

      将查询条件组织成url参数,添加到请求url地址中,这里可以借助其他类库快速开发,当前使用手工形式拼接,降低学习要求

      getAll() {
          //1.获取查询条件,拼接查询条件
          param = "?name="+this.pagination.name;
          param += "&type="+this.pagination.type;
          param += "&description="+this.pagination.description;
          console.log("-----------------"+ param);
          axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res) => {
              this.dataList = res.data.data.records;
          });
      },
      

      后台代码中定义实体类封查询条件

      @GetMapping("{currentPage}/{pageSize}")
      public R getAll(@PathVariable int currentPage,@PathVariable int pageSize,Book book) {
          System.out.println("参数=====>"+book);
          IPage pageBook = bookService.getPage(currentPage,pageSize);
          return new R(null != pageBook ,pageBook);
      }
      

      对应业务层接口与实现类进行修正

      public interface IBookService extends IService {
          IPage getPage(Integer currentPage,Integer pageSize,Book queryBook);
      }
      
      @Service
      public class BookServiceImpl2 extends ServiceImpl implements IBookService {
          public IPage getPage(Integer currentPage,Integer pageSize,Book queryBook){
              IPage page = new Page(currentPage,pageSize);
              LambdaQueryWrapper lqw = new LambdaQueryWrapper();
              lqw.like(Strings.isNotEmpty(queryBook.getName()),Book::getName,queryBook.getName());
              lqw.like(Strings.isNotEmpty(queryBook.getType()),Book::getType,queryBook.getType());
              lqw.like(Strings.isNotEmpty(queryBook.getDescription()),Book::getDescription,queryBook.getDescription());
              return bookDao.selectPage(page,lqw);
          }
      }
      

      页面回显数据

      getAll() {
          //1.获取查询条件,拼接查询条件
          param = "?name="+this.pagination.name;
          param += "&type="+this.pagination.type;
          param += "&description="+this.pagination.description;
          console.log("-----------------"+ param);
          axios.get("/books/"+this.pagination.currentPage+"/"+this.pagination.pageSize+param).then((res) => {
              this.pagination.total = res.data.data.total;
              this.pagination.currentPage = res.data.data.current;
              this.pagination.pagesize = res.data.data.size;
              this.dataList = res.data.data.records;
          });
      },
      

    总结

  • 定义查询条件数据模型(当前封装到分页数据模型中)
  • 异步调用分页功能并通过请求参数传递数据到后台
  • 基础篇完结

    基础篇到这里就全部结束了,在基础篇中带着大家学习了如何创建一个SpringBoot工程,然后学习了SpringBoot的基础配置语法格式,接下来对常见的市面上的实用技术做了整合,最后通过一个小的案例对前面学习的内容做了一个综合应用。整体来说就是一个最基本的入门,关于SpringBoot的实际开发其实接触的还是很少的,我们到实用篇和原理篇中继续吧,各位小伙伴,加油学习,再见。

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论