初始SpringBoot
1. SpringBoot创建和运行
1.1. SpringBoot的概念
SpringBoot称为Spring的脚手架(脚手架就是盖房子的框架).
Spring是为了简化Java程序的开发诞生的, 而SpringBoot是为了简化Spring程序开发诞生的.所以称为Spring的框架.
1.2. SpringBoot的优点
- 快速集成框架- Spring Boot 提供了启动添加依赖的功能,用于秒级集成各种框架
- 内置运行容器- 无需配置 Tomcat 等 Web 容器,直接运行和部署程序
- 快速部署项目- 无需外部容器即可启动并运行项目
- 抛弃Spring中繁琐的XML方式- 使用注解和配置的方式进行开发
- 支持更多的监控的指标- 可以更好的了解项目的运行情况
1.3. SpringBoot的创建
这里有三种创建方式, 专业版idea中自带方式, 和 社区版安装插件后的方式. 第三种方式, 就是在官网下载项目的压缩包.然后解压到自己选择的位置, 再用idea打开即可.(其实三种方式大同小异, 知道一种也可以很快的熟悉另外两种方式)
1.3.0. 前置工作:安装插件(这是社区版需要做的工作, 专业版可以忽略)
- 选择Settings进入设置页面
- 选择 Plugins --> Makelplace, 在搜索框中搜索插件名称 spring assistant. 选择插件点击 Install 即可
1.3.1. 社区版创建方式
- 为了不体现对待专业版特殊化, 我们先讲解社区版插件的方式
- 先选择New Project 进入到创建新项目的页面, 点击插件的模块
- 然后 选择自己对应的JDK 和 依赖源, 依赖源一般有默认值,可以不填写, 如果需要用国内稳定源, 可以在Custom中配置
- 填写相关的内容, 一般练习中需要更改的也就是 项目类型, Java版本 和 项目名称. 更改好以后, 继续点击Next
- 选择对应的SpringBoot的版本, 添加所需要的依赖.就可以点击Next了
- 这里需要注意地是 3的大版本要求JDK 最低版本为JDK17, 所以创建时对于版本的选择要谨慎, 选择合适的版本即可, 并不是版本越高越好.
- 填写项目名称, 并选择位置, 就可以点击Finish创建项目了
- 如果提醒没有这个文件夹, 选择Create创建就可以了
- 需要注意, 第一次打开Spring Boot项目需要加载很久, 因为当前SpringBoot框架没有在自己的本地仓库, 需要从网上拉取. 所以我们需要耐心等待
- 如图就说明加载完成了. 到这里 我们的项目也就创建成功了
1.3.2. 专业版创建方式
- 同样先选择New Project 进入到创建页面, 然后选择Spring Initializr框
- 填写相关内容, 如果需要更改拉取的源地址, 可以在上面更改. 填写好以后就可以点击Next
- 选择对应版本以及选择要添加的具体依赖. 点击Finish就开始创建了
- 耐心等待一会, 项目就加载好了
我们观察后, 不难发现, 两种创建方式创建出来的项目是没有什么差别的, 所以以后我们使用哪种方式都是可以的.
1.3.3. 网页版创建方式
- 首先访问官网地址: https://start.spring.io/
- 访问之后填写和更改具体内容, 选择要添加的依赖(内容和idea创建类似)
- 下载好以后解压出来, 用idea打开即可
1.4. 项目目录介绍
SpringBoot项目有两个主要的目录
- Java源代码目录
- 静态资源和配置文件的目录
具体细节如图:
1.5. SpringBoot项目的运行
- 打开运行类, 点击三角号即可运行(右上角的三角号同样功能)
启动类代码
importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassShowSpringbootUltimateApplication{publicstaticvoidmain(String[] args){SpringApplication.run(ShowSpringbootUltimateApplication.class, args);}}
- 运行起来, 且等待一会项目没有报错, 就说明项目运行成功
1.6. 网页输出 Hello World
- 在启动类同包下创建一个包,包下新建一个类
- 直接输入 规范代码(包名全小写, 类名首字母大写). 图中格式会创建一个包, 包下创建一个类
- 图中为上图创建好后的目录格式. 包和启动类是同级别
- 在UserController中编写代码, 编写好以后重新启动项目
代码如下:
importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/user")publicclassUserController{@RequestMapping("/sayhello")publicStringsayHi(){return"Hello World!";}}
- 访问页面得到数据, 输出 Hello World 成功
注意事项: 约定大于配置!!! 上述编写代码, 运行成功是因为. 我们遵守了 项目要求的目录格式, 如果我们将controller没有建在启动类的包下, 就会出现错误.(SpringBoot 没有将对象注入到容器中). 因为默认情况下, 启动类只会注入自己同级别的包下的内容.所以要记住 约定大于配置.要遵守约定好的目录格式.
2. SpringBoot的配置文件
2.1. 配置文件的作用
整个项目中所有重要的数据都是在配置文件中配置的
- 数据库的连接信息
- 项目的启动端口
- 第三方系统的调用密钥
- 用于发现和定位问题的日志
- 等等
可见配置文件还是很重要的.
2.2. 配置文件的格式
一般有两种格式 .properties文件 和 .yml文件, 并且这两种格式的配置文件是可以共存的
2.2.1. 关于 .properties文件
- 属于老版本的配置文件, 是创建SpringBoot项目默认的配置文件
- 基本语法- 按照键值形式配置的, key和value之间是以 “=” 连接的- 示例 - 配置端口号: server.port=8031- 注意: 周围不能有空格,包括"="周围
- 读取配置文件- 使用 @Value 注解读取 @Value(“${server.port}”)的格式读取. 编写代码, 并重启项目
代码如下:
# .properties文件
server.port=8031
// .java文件importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.annotation.PostConstruct;@RestController@RequestMapping("/user")publicclassUserController{@Value("${server.port}")privateString port;@RequestMapping("/readport")publicStringreadPort(){return"port: "+ port;}@RequestMapping("/sayhello")publicStringsayHi(){return"Hello World!";}}
重启项目, 访问页面观察结果
- .properties文件 缺点分析
以配置数据库为例, 可以观察出来很明显的缺点就是会有很多冗余信息
yml格式的配置文件就不会出现这样的冗余信息
2.2.2. 关于 .yml文件
2.2.2.1. .yml属于新版本的配置文件. 是ymal的缩写
2.2.2.2. .yml文件的优势
- yml的可读性高, 易于理解.并且它的语法和其他高级语言类似, 并且可以简单表达数组, 散列表, 标量等数据形态
- yml 最大的优势是可以跨语言, 不止是 Java 中可以使用. golang, python 都可以使用 yaml 作为配置文件
2.2.2.3. yml基本语法
基本语法: key: value
示例: key: value :和value中间必须有空格
使用yml连接数据库示例
代码如下:
# 演示yml配置数据库spring:datasource:url: mysql://localhost:3306/fhs?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&nullCatalogMeansCurrent=trueusername: root
password:123456
2.2.2.4. yml配置读取
- yml读取配置的方式 和properties的读取方式相同
- 使用注解 @Value - @Value(“${string.hello}”)
2.2.2.4. yml进阶使用
1. yml 配置不同数据类型及 null
yml代码
# 字符串string.value: Hello
# 布尔值,true或falseboolean.value:trueboolean.value1:false# 整数int.value:10int.value1: 0b1010_0111_0100_1010_1110 # 二进制# 浮点数float.value:3.14159float.value1:314159e-5# 科学计数法# Null, ~代表nullnull.value:~
2. yml中value值添加单双引号的区别
- 字符串默认不用加上单引号或者双引号
- 单引号会转义特殊字符, 特殊字符最终只是⼀个普通的字符串数据(填写的什么就是什么)
- 双引号不会转义字符串里面的特殊字符; 特殊字符会作为本身想表示的意思存在.(比如 \n 就是 换行)
application.yml代码
string:str1: Hello \n Spring Boot.
str2:'Hello \n Spring Boot.'str3:"Hello \n Spring Boot."
UserController.java代码
importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.annotation.PostConstruct;@RestController@RequestMapping("/user")publicclassUserController{@Value("${string.str1}")privateString str1;@Value("${string.str2}")privateString str2;@Value("${string.str3}")privateString str3;//初始化调用@PostConstructpublicvoidpostConstruct(){System.out.println("string.str1:"+ str1);System.out.println("string.str2:"+ str2);System.out.println("string.str3:"+ str3);}}
补充: 关于@PostConstruct 注解
a. 类初始化时调用的方法
放在这里的原因是因为希望在项目启动时观察到方法输出, 并且这个注解又需要等待 属性注入, 否则无意义
b. 类初始化时调用的顺序
1. 构造方法 Constructor
2. @Autowired
3. @PostConstruct
3. 配置对象
配置: 首先在配置文件中配置对象, 有两种配置写法 普通写法和行内写法,两种同等效益
application.yml代码
# 配置对象student:id:1name: Java
age:18# 行内写法student2:{id:1,name: Java,age:18}
获取: 编写对象类, 获取配置信息并观察.
右键show_springboot_ultimate包选择New–>Java Class
在运行类同级目录下创建一个子包和一个对象类
编写对象类并获取配置内容. 这个时候就不能⽤ @Value 来读取配置中的对象了,此时要使⽤另⼀个注解 @ConfigurationProperties来读取
StudentComponent.java代码
importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.stereotype.Component;@ConfigurationProperties(prefix ="student")@ComponentpublicclassStudentComponent{privateint id;privateString name;privateint age;publicintgetId(){return id;}publicvoidsetId(int id){this.id = id;}publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}publicintgetAge(){return age;}publicvoidsetAge(int age){this.age = age;}@OverridepublicStringtoString(){return"StudentComponent{"+"id="+ id +", name='"+ name + ''' +", age="+ age +'}';}}
编写代码, 并重启项目. 观察Student对象配置信息获取情况. 可以观察到,成功获取信息.
ReadYml.java代码
importcom.example.show_springboot_ultimate.model.StudentComponent;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjavax.annotation.PostConstruct;@ComponentpublicclassReadYml{@AutowiredprivateStudentComponent studentComponent;@PostConstructpublicvoidpostConstruct(){System.out.println(studentComponent);}}
4. 配置集合
配置: 和配置对象类似, 有两种书写方式 普通写法和行内写法
application.yml代码
# 配置集合dbtypes:name:- mysql
- sqlserver
- db2
# 行内写法dbtypes2:{name:[ mysql,sqlserver,db2 ]}
获取: 同样编写有集合属性的类来观察, 先在model包下New一个类
创建拥有集合属性的类来接收获取的配置文件的信息
编写代码并获取配置信息. 集合的读取和对象⼀样,也是使用 @ConfigurationProperties 注解来读取的
ListConfig.java代码
importlombok.Data;importorg.springframework.boot.context.properties.ConfigurationProperties;importorg.springframework.stereotype.Component;importjava.util.List;@Component@ConfigurationProperties("dbtypes")@DatapublicclassListConfig{privateList<String> name;}
编写代码, 并重启项目. 观察集合配置信息获取情况. 可以观察到,成功获取信息.
ReadYmlList.java代码
importcom.example.show_springboot_ultimate.model.ListConfig;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Component;importjavax.annotation.PostConstruct;@ComponentpublicclassReadYmlList{@AutowiredprivateListConfig listConfig;@PostConstructpublicvoidpostConstruct(){System.out.println(listConfig.getName());}}
3. SpringBoot的日志文件
3.1. 日志使用
- 首先在程序中获取日志对象
- 使用日志打印
UserController.java代码
importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.annotation.PostConstruct;/**
* @author Echo
* @version 1.0
* date 2023/3/24 16:15
* name UserController
* @deprecated exercises:
* 类初始化调用顺序
* (1)构造方法Constructor
* (2)@Autowired
* (3)@PostConstruct
*/@RestController@RequestMapping("/user")publicclassUserController{//首先获取日志对象//不要导错包了.//import org.slf4j.Logger;//import org.slf4j.LoggerFactory;privatestaticLogger logger =LoggerFactory.getLogger(UserController.class);@Value("${server.port}")privateString port;@Value("${string.str1}")privateString str1;@Value("${string.str2}")privateString str2;@Value("${string.str3}")privateString str3;//初始化调用@PostConstructpublicvoidpostConstruct(){
logger.info("这是初始化方法的日志打印");System.out.println("string.str1:"+ str1);System.out.println("string.str2:"+ str2);System.out.println("string.str3:"+ str3);}@RequestMapping("/readport")publicStringreadPort(){//日志打印
logger.info("这是返回获取配置文件中端口方法的日志打印");return"port: "+ port;}@RequestMapping("/sayhello")publicStringsayHi(){//日志打印
logger.info("这是访问方法时的日志打印");return"Hello World!";}}
- 访问并观察
- 日志格式说明
日志格式: 日志打印时间 + 日志打印级别 + 线程ID + 线程名称 + 执行的类名 + 日志输出信息
3.2. 日志级别
- 日志级别分类- trace: 微量, 少许的意思, 级别最低- info: 普通的打印信息- debug: 需要调试时候的关键信息打印- warn: 警告, 不影响使用, 但需要注意的问题- error: 错误信息, 级别较高的错误日志信息- fatal: 致命的, 因为代码异常导致程序退出执行的事件
- 日志级别的顺序
越往上 , 接收到的消息越少(下打印的信息包含上的信息)
- 日志级别的配置
application.yml代码
# 配置日志打印等级logging:level:root: trace
UserController.java代码
importorg.springframework.beans.factory.annotation.Value;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjavax.annotation.PostConstruct;@RestController@RequestMapping("/user")publicclassUserController{//首先获取日志对象//不要导错包了.//import org.slf4j.Logger;//import org.slf4j.LoggerFactory;privatestaticLogger logger =LoggerFactory.getLogger(UserController.class);@Value("${string.str1}")privateString str1;@Value("${string.str2}")privateString str2;@Value("${string.str3}")privateString str3;//初始化调用@PostConstructpublicvoidpostConstruct(){//不同等级日志打印
logger.trace("这是初始化方法的日志打印");
logger.debug("这是初始化方法的日志打印");
logger.info("这是初始化方法的日志打印");
logger.warn("这是初始化方法的日志打印");
logger.error("这是初始化方法的日志打印");// fatal等级日志, 由于程序已经退出, 所以也就不会有打印了System.out.println("string.str1:"+ str1);System.out.println("string.str2:"+ str2);System.out.println("string.str3:"+ str3);}}
- 观察不同等级日志打印
3.3. 日志持久化
- 在配置文件中设置日志文件保存的目录即可自动保存日志.
application.yml代码
# 配置日志打印等级 + # 设置日志文件的目录logging:file:path: D:\home\ruoyi # 日志文件保存位置level:root: trace
设置文件保存的名称(名称里就可以包含了文件的目录, 所以目录配置就可以省略)
application.yml代码
# 配置日志打印等级 + # 设置日志文件保存的名称 + # 设置日志文件的目录logging:file:# path: D:\home\ruoyi # 日志文件保存位置name: D:\home\ruoyi\spring-1204.log # 日志文件保存名称(内涵日志位置)level:root: trace
3.4. 更简单的日志输出 – lombok
3.4.1. 添加lombok依赖
依赖地址: https://mvnrepository.com/artifact/org.projectlombok/lombok/1.18.20
依赖内容:
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version><scope>provided</scope></dependency>
3.4.2. 使用 @slf4j 注解代替输出日志
使用注解代替一行代码, 节省工作量(毕竟程序员很累的)
UserService.java代码
importlombok.extern.slf4j.Slf4j;importorg.springframework.stereotype.Controller;importorg.springframework.stereotype.Service;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.ResponseBody;/**
* 使用更简便的得到日志的方法:注解
*///@Service 设置为它无法直接访问路由@Controller//此处没有它就无法访问路由@ResponseBody//此处方法没有返回任何信息,没有它就会返回500页面(因为方法无返回内容)@Slf4j//代替了获取日志对象 (默认名称为log)publicclassUserService{//得到日志对象 注解代替了下面的代码// private static final Logger log = LoggerFactory.getLogger(UserService.class);@RequestMapping("/sayhello")publicvoidsayhello(){//名称同样为 log
log.trace("我是sayhello trace");
log.debug("我是sayhello debug");
log.info("我是sayhello info");
log.warn("我是sayhello warn");
log.error("我是sayhello error");}}
4. lombok的更多注解说明
基本注解作⽤@Getter⾃动添加 getter ⽅法@Setter⾃动添加 setter ⽅法@ToString⾃动添加 toString ⽅法@EqualsAndHashCode⾃动添加 equals 和 hashCode ⽅法@NoArgsConstructor⾃动添加⽆参构造⽅法@AllArgsConstructor⾃动添加全属性构造⽅法, 顺序按照属性的定义顺序@NonNull属性不能为 null@RequiredArgsConstructor⾃动添加必需属性的构造⽅法, final + @NonNull 的 属性为必需@Data@Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor + @NoArgsConstructor@Slf4j添加⼀个名为 log 的⽇志, 使⽤ slf4j
版权归原作者 魚小飛 所有, 如有侵权,请联系我们删除。