Spring Boot是基于Spring开发的全新框架,相当于对Spring做了又一层封装。
其设计目的是用来简化Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。(也就是SpringBoot会对一些常用样板化的配置进行自动配置,简化开发成本),Spring能做的,SpringBoot都能做。
为啥其实Spring能做的功能已经非常强大了,我们还要学习SpringBoot呢?那就要不得不提到SpringBoot相对于Spring的各种优点了。
1.自动配置
SpringBoot中最重要的特性就是自动配置。
Springboot遵循“约定优于配置”的原则,自动做了默认配置。这样就不需要做大量的配置。
当我们需要使用什么场景时,就会自动配置这个场景相关的配置。
如果他的默认配置不符合我们的需求时修改这部分配置即可。
回想Spring阶段,我们如果要集成第三方框架的依赖,就需要在配置文件中开启相应的配置信息,例如引入AOP,Mybatis等,都需要在配置文件中填写各种配置信息。而这些配置信息又相对十分的固定(如果没有特殊需求的话),但是每次都需要我们自己写,又显得十分的繁琐,SpringBoot就对此进行该进,对一些常用样板化的配置进行自动配置,简化开发成本,我们只需要导入依赖就可以直接使用,抛弃繁琐的配置信息。
2.版本锁定与start机制
SpringBoot依靠其父工程(spring-boot-starter-parent )中的版本锁定和starter机制让我们能更轻松的实现对依赖的管理。
start机制
当我们需要使用某种功能时只需要引入对应的starter即可。一个starter针对一种特定的场景,其内部引入了该场景所需的依赖。这样我们就不需要单独引入多个依赖了,例如spring-boot-starter-web启动依赖内就包括了Tomcat,SpringBoot启动器等的依赖,因此可以可以秒级集成各种框架。
命名规律
官方starter都是以
spring-boot-starter
开头后面跟上场景名称。例如:spring-boot-starter-data-jpa非官方starter则是以
场景名-spring-boot-starter
的格式,例如:mybatis-spring-boot-starter版本控制
SpringBoot的父工程可以自动帮我们管理依赖版本,所以可以不用自己写版本号。
我们的SpringBoot模块都需要继承一个父工程:spring-boot-starter-parent。在spring-boot-starter-parent的父工程spring-boot-dependencies中对常用的依赖进行了版本锁定。这样我们在添加依赖时,很多时候都不需要添加依赖的版本号了。
当然我们也可以采用覆盖properties配置或者直接指定版本号的方式修改依赖的版本,这样就可以满足多种对依赖版本的需求。
3.其他优点
前面两个优点其实就是SpringBoot的主要优点,下面这些就属于一些其他优点。
● 内置运⾏容器,⽆需配置 Tomcat 等 Web 容器,直接运⾏和部署程序。
● 快速部署项⽬,⽆需外部容器即可启动并运⾏项⽬。● 可以完全抛弃繁琐的 XML,使⽤注解和配置的⽅式进⾏开发。● ⽀持更多的监控的指标,可以更好的了解项⽬的运⾏情况。
idea+jdk1.8+idea自带Maven插件
要想在创建SpringBoot项目或下载其他依赖的时候,不容易发生依赖包下载失败的情况,我们需要线配置一下本地仓库的Setting.xml的远程仓库配置信息,首先找到你自己的本地仓库位置,默认是在"{user.home}/.m2/repository",然后在repositroy同级目录下有一个Setting.xml文件,这个就是Maven的配置文件,如果没有这个文件也没关系,直接拷贝创建一个,一会我会把配置好的文件放下面,如果你自己修改过本地仓库的位置,同理你只要找到该配置文件进行配置就行。
1.配置国内源信息
maven在下载依赖时,会先在本地仓库寻找,如果有相关依赖,那么直接导入,如果没有那么就会从默认的远程仓库进行下载,但是由于远程仓库是在国外,所以如果网络不好就很有可能导致下载失败,所以我们要把远程仓库地址修改为国内仓库
例如我的本地仓库下的setting,xml在此
也可以在Idea下打开该配置文件
然后找到远程仓库的镜像信息
你的可能不是这个,我这个已经配置成阿里云的了
aliyunmaven central aliyun maven https://maven.aliyun.com/repository/public 如果这个也不行,还有其他的,也可以试一下
huaweicloud central HuaWei https://repo.huaweicloud.com/repository/maven/ nexus-tencentyun central tencent http://mirrors.cloud.tencent.com/nexus/repository/maven-public/ 2.配置默认编译器插件
这个不是必须的,可以在pom.xml的属性标签里也可以配置。
jdk-1.8 true 1.8 1.8 1.8 1.8
为了确保正常使用,我们要先对maven本地下载失败的残缺依赖进行清除,具体脚本如下,你需要自己创建一个.bat结尾的文件,然后将下面的脚本复制进行,填写你的仓库地址双击运行即可。
@echo off
rem create by NettQun
rem 这里写你的仓库路径
set REPOSITORY_PATH=E:\Develop\maven_rep
rem 正在搜索...
for /f "delims=" %%i in ('dir /b /s "%REPOSITORY_PATH%\*lastUpdated*"') do (
echo %%i
del /s /q "%%i"
)
rem 搜索完毕
pause
例如我的
1.创建maven项目
这个我就不具体演示了,非常简单,可能有的博主会使用SpringBoot创建插件来创建项目,但是其实我是不推荐的,因为使用插件很容易出现了一些问题,然后又要花时间去修改,但是我们如果使用maven来自己创建,那么哪里错了就可以很快定位。
例如我创建好了一个maven项目
2.导入添加SpringBoot父工程
前面我们说到SpringBoot可以依靠其父工程进行常用依赖进行版本锁定,所以我们先添加SpringBoot父工程。
org.springframework.boot spring-boot-starter-parent 2.5.0 3.导入SpringBoot启动器依赖
前面我们说SpringBoot最大的优点之一就是start机制,所以我们只需要添加spring-boot-starter-web启动器依赖就可以自动导入SpringBoot,Tomcat等的启动器依赖,很方便
org.springframework.boot spring-boot-starter-web 刷新一下依赖,可以看到,导入成功。
4.创建工程目录
1.创建启动类
首先要在src/java目录下创建一个启动类以及所在的目录,也就是包含main方法的唯一启动类,作为SpringBoot程序启动的起点,类名不唯一,然后在该启动类同级目录或者子目录下创建要注入到Spring容器中的类,这样才可以被SpringBoot识别托管并注入,至于为什么,这就又回到开头,SpringBoot的理念是"约定大于配置",这是人家开发者的设计,我们只要遵守即可。
创建好启动类和main方法后,在类的上面加上SpringBoot启动注解,然后main方法中调用SpringApplication.run()方法,即可完成,启动类所在目录及源码如下。
package com.lph; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication//1.添加SpringBoot启动类注解 public class AppApplication { public static void main(String[] args) { //调用SpringBoot启动方法(1.启动类字节码对象,主方法参数) SpringApplication.run(AppApplication.class,args); } }
2.添加配置文件
和Spring项目一样,Spring项目中需要一个xxx.xml的配置文件,那么SpringBoot项目中也一样需要一个配置文件,只不过这个配置文件不是.xml而是application.properties或application.yml,注意这两种格式的配置文件SpringBoot都能识别,都可以写,但是命名都需要以application.xxx格式,不然识别不了,约定大于配置,所以在resource目录下创建一个或多个配置文件。
至此,一个最基本的SpringBoot项目就创建好了。
基于上诉SpringBoot项目,我们在其基础上使用SpringBoot来完成一个输出hello world的简单web应用
1.创建controller
在启动类同级目录或子目录下创建一个处理请求的控制类
2.配置启动端口
选择两种配置文件中的一种就可以,这里先使用原始的application.properties进行配置,具体配置文件相关知识见后,设置一个启动端口号,我这里88883.启动项目并访问
访问成功
尽管上诉这是一个非常简单的入门程序,也可能出现千奇百怪的报错,我接下来就针对上诉入门程序说几个典型问题
●访问时404
这个问题属于资源未找到,也就是未找到请求路径,检查浏览器url是否和controller下的路径映射一致(RequestMapping),另外检查创建的Controller类是不是在启动类所在的包或者其子包下,如果不是需要进行修改,因为这是SpringBoot约定的项目结构,不然无法识别。
●依赖爆红
说明依赖导入失败,检查是否配置国内源,如果没有记得去配置阿里云镜像后刷新maven项目让其下载。
●controller注解使用错误
如果上诉问题都不是,那么还有一个可能出错的地方,那就是你的@RestController写成了@Controller,这是一个很容易犯的错,因为我们返回的是一个字符串数据,而不是一个页面,所以如果直接使用@Controller,就会出现浏览器页面显示错误,如下,所以要告诉浏览器该请求返回的是一个数据而非页面,就需要使用@Controller+@ResponseBody或直接使用@RestController。
快速入门阶段,我们简单认识了SpringBoot的两种配置文件,接下来就来详细认识一下这两种配置文件,那么配置文件究竟有些啥用呢?。
整个项⽬中所有重要的数据都是在配置⽂件中配置的,⽐如:●数据库的连接信息(包含⽤户名和密码的设置);●项⽬的启动端⼝;●第三⽅系统的调⽤秘钥等信息;●⽤于发现和定位问题的普通⽇志和异常⽇志等。想象⼀下如果没有配置信息,那么 Spring Boot 项⽬就不能连接和操作数据库,甚⾄是不能保存可以⽤于排查问题的关键⽇志,所以配置⽂件的作⽤是⾮常重要的
1.简介
这种类型的配置文件是早期SpringBoot使用的配置文件语法格式,是SpringBoot默认的配置文件格式。
2.语法
properties 是以键值的形式配置的,key 和 value 之间是以“=”连接的
例如:
# 配置项⽬端⼝号 server.port=8084 # 配置数据库连接信息 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=root
3.缺点分析
可以看到其实使用这种格式的配置文件其实是有一些明显的缺点的,例如有一些重复的信息,导致看上去配置信息十分冗余。
1.简介
yml 是 YAML 是缩写,它的全称 Yet Another Markup Language 翻译成中⽂就是“另⼀种标记语⾔”。2.语法yml 是树形结构的配置⽂件,它的基础语法是“key: value”,注意 key 和 value 之间使⽤英⽂冒汗加空格的⽅式组成的,其中的空格不可省略,不能使用TAB键代替。详细语法约定如下
k:[空格]v 表示键值对关系,冒号后面必须有一个空格
使用空格的缩进表示层级关系,空格数目不重要,只要是左对齐的一列数据,都是同一个层级的
大小写敏感
缩进时不允许使用Tab键,只允许使用空格。
java中对于驼峰命名法,可用原名或使用-代替驼峰,如java中的lastName属性,在yml中使用lastName或 last-name都可正确映射。
yml中注释前面要加#
例如上诉.properties配置文件转换为.yml:#配置端口信息 server: port: 8084 #配置数据库连接信息 spring: datasource: password: root url: jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8 username: root
3.键值关系
字面量
k: v:字面量直接写;
字符串默认不用加上单引号或者双绰号;
"": 双引号;转意字符能够起作用name: "sangeng \n caotang":输出;sangeng 换行 caotang
'':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据name: "sangeng \n caotang":输出;sangeng \n caotang
日期
对象(属性和值)、Map(键值对)
1.行内写法
2.多行写法
数组、list、set
行内写法
多行写法
对象数组、对象list、对象set
4.占位符赋值
在配置文件内部也是可以使用 ${key:defaultValue} 的方式来赋值,若key不存在,则会使用defaultValue来赋值,这个就叫做配置文件中参数之间的引用。
server: port: ${myPort:88} myPort: 80
5.优点
YAML易于人们阅读。
更加简洁明了
知道如何使用配置文件后,那么该如何在SpringBoot中读取配置文件中的信息呢?在SpringBoot项目中,无论是读取.properties还是.yml配置文件,读取方式都是一样的。
1.读取字面量
如果在项⽬中,想要主动的读取配置⽂件中的字面量内容,可以使⽤ @Value 注解来实现。@Value 注解使⽤“${}”的格式读取 ,但是要注意,使用@Value注解读取配置文件的类需要由Spring容器托管, 注意使用此注解只能获取简单类型的值(8种基本数据类型及其包装类,String,Date) 。例如:1.读取properties字面量
package com.lph.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class ConfigController { @Value("${property.str}") private String str; @Value("${property.str2}") private String str2; @Value("${property.int}") private int age; @Value("${property.bool}") private boolean flag; @RequestMapping("/test") public String test(){ return "str: "+str+"\n"+ "str2: "+str2+"\n"+ "age: "+age+"\n"+ "flag: "+flag+"\n"; } }
读取成功。
但是有可能在读取properties中文过程中出现乱码,你可以这样设置,然后删掉properties配置文件重新创建就可以了
2.读取.yml配置文件
package com.lph.controller; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class Config2Controller { @Value("${yml.str}") private String str; @Value("${yml.str2}") private String str2; @Value("${yml.int}") private int age; @Value("${yml.bool}") private boolean flag; @RequestMapping("/test2") public String test(){ System.out.println("str: "+str+"\n"+ "str2: "+str2+"\n"+ "age: "+age+"\n"+ "flag: "+flag+"\n"); return "访问成功2"; } }
读取运行结果
2.读取复杂类型和集合类型
当读取复杂数据类型时,这个时候就不能⽤ @Value 来读取配置中的对象了,此时要使⽤另⼀个注解 @ConfigurationProperties(prefix="配置前缀")来读取
在演示案例之前,先导入一下lombok的依赖,自动为类生成get/set/构造方法等,因为读取这种复杂类型的数据,其注意事项就是:要求对应的属性要有set/get方法,并且key要和成员变量名一致才可以对应的上。
org.projectlombok lombok 读取成功
加强练习
package com.lph.domain; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.Date; import java.util.List; import java.util.Map; @Data @AllArgsConstructor @NoArgsConstructor @ConfigurationProperties(prefix = "student2") public class Student2 { private String lastName; private Integer age; private Boolean boss; private Date birthday; private Map
maps; private Map maps2; private List list; private Dog dog; private String[] arr; private String[] arr2; private Map dogMap; } # 练习 student2: lastName: sangeng age: 15 boss: true birthday: 2006/2/3 maps: name: sangeng age: 11 maps2: {name: caotang,age: 199} list: - name: 小白 age: 3 - name: 小黄 age: 4 - {name: 小黑,age: 1} dog: name: 小红 age: 5 arr: - sangeng - caotang arr2: [sangeng,caotang] dogMap: xb: {name: 小白,age: 9} xh: name: 小红 age: 6
启动
读取成功
可以看到无论是哪种配置文件,其实读取配置信息都是相同的,只是配置信息的格式不同而已,所以只需要选择你喜欢的即可,尤其是这两种格式的文件也是有网站支持在线转换的
在线yaml转properties-在线properties转yaml-ToYaml.com
其实呢,SpringBoot读取配置文件也不止上诉介绍的两种方式,更多读取配置信息请查阅这篇大佬写的文章《读取配置文件的N种方式》
■ properties 是以 key=value 的形式配置的键值类型的配置⽂件,⽽ yml 使⽤的是类似 json 格式的树形配置⽅式进⾏配置的,yml 层级之间使⽤换⾏缩进的⽅式配置,key 和 value 之间使⽤“: ”英⽂冒号加空格的⽅式设置,并且空格不可省略。
■ properties 为早期并且默认的配置⽂件格式,但其配置存在⼀定的冗余数据,使⽤ yml 可以很好的解决数据冗余的问题。■ yml 通⽤性更好,⽀持更多语⾔,如 Java、Go、Python 等,如果是云服务器开发,可以使⽤⼀份配置⽂件作为 Java 和 Go 的共同配置⽂件。■ yml ⽀持更多的数据类型。
在使用SpringBoot配置文件参数时,配置文件中有时候一些参数不想要它只有某个固定值,例如密钥,服务端口号等,那么可以使用生成随机数来完成,也就是Spring Boot的属性配置⽂件中可以通过 ${random} 来产⽣int值、long值或者string字符串,来⽀持属性的随机值。。
# 随机字符串
com.didispace.blog.value=${random.value}
# 随机int
com.didispace.blog.number=${random.int}
# 随机long
com.didispace.blog.bignumber=${random.long}
# 10以内的随机数
com.didispace.blog.test1=${random.int(10)}
# 10-20的随机数
com.didispace.blog.test2=${random.int[10,20]}
例如
我们在开发Spring Boot应⽤时,通常同⼀套程序会被应⽤和安装到⼏个不同的环境,⽐如:开发、测试、⽣产等。其中每个环境的数据库地址、服务器端⼝等等配置都会不同,如果在为不同环境打包时都要频繁修改配置⽂件的话,那必将是个⾮常繁琐且容易发⽣错误的事。
对于多环境的配置,各种项⽬构建⼯具或是框架的基本思路是⼀致的,通过配置多份不同环境的配置⽂件,再通过打包命令指定需要打包的内容之后进⾏区分打包,Spring Boot也不例外,或者说更加简单。
在Spring Boot中多环境配置⽂件名需要满⾜ application-{profile}.properties 的格式,其中 {profile} 对应你的环境标识,⽐如:
⾄于哪个具体的配置⽂件会被加载,需要在 application.properties ⽂件中通过 spring.profiles.active
属性来设置,其值对应 {profile} 值。
如: spring.profiles.active=test 就会加载 application-test.properties 配置⽂件内容
下⾯,以不同环境配置不同的服务端⼝为例,进⾏样例实验。
按照上⾯的实验,可以如下总结多环境的配置思路:
回想一下,当你的程序运行报错了,那么你第一步会干嘛,不就是先看一下控制台打印输出了什么报错信息吗?然后再根据报错信息进行修改,很好,你已经学会使用日志的一部分了了。例如SpringBoot在启动时就会自动打印一些日志信息
当然日志就只能用于查看报错信息吗?并不是日志文件还有其他非常实用的功能
例如
除了发现和定位问题之外,我们还可以通过⽇志实现以下功能:♦记录⽤户登录⽇志,⽅便分析⽤户是正常登录还是恶意破解⽤户。♦记录系统的操作⽇志,⽅便数据恢复和定位操作⼈。♦记录程序的执⾏时间,⽅便为以后优化程序提供数据⽀持。以上这些都是⽇志提供的⾮常实⽤的功能
首先,从SpringBoot启动时在控制台自动打印的日志信息来看,其实这些日志信息是不需要我们开发者自己来进行打印的,SpringBoot内部自己就会打印这些日志信息,这是由于SpringBoot内置了日志打印的框架才得以实现的,所以如果我们想要在控制台自定义打印输出一些用于我们查看的日志信息,那么该如何操作呢?
1.使用日志对象
我们要想自定义输出日志信息,那么就先需要获取到用于·日志打印的日志对象,这个日志对象可以完成一些常用日志的打印,当然这个对象是SpringBoot里的日志框架slf4j为我们提供好的,我们可以直接获取并使用
在程序中获取⽇志对象需要使⽤⽇志⼯⼚ LoggerFactory@RestController public class LogController { //使用日志工厂获取日志对象 private static Logger log= LoggerFactory.getLogger(LogController.class); @RequestMapping("/log") public void test(){ log.info("-------------我的日志[info]------------"); log.error("-------------我的日志[error]------------"); } }
需要注意的是,Logger是"org.slf4j.Logger"包下的,不要导入错了。
日志打印格式
日志框架结构(了解)
日志级别作用
♣⽇志级别可以帮你筛选出重要的信息,⽐如设置⽇志级别为 error,那么就可以只看程序的报错⽇志了,对于普通的调试⽇志和业务⽇志就可以忽略了,从⽽节省开发者信息筛选的时间。♣⽇志级别可以控制不同环境下,⼀个程序是否需要打印⽇志,如开发环境我们需要很详细的信息,⽽⽣产环境为了保证性能和安全性就会输⼊尽量少的⽇志,⽽通过⽇志的级别就可以实现此需求。
日志级别分类与使用
⽇志的级别分为:trace:微量,少许的意思,级别最低;debug:需要调试时候的关键信息打印;info:普通的打印信息(默认⽇志级别);warn:警告,不影响使⽤,但需要注意的问题;error:错误信息,级别较⾼的错误⽇志信息;fatal:致命的,因为代码异常导致程序退出执⾏的事件。
使用日志级别
SpringBoot默认的日志级别是info,所以只能使用info或以上的日志级别,否则即使使用了该日志级别以下的日志,也无法在控制台打印显示,也就是说设置的日志级别越高,那么在控制台显示的日志就越少。
设置日志级别
⽇志级别配置只需要在配置⽂件中设置“logging.level”配置项即可,如下所示,将日志级别设置为最低。logging: level: root: trace
想要将⽇志进⾏持久化,只需要在配置⽂件中指定⽇志的存储⽬录或者是指定⽇志保存⽂件名之后, Spring Boot 就会将控制台的⽇志写到相应的⽬录或⽂件下了。
设置日志文件路径
# 设置⽇志⽂件的⽬录 logging: file: path: D:\java-ssm\sg\SpringBoot_csdn\src\main\resources
设置日志文件名
# 设置⽇志⽂件的⽂件名 logging: file: name: D:\java-ssm\sg\SpringBoot_csdn\src\main\resources\SpringBootDev.log
运行后
除了上诉使用日志工厂的方式获取日志对象,其实我们还可以使用更简便的注解方式来完成日志的输出。
每次都使⽤ LoggerFactory.getLogger(xxx.class) 很繁琐,且每个类都添加⼀遍,也很麻烦,这⾥讲⼀种更好⽤的⽇志输出⽅式,使⽤ lombok 来更简单的输出。1. 添加 lombok 框架⽀持。
org.projectlombok lombok 2. 使⽤ @slf4j 注解输出⽇志@RestController @Slf4j public class LogController2 { @RequestMapping("/log2") public void test(){ //直接使用log对象 log.info("使用@slf4j打印的日志信息"); } }
,恭喜你完成了SpringBoot的入门教学,接着学习,SpringMVC吧,然后再学习一下SpringBoot的常用场景。