初始SpringBoot

350 阅读13分钟

1. SpringBoot创建和运行

1.1. SpringBoot的概念

SpringBoot称为Spring的脚手架(脚手架就是盖房子的框架).

Spring是为了简化Java程序的开发诞生的, 而SpringBoot是为了简化Spring程序开发诞生的.所以称为Spring的框架.

1.2. SpringBoot的优点

  1. 快速集成框架
    • Spring Boot 提供了启动添加依赖的功能,用于秒级集成各种框架
  2. 内置运行容器
    • 无需配置 Tomcat 等 Web 容器,直接运行和部署程序
  3. 快速部署项目
    • 无需外部容器即可启动并运行项目
  4. 抛弃Spring中繁琐的XML方式
    • 使用注解和配置的方式进行开发
  5. 支持更多的监控的指标
    • 可以更好的了解项目的运行情况

1.3. SpringBoot的创建

这里有三种创建方式, 专业版idea中自带方式, 和 社区版安装插件后的方式. 第三种方式, 就是在官网下载项目的压缩包.然后解压到自己选择的位置, 再用idea打开即可.(其实三种方式大同小异, 知道一种也可以很快的熟悉另外两种方式)

image.png

1.3.0. 前置工作:安装插件(这是社区版需要做的工作, 专业版可以忽略)

  1. 选择Settings进入设置页面

image.png

  1. 选择 Plugins --> Makelplace, 在搜索框中搜索插件名称 spring assistant. 选择插件点击 Install 即可

image.png

1.3.1. 社区版创建方式

  1. 为了不体现对待专业版特殊化, 我们先讲解社区版插件的方式

  2. 先选择New Project 进入到创建新项目的页面, 点击插件的模块

  3. 然后 选择自己对应的JDK 和 依赖源, 依赖源一般有默认值,可以不填写, 如果需要用国内稳定源, 可以在Custom中配置

image.png

  1. 填写相关的内容, 一般练习中需要更改的也就是 项目类型, Java版本 和 项目名称. 更改好以后, 继续点击Next

image.png

  1. 选择对应的SpringBoot的版本, 添加所需要的依赖.就可以点击Next了

image.png

  1. 这里需要注意地是 3的大版本要求JDK 最低版本为JDK17, 所以创建时对于版本的选择要谨慎, 选择合适的版本即可, 并不是版本越高越好.
  2. 填写项目名称, 并选择位置, 就可以点击Finish创建项目了

image.png

  1. 如果提醒没有这个文件夹, 选择Create创建就可以了

image.png

  1. 需要注意, 第一次打开Spring Boot项目需要加载很久, 因为当前SpringBoot框架没有在自己的本地仓库, 需要从网上拉取. 所以我们需要耐心等待
  2. 如图就说明加载完成了. 到这里 我们的项目也就创建成功了

image.png

1.3.2. 专业版创建方式

  1. 同样先选择New Project 进入到创建页面, 然后选择Spring Initializr框

  2. 填写相关内容, 如果需要更改拉取的源地址, 可以在上面更改. 填写好以后就可以点击Next

image.png

  1. 选择对应版本以及选择要添加的具体依赖. 点击Finish就开始创建了

image.png

  1. 耐心等待一会, 项目就加载好了

image.png

我们观察后, 不难发现, 两种创建方式创建出来的项目是没有什么差别的, 所以以后我们使用哪种方式都是可以的.

1.3.3. 网页版创建方式

  1. 首先访问官网地址: start.spring.io/

  2. 访问之后填写和更改具体内容, 选择要添加的依赖(内容和idea创建类似)

image.png

  1. 下载好以后解压出来, 用idea打开即可

1.4. 项目目录介绍

SpringBoot项目有两个主要的目录

  1. Java源代码目录
  2. 静态资源和配置文件的目录

具体细节如图:

image.png

1.5. SpringBoot项目的运行

  1. 打开运行类, 点击三角号即可运行(右上角的三角号同样功能)

image.png

启动类代码


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ShowSpringbootUltimateApplication {

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

}
  1. 运行起来, 且等待一会项目没有报错, 就说明项目运行成功

image.png

1.6. 网页输出 Hello World

  1. 在启动类同包下创建一个包,包下新建一个类

image.png

  1. 直接输入 规范代码(包名全小写, 类名首字母大写). 图中格式会创建一个包, 包下创建一个类

