# 概述
SpringBoot 是个好东西,简化了很多,尤其是配置,很少的配置就能使得项目运行。
Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。Spring Boot 以约定大于配置的核心思想,默认帮我们进行了很多设置,多数 Spring Boot 应用只需要很少的 Spring 配置。同时它集成了大量常用的第三方库配置(例如 Redis、MongoDB、Jpa、RabbitMQ、Quartz 等等),Spring Boot 应用中这些第三方库几乎可以零配置的开箱即用。
# 创建
使用官方的 Spring Initializr 生成 SpringBoot 项目:https://start.spring.io/
当然 IDEA 也带有 SpringBoot 新建功能,只需要选好配置和依赖就行。
# 版本
SpringBoot 支持
目前(2023.03)Springboot 已经发布了 3.1.x 版本,但是 3 版本最低要求 JDK17。而 JDK8 可以使用 2.7.x 版本。
# 项目类型
首先对于项目的创建可以选择基于 Mevan 或是 Gradle,这里要提一下 Gradle:
Gradle 是一个基于 Apache Ant 和 Apache Mevan 概念的项目自动化建构工具。
构建脚本使用 Groovy 和 Kotlin 的特定领域语言来编写的,不是传统的 XML
groupid 和 artifactId 被统称为 “坐标” 是为了保证项目唯一性而提出的,如果你要把你项目弄到 maven 本地仓库去,你想要找到你的项目就必须根据这两个 id 去查找。
# 打包方式
jar 与 war 区别:
jar 是类的归档文件(JAVA Archive)是与平台无关的文件格式,它允许将多个组合成一个压缩文件,jar 文件格式以 zip 文件格式为基础。同时,jar 文件不仅用于压缩和发布,还用于部署和封装库、组件和插件程序,并可被编译器和 JVM 这样的工具直接使用。
war 包是一个 Web 应用程序,里面包含我们 web 程序需要的一些东西,其中包括 web.xml 的配置文件,前端的页面文件,以及依赖的 jar。便于我们部署工程,直接放到 tomcat 的 webapps 目录下,直接启动 tomcat 即可。同时,可以使用 WinRAR 查看 war 包,直接将后缀.war 改成.rar。
Web 存档 (war) 文件包含 Web 应用程序的所有内容。它减少了传输文件所需要的时间。
区别:
SpringBoot 项目既可以打成 war 包发布,也可以找成 jar 包发布。
jar 包:直接通过内置 Tomcat 运行,不需要额外安装 Tomcat。如需修改内置 Tomcat 的配置,只需要在 SpringBoot 的配置文件中配置。内置 Tomcat 没有自己的日志输出,全靠 jar 包应用输出日志。但是比较方便,快速,比较简单。
war 包:传统的应用交付方式,需要安装 Tomcat,然后放到 wabapps 目录下运行 war 包,可以灵活选择 Tomcat 版本,可以直接修改 Tomcat 的配置,有自己的 Tomcat 日志输出,可以灵活配置安全策略,相对打成 jar 包来说没那么快速方便。
# 依赖
在创建 springboot 项目时可以添加自己需要的依赖,只需要点击 ADD DEPENDENCIES 或者 ctrl + B
查找依赖进行添加
# 项目目录
项目下载解压后目录:
1 | ├─.idea |
# git 和 maven 相关文件
# .gitignore
分布式版本控制系统 git 的配置文件,忽略提交
在.gitignore 文件中,遵循相应的语法,在每一行指定一个忽略规则如:
.log
.temp
/vendor
# mvnw
maven wrapper 缩写
在 maven-wrapper.properties 文件中记录你要使用的 maven 版本,当用户执行 mvnw clean
命令,发现当前用户的 mevan 版本和期望的版本不一致,那么就下载期望的版本,然后用期望的版本来执行 mvn 命令
# .mvn 文件夹
存放 maven-wrapper.properties 和相关 jar 包
# mvn.cmd
执行 mvnw 命令的 cmd 入口
# resouces 目录
# static
存放静态资源
# templates
存放模板资源
freemaker 相关
# 配置文件
springboot 默认读取全局配置文件:
application.yam 或 application.properties 文件
yml 文件格式:yaml(Ain't a Markup Language)
一种直观的能够被电脑识别的数据序列化格式,并且容易被人类阅读
文件默认在 resources 目录下读取,使用配置文件修改默认配置
prooperties 文件格式:
1 | server.port=8080 |
yml 文件格式:
1 | server: |
# profile
Profile 是 Spring 用来针对不同环境对不同配置提供全局的 Profile 配置,使用 application-{Profile}.yml
主配置文件 application.yml
1 | ##环境选择配置 |
工程当中我们会使用三种配置文件对应不同的环境:
- dev 开发环境
- test 测试环境
- pro 正式环境
也可以使用 application-dev.xml
,然后在项目启动时加上 -Dspring.profiles.active=dev
来使用开发配置启动项目,在本地 idea 开发时可以在启动配置中加入这个参数:
启动时会打印相关信息:
1 | 2023-03-06 16:04:46.031 INFO 38292 --- [main] n.b.s.SecurityDepartmentApplication : The following 1 profile is active: "dev" |
# 日志
使用 web 自动引入依赖
application.yml:
1 | logging: |
# Start 坐标
SpringBoot 引入全新坐标体系,简化 pom.xml
使用 Spring MVC 来构建 RESTful Web 应用,并使用 Tomcat 作为默认容器
1 | <dependency> |
集成视图技术
1 | <dependency> |
1 | <dependency> |
Spring-boot 项目引入 starter 系列坐标,对应的版本库统一由父工程坐标统一控制,即:
1 | <parent> |
<relativePath/> 设定一个空值将始终从仓库中获取,不从本地路径获取
# 自动化配置
SpringBoot 的项目一般都会有 * Application 的入口类,入口类中提供 main 方法,这是一个标准的 Java 应用程序的入口方法。 @SpringBootApplication
注解是 SpringBoot 的核心注解,它其实是一个组合注解。
# 元注解概述
JDK1.5 开始,Java 增加了对元数据的支持,也就是 Annotation
注解就是就是代码中的特殊标记,用于替代配置文件
# meta-annotation
除了 JDK 定义好的注解,我们还可以自定义注解,JDK1.5 提供了四个标准用来对注解类型进行注解的注解类
@Target
@Retention
@Document
Inherited
# @Target 注解
描述注解的使用范围
Target 注解用来说明被注解的注解类可修饰的对象的范围:
注解可以修饰 packages types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量
取值范围在 ElementType 枚举中:
1 | public enum ElementType { |
# @Retention 注解
描述注解保留的时间范围
限定所注解的注解类注解到其他类上后,可以被保留到何时,一共三个策略,定义在 RetentionPolicy 枚举中:
1 | public enum RetentionPolicy { |
# @Documented 注解
描述在使用 javadoc 工具为类生成帮助文档时是否需要保留注解信息
# @Inherited 注解
使被修饰的注解具有继承性
# 总结
SpringBoot 通过 maven 中的 starter 导入了所需场景下的 jar 包,并通过主启动类 @SpringBootApplication 中的 @EnableAutoConfiguration 读取该 jar 路径下的 META—INF/spring.factories 下 EnableAutoFiguration 的配置类,这些配置类使用 @ConditionOnClass 来标注,根据 @ConditionOnClass 约束条件引入自动化环境的配置。
# 项目使用
# 开启
使用 war 包就打包为 war 包放到 tomcat 容器下
jar 包使用 java -jar 包名
运行
# 关闭
springboot 关闭貌似比较麻烦
# 使用 Actuator
1 | <dependency> |
SpringBoot 内置监控功能 Actuator,添加依赖后正常启动项目,Actuator 会把收集的所有信息暴露给 JMX(Java Management Extensions)
Spring Boot Actuator 端点通过 JMX 和 HTTP 公开暴露给外界访问,大多数时候我们使用基于 HTTP 的 Actuator 端点,因为它们很容易通过浏览器、CURL 命令、shell 脚本等方式访问。
常用端点:
- /beans:此端点返回应用程序中配置的所有 bean 的列表。
- /env:提供有关 Spring Environment 属性的信息。
- /health:显示应用程序运行状况
- /info:显示应用程序信息,我们可以在 Spring 环境属性中配置它。
- /mappings:显示所有 @RequestMapping 路径 的列表 。
- /shutdown:允许我们正常关闭应用程序。
- /threaddump:提供应用程序的线程转储。
# 全局异常处理
# @ControllerAdivice
组合注解,组合了 @Componet 注解,常用全局异常处理切面类,同时该注解可以指定扫描包范围
# @ExceptionHandler
spring3.x 引入,处理异常时标注到方法,代表当前方法处理异常有哪些
# 数据校验
# validation
日常项目开发中,对于前端提交的表单,后台接口接收到表单数据后,为了程序的严谨性,通常后端会加入业务参数的合法校验操作来避免程序的非技术性 bug, 这里对于客户端提交的数据校验,SpringBoot 通过 spring-boot-starter-validation 模块包含了数据校验的工作。
相关概念:
- JSR303:是一项标准,只提供规范不提供实现,规定一些校验规范即校验注解,如 @Null、@NouNull、@Pattern、位于 javax.validation.constrains 包下。JSR-349 是升级版本
- Hibernate Validation:对以上规范的实现,并增加了一些其他校验,如 @Email、@Length、@Range 等等
- Spring Validation :对 Hibernate Validation 的二次封装,在 SpringMVC 模块添加了自动校验,并将校验信息封装进了特定的类中
约束性注解:
注解 | 说明 |
---|---|
@AssertFalse | 可以为 null,如果不为 null 的话必须为 false |
@AssertTrue | 可以为 null,如果不为 null 的话必须为 true |
@DecimalMax | 设置不能超过最大值 |
@decimalMin | 设置不能超过最小值 |
@Digits | 设置必须是数字且数字整数的位数和小数的位数必须在指定范围内 |
@Future | 日期必须先在当前日期未来 |
@Past | 日期必须在当前日期过去 |
@Max | 最大不得超过此最大值 |
@Min | 最小不得小于最小值 |
@NotNull | 不能为 null 可以是空 |
@Null | 必须 null |
@Pattern | 必须满足指定的正则表达式 |
@Size | 集合、数组、map 等的 size () 不能为 0;字符串 trim () 后可以等于 “” |
必须是 email 格式 | |
@Length | 长度必须在指定范围内 |
@NotBlank | 字符串不能为 null,字符串 trim () 后不能为 “” |
@NotEmpty | 不能为 null,集合、数组、map 等 size () 不能为 0;字符串 trim () 后可以等于 “” |
@Range | 值必须在指定范围内 |
@URL | 必须是一个 URL |
配合全局异常捕捉
1 |
|
# 分布式缓存 Ehcache 整合
Ehcache 是一个成熟的 java 缓存框架,最早从 hibernate 发展而来,是进程中的缓存系统,它提供了用内存,磁盘文件存储,以及分布式存储的方式等多种灵活的 cache 管理方案,快速简单
springboot 对 Ehcache 的使用提供支持,所以在 springboot 中只需要简单配置即可使用 Ehcache 实现数据缓存处理。
依赖:
1 | <dependency> |
# 缓存配置文件
encache-config.xml
1 |
|
也可以:
1 | Cache cache = manager.getCache("mycache"); |
# SpringCache 相关注解说明
springBoot 缓存实现内部使用 springcache 实现缓存机制,这里集成 Ehcache 实际上是对 springCache 的抽象的一种实现。
# @CacheConfig
用于标注类上,可以存放该类中所有缓存的公有属性,比如缓存名
1 |
|
配置了该数据访问对象中返回的内容将存储于名为 users 的缓存对象中,我们也可以不使用该注解,直接通过 @Cacheable 自己配置缓存集的名字来定义。
# @Cacheable
应用到读取数据的方法上,即可缓存的方法,如查找方法,先从缓存中读取,如果没有就调用相应方法获取数据,然后把数据添加到缓存中。
该注解有以下参数:
- value、cacheNames : 两个等同的参数 (cacheNames 为 Spring4 新增,作为 value 的别名),用于指定缓存存储的集合名。由于 Spring4 中新增了 @CacheConfig, 因此在 Spring 了中原本必须有的 value 属性,也成为非必需项了
- key: 缓存对象存储在 Map 集合中的 key 值,非必需,缺省按照函数的所有参数组合作为 key 值,若自己配置需使用 SqL 表达式,比如: @Cacheable (key = "#p0") : 使用函数第一个 参数作为缓存的 key 值,更多关于 SpEL 表达式的详细内容可参
考官方文档。 - condition : 缓存对象的条件,非必需,也需使用 SpEL 表达式,只有满足表达式条件的内容才会被缓存,比如:
@Cacheable (key = "#p0", condition = "#p0.length ()< 3"),表示只有当第一个 参数的长度小于 3 的时候才会被缓存。 - unless : 另外一个缓存条件参数,非必需,需使用 SpEL 表达式。它不同于 condition 参数的地方在于它的判断时机,该条件是在函数被调用之后才做判断的,所以它可以通过对 result 进行判断。
- keyGenerator : 用于指定 key 生成器,非必需。若需要指定一个自定义的 key 生成器,我们需要去实现
org.springframework.cache.interceptor.KeyGenerator 接口,并使用该参数来指定。需要注意的是:该参数与 key 是互斥
的。 - cacheManager : 用于指定使用哪个缓存管理器,非必需。只有当有多个时才需要使用
- cacheResolver : 用于指定使用那个缓存解析器,非必需。需通过 org.springframework.cache.interceptor.CacheResolver
接口来实现自己的缓存解析器,并用该参数指定。
# 缓存过期策略
EhCache 提供了三种淘汰算法:
- FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。
- LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。
- LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。
Ehcache 采用的是懒淘汰机制,每次往缓存放入数据时,都会存一个时间,在读取时要和设置的时间做 TTL 比较来判断是否过期。
# 单元测试
控制层单元测试
1 |
|
# 热部署
热部署,就是再应用正在运行的时候升级软件(增加业务 / 修改 bug),而不需要重启应用。
项目开发过程中,常常会修改页面数据或数据结构,为了显示改动效果,往往需要重新启动应用,查看变动效果,其实就是重新编译生成了 class 文件,这个文件里记录了与代码对应的各种信息,然后 class 文件将被虚拟机 ClassLoader 加载。
而热部署正是利用了这个特点,它监听到如果有 Class 文件改动了。就会创建一个新的 ClassLoader 进行加载改文件,经过一系列的过程,最终将结果呈现在我们眼前,SpringBoot 通过配置 DevTools 工具来达到热部署效果。
在原理上是使用了两个 ClassLoader,一个 ClassLoader 加载哪些不会改变的类,另一个 ClassLoader 加载会改变的类,称为 resrart ClassLoader,这样在有代码更改的时候,原来的 restart ClassLoader 被丢弃,重新创建一个 restart ClassLoader,由于需要加载的类相比较少,所以实现了较快的重启时间,。
1 | <dependency> |
devtools 可以实现页面热部署(即页面修改后会立即生效,这个可以直接再 application.yml 文件中配置 spring.thymeleaf.cache=true 实现),实现类文件热部署(类文件修改后不会立即生效),实现对属性文件的热部署。即 devtools 会监听 classpath 下的文件变动,并且会立即重启应用(发生在保存实际),注意,以为其采用虚拟机机制,该项目重启是很快的。配置了后在修改 java 文件后也就支持了热启动,不过这种方式属于项目重启(速度比较快的项目重启),会清空 session 中的值,也就是如果有用户登录的话,项目重启后需要重新登录。
默认情况下,/META-INF/maven,/META-INF/resources,/resources , /static/templates, /public 这些文件修改不会使应用重启,但会重新加载(devtools 内嵌了一个 LiveReload server,当资源发生改变时,浏览器刷新
配置文件:
1 | spring: |
配置 spring.devtools.restart.enabled=true 后 restart 类加载器还会初始化,但不会监视文件更新
修改 java 类后,idea 默认是不自动编译的,而 spring-boot-devtools 又是监测 classpath 下的文件发生变化才重新启动应用,所以需要设置 idea 重新编译
之后启动应用 ctrl+F9 重新启动即热部署成功
# API 文档构建 - swagger2
由于 SpringBoot 能够快速开发、便捷部署等特性,通常再使用 SpringBoot 构建 RESTful 风格接口应用时考虑到多终端的原因,这些终端会共用很多底层逻辑,因此我们会抽象出这样一层来同时服务于多个移动端或者 Web 前端。对于不同的终端公用一套接口 API 时,对于联调测试的时候就知道后端提供的接口 Api 列表文档,对于服务端开发人员来说就需要编写接口文档,描述接口调用地址、参数结果等,这里借助第三方构建工具 Swagger2 来实现 API 文档生成功能。
依赖添加:
1 | <dependency> |
常用注解:
# @Api
用在请求的类上,说明该类作用
1 |
# @ApiOperation
@ApiOperation: 用在请求方法上,说明方法作用
value = 说明方法作用
notes = 方法的备用说明
1 |
# @ApiImplicitParams
1 | 用在方法上,包含一组参数说明 |
1 |
# @ApiResponses
1 | :用于请求的方法上,表示一组响应 |
# @ApiModel
用于响应类上,表示一个返回响应数据的信息(一般在 post 创建的时候,使用 @RequestBody 这样的场景,请求参数无法使用 @ApiImplicitParam 注解进行描述的时候)
@ApiModelProperty:用在属性上,描述响应类的属性
# Quartz 定时任务
在日常项目运行中,我们总会有需求在某一时间段周期性执行某个动作。比如每天再某个时间段导出报表,或者每隔多久统计一次现在在线的用户量等。
在 SpringBoot 中有 Java 自带的 Java.util.Timer 类,也有强大的调度器 Quartz,还有 SpringBoot 自带的 Scheduled 来实现。Scheduled 在 Spring3.X 引入,默认 SpringBoot 自带该功能,使用起来也很简单,在启动类级别添加 @EnableScheduling 注解即可引入定时任务环境。但遗憾的是 Scheduled 默认不支持分布式环境,这里主要讲解 Quartz 时钟调度框架与 SpringBoot 集成。
依赖:
1 | <dependency> |