image.png

  1. 图中为上图创建好后的目录格式. 包和启动类是同级别

image.png

  1. 在UserController中编写代码, 编写好以后重新启动项目

image.png

代码如下:

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/sayhello")
    public String sayHi() {
        return "Hello World!";
    }
}
  1. 访问页面得到数据, 输出 Hello World 成功

image.png

注意事项: 约定大于配置!!! 上述编写代码, 运行成功是因为. 我们遵守了 项目要求的目录格式, 如果我们将controller没有建在启动类的包下, 就会出现错误.(SpringBoot 没有将对象注入到容器中). 因为默认情况下, 启动类只会注入自己同级别的包下的内容.所以要记住 约定大于配置.要遵守约定好的目录格式.

2. SpringBoot的配置文件

2.1. 配置文件的作用

整个项目中所有重要的数据都是在配置文件中配置的

  1. 数据库的连接信息
  2. 项目的启动端口
  3. 第三方系统的调用密钥
  4. 用于发现和定位问题的日志
  5. 等等

可见配置文件还是很重要的.

2.2. 配置文件的格式

一般有两种格式 .properties文件 和 .yml文件, 并且这两种格式的配置文件是可以共存的

image.png

2.2.1. 关于 .properties文件

  1. 属于老版本的配置文件, 是创建SpringBoot项目默认的配置文件

  2. 基本语法

    • 按照键值形式配置的, key和value之间是以 "=" 连接的
    • 示例
      • 配置端口号: server.port=8031
      • 注意: 周围不能有空格,包括"="周围
  3. 读取配置文件

    • 使用 @Value 注解读取 @Value(“${server.port}”)的格式读取. 编写代码, 并重启项目

image.png

代码如下:

# .properties文件
server.port=8031
// .java文件
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

@RestController
@RequestMapping("/user")
public class UserController {

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

    @RequestMapping("/readport")
    public String readPort() {
        return "port: " + port;
    }

    @RequestMapping("/sayhello")
    public String sayHi() {
        return "Hello World!";
    }
}

重启项目, 访问页面观察结果

image.png

  1. .properties文件 缺点分析

以配置数据库为例, 可以观察出来很明显的缺点就是会有很多冗余信息

image.png

yml格式的配置文件就不会出现这样的冗余信息

2.2.2. 关于 .yml文件

2.2.2.1. .yml属于新版本的配置文件. 是ymal的缩写

2.2.2.2. .yml文件的优势

  1. yml的可读性高, 易于理解.并且它的语法和其他高级语言类似, 并且可以简单表达数组, 散列表, 标量等数据形态
  2. yml 最大的优势是可以跨语言, 不止是 Java 中可以使用. golang, python 都可以使用 yaml 作为配置文件

2.2.2.3. yml基本语法

基本语法: key: value

示例: key: value :和value中间必须有空格

image.png

使用yml连接数据库示例

image.png

代码如下:

# 演示yml配置数据库
spring:
  datasource:
    url: mysql://localhost:3306/fhs?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&nullCatalogMeansCurrent=true
    username: root
    password: 123456

2.2.2.4. yml配置读取

  • yml读取配置的方式 和properties的读取方式相同
  • 使用注解 @Value
    • @Value("${string.hello}")

2.2.2.4. yml进阶使用

1. yml 配置不同数据类型及 null

image.png

yml代码

# 字符串
string.value: Hello
# 布尔值,true或false
boolean.value: true
boolean.value1: false
# 整数
int.value: 10
int.value1: 0b1010_0111_0100_1010_1110 # 二进制
# 浮点数
float.value: 3.14159
float.value1: 314159e-5 # 科学计数法
# Null, ~代表null
null.value: ~
2. yml中value值添加单双引号的区别
  • 字符串默认不用加上单引号或者双引号
  • 单引号会转义特殊字符, 特殊字符最终只是⼀个普通的字符串数据(填写的什么就是什么)
  • 双引号不会转义字符串里面的特殊字符; 特殊字符会作为本身想表示的意思存在.(比如 \n 就是 换行)

image.png

application.yml代码

string:
  str1: Hello \n Spring Boot.
  str2: 'Hello \n Spring Boot.'
  str3: "Hello \n Spring Boot."

UserController.java代码

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;

@RestController
@RequestMapping("/user")
public class UserController {

    @Value("${string.str1}")
    private String str1;
    @Value("${string.str2}")
    private String str2;
    @Value("${string.str3}")
    private String str3;

    //初始化调用
    @PostConstruct
    public void postConstruct() {
        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. 配置对象

配置: 首先在配置文件中配置对象, 有两种配置写法 普通写法和行内写法,两种同等效益

image.png

application.yml代码

# 配置对象
student:
  id: 1
  name: Java
  age: 18

# 行内写法
student2: { id: 1,name: Java,age: 18 }

获取: 编写对象类, 获取配置信息并观察.

右键show_springboot_ultimate包选择New-->Java Class

image.png

在运行类同级目录下创建一个子包和一个对象类

image.png

编写对象类并获取配置内容. 这个时候就不能⽤ @Value 来读取配置中的对象了,此时要使⽤另⼀个注解 @ConfigurationProperties来读取

image.png

StudentComponent.java代码

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@ConfigurationProperties(prefix = "student")
@Component
public class StudentComponent {
    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "StudentComponent{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

编写代码, 并重启项目. 观察Student对象配置信息获取情况. 可以观察到,成功获取信息.

image.png

ReadYml.java代码

import com.example.show_springboot_ultimate.model.StudentComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class ReadYml {
    @Autowired
    private StudentComponent studentComponent;

    @PostConstruct
    public void postConstruct() {
        System.out.println(studentComponent);
    }
}
4. 配置集合

配置: 和配置对象类似, 有两种书写方式 普通写法和行内写法

image.png

application.yml代码

# 配置集合
dbtypes:
  name:
    - mysql
    - sqlserver
    - db2

# 行内写法
dbtypes2: { name: [ mysql,sqlserver,db2 ] }

获取: 同样编写有集合属性的类来观察, 先在model包下New一个类

image.png

创建拥有集合属性的类来接收获取的配置文件的信息

image.png

编写代码并获取配置信息. 集合的读取和对象⼀样,也是使用 @ConfigurationProperties 注解来读取的

image.png

ListConfig.java代码

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@ConfigurationProperties("dbtypes")
@Data
public class ListConfig {
    private List<String> name;
}

编写代码, 并重启项目. 观察集合配置信息获取情况. 可以观察到,成功获取信息.

image.png

ReadYmlList.java代码

import com.example.show_springboot_ultimate.model.ListConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class ReadYmlList {
    @Autowired
    private ListConfig listConfig;

    @PostConstruct
    public void postConstruct() {
        System.out.println(listConfig.getName());
    }
}

3. SpringBoot的日志文件

3.1. 日志使用

  1. 首先在程序中获取日志对象

image.png

  1. 使用日志打印

image.png

UserController.java代码


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.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")
public class UserController {

    //首先获取日志对象
    //不要导错包了.
    //import org.slf4j.Logger;
    //import org.slf4j.LoggerFactory;
    private static Logger logger = LoggerFactory.getLogger(UserController.class);

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

    @Value("${string.str1}")
    private String str1;
    @Value("${string.str2}")
    private String str2;
    @Value("${string.str3}")
    private String str3;

    //初始化调用
    @PostConstruct
    public void postConstruct() {
        logger.info("这是初始化方法的日志打印");
        System.out.println("string.str1:" + str1);
        System.out.println("string.str2:" + str2);
        System.out.println("string.str3:" + str3);
    }

    @RequestMapping("/readport")
    public String readPort() {
        //日志打印
        logger.info("这是返回获取配置文件中端口方法的日志打印");
        return "port: " + port;
    }

    @RequestMapping("/sayhello")
    public String sayHi() {
        //日志打印
        logger.info("这是访问方法时的日志打印");
        return "Hello World!";
    }
}
  1. 访问并观察

访问.png

观察.png

  1. 日志格式说明

image.png

日志格式: 日志打印时间 + 日志打印级别 + 线程ID + 线程名称 + 执行的类名 + 日志输出信息

3.2. 日志级别

  1. 日志级别分类

    • trace: 微量, 少许的意思, 级别最低
    • info: 普通的打印信息
    • debug: 需要调试时候的关键信息打印
    • warn: 警告, 不影响使用, 但需要注意的问题
    • error: 错误信息, 级别较高的错误日志信息
    • fatal: 致命的, 因为代码异常导致程序退出执行的事件
  2. 日志级别的顺序

image.png

越往上 , 接收到的消息越少(下打印的信息包含上的信息)

  1. 日志级别的配置

image.png

application.yml代码

# 配置日志打印等级
logging:
  level:
    root: trace

UserController.java代码

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
@RestController
@RequestMapping("/user")
public class UserController {

    //首先获取日志对象
    //不要导错包了.
    //import org.slf4j.Logger;
    //import org.slf4j.LoggerFactory;
    private static Logger logger = LoggerFactory.getLogger(UserController.class);

    @Value("${string.str1}")
    private String str1;
    @Value("${string.str2}")
    private String str2;
    @Value("${string.str3}")
    private String str3;

    //初始化调用
    @PostConstruct
    public void postConstruct() {
        //不同等级日志打印
        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);
    }
}
  1. 观察不同等级日志打印

image.png

3.3. 日志持久化

  1. 在配置文件中设置日志文件保存的目录即可自动保存日志.

image.png

application.yml代码

# 配置日志打印等级 + # 设置日志文件的目录
logging:
  file:
    path: D:\home\ruoyi # 日志文件保存位置
  level:
    root: trace
  1. 设置文件保存的名称(名称里就可以包含了文件的目录, 所以目录配置就可以省略)

image.png

application.yml代码

# 配置日志打印等级 + # 设置日志文件保存的名称 + # 设置日志文件的目录
logging:
  file:
  #  path: D:\home\ruoyi # 日志文件保存位置
    name: D:\home\ruoyi\spring-1204.log # 日志文件保存名称(内涵日志位置)
  level:
    root: trace
  1. 指定日志文件最大大小. 当日志文件大小超过指定大小时, SpringBoot将自动滚动日志文件并创建新文件
# 配置日志文件的最大大小
logging:
  file:
    name: myapp.log
    max-size: 10MB
  1. 指定日志文件最大保存数量. 当日志文件超过最大大小后新增时, SpringBoot将保留指定数量的旧文件
logging:
  file:
    name: myapp.log
    max-size: 10MB
    max-history: 5

3.4. 日志输出格式化

SpringBoot提供了一种简单的方式来格式化应用程序代码中记录的日志信息. 在application.properties或application.yml配置文件中, 您可以使用logging.pattern属性来指定日志的输出格式

例:

logging:
  pattern:
    console: "%d %clr(%-5level) %m%n"

3.4.1. 关于输出格式中的常用属性

  • %d":时间
  • %-5level:级别
  • %m%n:消息
  • %c:Logger的名称
  • %C:调用记录器的类的名称
  • %t:线程名称
  • %L:调用记录器的行号
  • %F:调用记录器的文件名
  • %M:调用记录器的方法名

3.4.2. 完整的格式化模板

一个完整的格式化模板如下所示:

logging:
  pattern:
    console: "%d [%thread] %-5level %logger{35} - %msg%n"

上面的配置设置了四个属性:

  • %d:当前时间。
  • [%thread]:当前线程名称(用方括号括起来)
  • %-5level:级别,左对齐并最多为5个字符长
  • %logger{35}:Logger的名称,最多为35个字符长度。如果超过这个长度,将使用省略符号(...)代替

此外,我们还可以使用常量字符串,例如“===>”或者“<===”,来分隔日志记录

logging:
  pattern:
    console: "\n\n=====> %msg <=====\n\n"

上面的配置将消息用两个空行与前后的“===>”包围起来

3.5. 更简单的日志输出 -- lombok

3.5.1. 添加lombok依赖

image.png

依赖地址: mvnrepository.com/artifact/or…

依赖内容:

<!-- 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.5.2. 使用 @slf4j 注解代替输出日志

使用注解代替一行代码, 节省工作量(毕竟程序员很累的)

image.png

UserService.java代码

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 使用更简便的得到日志的方法:注解
 */
//@Service  设置为它无法直接访问路由
@Controller//此处没有它就无法访问路由
@ResponseBody
//此处方法没有返回任何信息,没有它就会返回500页面(因为方法无返回内容)
@Slf4j//代替了获取日志对象   (默认名称为log)
public class UserService {
    //得到日志对象 注解代替了下面的代码
//    private static final Logger log = LoggerFactory.getLogger(UserService.class);

    @RequestMapping("/sayhello")
    public void sayhello(){
        //名称同样为 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