一、什么是Spring?

Spring 是一个开源框架,2003年兴起的一个轻量级的Java开发框架。

Spring为了解决企业级应用开发的复杂性而创建的,简化开发。


Spring是如何简化开发的?

为了降低Java开发的复杂性,Spring采用了一下四种关键策略:

  • 基于POJO的轻量级和最小侵入性编程;
  • 通过IOC、依赖注入(DI)和面向接口实现松耦合;
  • 基于切面(AOP)和惯例进行声明式编程;
  • 通过切面和模板(template)减少样式代码;

二、什么是SpringBoot?

SPring Boot基于 Spring 开发,Spring Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快捷,敏捷地开发新一代基于 Spring 框架的应用程序。

SpringBoot 的主要优点:

  • 为所有Spring 开发者更快的入门
  • 开箱即用,提供各种默认配置来简化项目配置
  • 内嵌式容器简化web项目
  • 没有冗余代码生成和XML配置的要求

三、第一个SpringBoot程序

1、环境需求:

  • jdk1.8
  • maven 3.6.1
  • springboot 最新版
  • IDEA

2、创建项目:(建议使用第二种方法)

第一种方式:通过SPring官网,生成压缩包,可能打不开...

Spring官网:Spring | Home

  1. 点击 Projects,选择 Spring Boot

SpringBoot全解_java

  1. 往下滑,找到 Spring initializr,点击

SpringBoot全解_java_02

  1. 填好需要创建的项目信息,点击 最后一行的 GENERATE,生成zip压缩包

SpringBoot全解_配置文件_03

  1. 解压压缩包,直接导入idea。导入idea 后需加载很长时间(根据网速而定)。

第二种方式:直接使用 idea 创建新项目

  1. 依次点击 File->new->project

SpringBoot全解_java_04

  1. 点击左边栏 Spring Initializr,进行项目文件信息的设置,设置完成后点击 next

SpringBoot全解_配置文件_05

  1. 设置 SPringBoot版本,打勾 spring web,点击 Finish

SpringBoot全解_spring_06

  1. 等待一会儿,项目新建完成!附上项目目录

SpringBoot全解_配置文件_07

3、启动项目,在页面上返回一个字符串

  1. 配置项目结构:

SpringBoot全解_配置文件_08

  1. 在 Controller 包下新建一个 java文件 :HelloControlller.java
package com.yyt.springbootdemo.controller;

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

//@Controller // 普通Controller
@RestController  //返回字符串的Controller
public class HelloController {

    //接口:http://localhost:8080/hello
    @RequestMapping("/hello")
    public String hello(){
//        调用业务,接收前端的参数
        return "hello,Spring Boot!";
    }
}
  1. 运行 SpringBootDemoApplication,在浏览器中输入 localhost:8080/hello,运行成功界面。

SpringBoot全解_java_09

四、原理初探

自动配置

pom.xml:

  • spring-boot-dependencies:核心依赖在父工程中。
// 依赖管理 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
//他的父依赖
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.7.9</version>
  </parent>
  • 在写或者引入一些SpringBoot依赖的时候,不需要指定版本,因为有版本仓库。

启动器:

<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
       </dependency>
  • 启动器:就是Springboot的启动场景;
  • 比如:spring-boot-starter-web 就会自动导入 web 环境所有的依赖
  • springboot会把所有的功能场景,变成一个一个的启动器
  • 我们要使用什么功能,只需要找到对应的启动器就可以 starter ,直接在官网上寻找。

主程序:

package com.yyt.springbootdemo;

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


//程序的主入口
// @SpringBootApplication: 标注这个类是一个 SpringBoot的应用,启动类下的所有zi'yaun
@SpringBootApplication
public class SpringBootDemoApplication {

    public static void main(String[] args) {
        // 通过 run 方法,将这个程序启动。
        // 该方法主要分为两部分,一部分是SpringApplication的实例化,二是run方法的执行。
        SpringApplication.run(SpringBootDemoApplication.class, args);
    }

}
- 注解
@SpringBootConfiguration:Springboot的配置
    @Configuration:spring配置类
      @Component:说明这也是一个Spring的组件
      
@EnableAutoConfiguration:自动配置
   @AutoConfigurationPackage: 自动配置包
       @Import({Registrar.class}):自动配置`包注册`
   @Import({AutoConfigurationImportSelector.class}):自动配置导入选择
   
//获取所有的配置
 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {·······}

META-INF/spring-factories:自动配置的核心文件

SpringBoot全解_java_10

Properties properties = PropertiesLoaderUtils.loadProperties(resource);
所有资源加载到配置类中。

自动配置原理梳理:

SpringBoot全解_java_11

总结:springboot所有自动配置都是在启动的时候扫描并加载:spring.factories 所有自动配置类都在这里面,但是并不一定生效,要判断 @ConditionalOnxxx里面的条件是否满足。只要导入了对应的 start,就有对应的启动器,有了启动器,自动装配就会生效,就可以配置成功!

  1. SpringBoot在启动的时候,从类路径下 /META-INF/spring-factories获取指定的值。
  2. 将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置。
  3. 以前我们需要将自动配置的东西,现在SpringBoot通过上面两步帮我们做了。
  4. 整合JavaEE,解决方案和自动配置的东西都在 spring-boot-autoconfigure-2.7.9.jar 这个包下
  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器。
  6. 容器中也会存在非常多的 xxxxAutoConfiguration的文件,就是这些类给容器中导入了这个场景需要的所有组件,并自动配置,@Configuration ,JavaConfig
  7. 有了自动配置类,免去了我们手动编写配置的过程。
- 启动类
  • SpringApplication 这个类主要做了以下四件事:
  • 推断应用的类型是普通的项目还是Web项目
  • 查找并加载所有可用初始化器,设置到 initializers 属性中
  • 找出所有的应用程序监听器,设置到 listeners 属性中
  • 推断并设置main方法的定义类,找到运行的主类

五、yaml 语法讲解

(1)配置文件

SpringBoot 使用一个全局的配置文件,配置文件名称是固定的

  • application.properties
  • 语法结构:Key = value
  • application.yml
  • 语法结构:key:空格 value

配置文件的作用:修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了。

(2)yaml概述

YAML是“YAML Ain’t a Markup Language”(YAML不是一种标记语言)的递归缩写。 这种语言以数据作为中心,而不是以标记语言为重点!!

以前的配置文件,大多数都是使用 xml 来配置:比如一个简单的端口配置,对比一下传统的yamlxml

传统的xml配置:

<server>
   <port>8080</port>
</server>

yaml配置:

server:
  port: 8080

(3)yaml基本语法

说明:语法要求严格!

  1. 空格不能省略
  2. 以缩进来控制层级关系,只要是左边对齐的一列数据都是同一层级的
  3. 属性和值的大小写都是十分敏感的。

1、字面量:普通的值【数字,布尔值,字符串】

字面量直接写在后面就可以,字符串默认不用加上双引号或者单引号;

# K = V 普通的 key - value
name: yyt

注意:

  • “ ”双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思: 比如:name:“yyt \n hello” 输出:yyt 换行 hello
  • ‘’单引号,会转义特殊字符,特殊字符最终会变成和普通字符一样输出
    比如:name:“yyt \n hello” 输出:yyt \n hello

2、对象、Map(键值对)

#对象、Map格式
k:
  v1:
  V2:

在下一行来写对象的属性和值的关系,注意缩进。

student:
  name: yyt
  age: 18

行内写法:

student: {name: yyt,age: 18}

3、数组(List、set)

用 - 值表示数组中的一个元素,比如:

pets:
 - cat
 - dog
 - pig

行内写法:

pets: [cat,dog,pig]

4、修改 SPringBoot 的默认端口号

配置文件中添加,端口号的参数,就可以切换端口:

server:
  port: 8080

(4)通过绑定配置文件,注入值的方法(重要!!)

① 通过 yaml 注入配置文件,绑定值

  1. 在 springboot 项目中的 resources 目录下新建一个文件 application.yml。 在 Springboot 项目中application.propertiesapplication.yml同时存在时,两个文件都是有效的,但是优先级不同,application.properties 的优先级要高于application.yml,但在springboot中推荐使用 yaml文件。
  2. 编写一个实体类 Dog
  3. 直接在类中 使用 @Value 给bean注入属性值。
package com.yyt.springbootdemo.pojo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @author yyt
 * @version 1.0
 * @data 2023/3/31 17:58
 * @Project_Name SpringBootDemo
 * @Component 定义Spring管理Bean(也就是将标注@Component注解的类交由spring管理)
 * @Value() 直接使用注解进行赋值
 * @Data lombok方法,快速构造 有参无参构造,get、set方法,tostring()方法
 */
@Component
@Data
public class Dog {

//    狗狗的名字
    @Value("小五")
    private String name;

//    狗狗的年龄
    @Value("3")
    private Integer age;
}

4.在 SpringBoot 的测试类下给 Dog 类输出一下。

package com.yyt.springbootdemo;

import com.yyt.springbootdemo.pojo.Dog;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @Autowired 将类自动注入进来,自动装配的作用
 */

//单元测试
@SpringBootTest
class SpringBootDemoApplicationTests {

    @Autowired
    private Dog dog;

    @Test
    void contextLoads() {
        System.out.println(dog);
    }

}

5.结果成功输出,@Value注入成功!

SpringBoot全解_配置文件_12

6.继续编写一个较复杂的实体类,Person 类

package com.yyt.springbootdemo.pojo;

import lombok.Data;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author yyt
 * @version 1.0
 * @data 2023/3/31 18:01
 * @Project_Name SpringBootDemo
 */
@Component
@Data
public class Person {

    private String name;

    private Integer age;

    private Boolean happy;

    private Date birth;

    private Map<String,Object> maps;

    private List<Object> list;

    private Dog dog;
}

7.不同于上面的用 @Value 注入值的方法,这次,使用 yaml 配置的方法进行值的注入。

person:
  name: yyt
  age: 18
  happy: true
  birth: 2008/01/01
  maps: {k1: v1,k2: v2}
  list:
    - code
    - boy
    - food
  dog:
    name: 小高
    age: 3

8.通过上面 yaml配置的方式,已将 person 的对象所有值写好,接下来注入到 person 类中,就是添加注解 @ConfigurationProperties;

package com.yyt.springbootdemo.pojo;

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

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author yyt
 * @version 1.0
 * @data 2023/3/31 18:01
 * @Project_Name SpringBootDemo
 *
 * @ConfigurationProperties 作用:
 * 将配置文件中配置的每一个属性的值,映射到这个组件中;
 * 告诉SpringBoot 将本类中的所有属性和配置文件中相关的配置进行绑定
 * 参数 prefix = "person":将配置文件中的 person 下面的所有属性一一对应。
 */
@Component
@Data
@ConfigurationProperties(prefix = "person")
public class Person {

    private String name;

    private Integer age;

    private Boolean happy;

    private Date birth;

    private Map<String,Object> maps;

    private List<Object> list;

    private Dog dog;
}

9.接下来,去测试类中进行测试:

package com.yyt.springbootdemo;

import com.yyt.springbootdemo.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

//单元测试
@SpringBootTest
class SpringBootDemoApplicationTests {

    @Autowired
    private Person person;

    @Test
    void contextLoads() {
        System.out.println(person);
    }
}

10.查看结果:

SpringBoot全解_配置文件_13

② 通过加载指定的配置文件,绑定值

@PropertySource : 加载指定的配置文件; @ConfigurationProperties : 默认从全局配置文件中获得值;

  1. 在 resources 目录下新建一个 person.properties文件
name=yyt
  1. 然后 person类中指定加载 person.properties 文件,使用 @PropertySource 注解
package com.yyt.springbootdemo.pojo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author yyt
 * @version 1.0
 * @data 2023/3/31 18:01
 * @Project_Name SpringBootDemo
 * @PropertySource(value = "classpath:person.properties") 加载指定的配置文件
 */
@Component
@Data
@PropertySource(value = "classpath:person.properties")
public class Person {

 // 用 EL 表达式取出配置文件   
    @Value("${name}")
    private String name;

    private Integer age;

    private Boolean happy;

    private Date birth;

    private Map<String,Object> maps;

    private List<Object> list;

    private Dog dog;
}

六、JSR303 数据校验

Springboot 中可以用 @Validated 来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。

下面,写个注解,让 person类 中的 name 只能支持 Email 格式;

package com.yyt.springbootdemo.pojo;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import javax.validation.constraints.Email;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author yyt
 * @version 1.0
 * @data 2023/3/31 18:01
 * @Project_Name SpringBootDemo
 * @Validated:数据校验注解
 * @Email()只能支持 Email 格式,参数为错误提示。
 * */
@Component
@Data
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {

    @Email(message = "name 输入格式不正确,请输入邮箱格式!")
    private String name;

    private Integer age;

    private Boolean happy;

    private Date birth;

    private Map<String,Object> maps;

    private List<Object> list;

    private Dog dog;
}

输出:

SpringBoot全解_配置文件_14

使用数据校验,可以保证数据的正确性!

常见的参数:

@NotNull(message="名字不能为空")
private String userName;
@Max(value=120,message="年龄最大不能查过120")
private int age;
@Email(message="邮箱格式错误")
private String email;

空检查
@Null       验证对象是否为null
@NotNull    验证对象是否不为null, 无法查检长度为0的字符串
@NotBlank   检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.
@NotEmpty   检查约束元素是否为NULL或者是EMPTY.
    
Booelan检查
@AssertTrue     验证 Boolean 对象是否为 true  
@AssertFalse    验证 Boolean 对象是否为 false  
    
长度检查
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内  
@Length(min=, max=) string is between min and max included.

日期检查
@Past       验证 Date 和 Calendar 对象是否在当前时间之前  
@Future     验证 Date 和 Calendar 对象是否在当前时间之后  
@Pattern    验证 String 对象是否符合正则表达式的规则

.......等等
除此以外,我们还可以自定义一些数据校验规则

七、多环境配置及配置日志文件

1、多环境配置

① 多环境配置优点:

  • ⽅便应⽤程序的管理和维护:在不同环境下,我们可以灵活地配置应⽤程序的参数,例如⽇志级

别、调试模式等,⽅便应⽤程序的管理和维护。

  • 提⾼应⽤程序的可移植性:将应⽤程序的配置信息与代码分离,可以提⾼应⽤程序的可移植性,使

其更容易部署到不同的环境中。

  • 增强应⽤程序的安全性:通过多环境配置,我们可以将敏感信息(如密码、密钥等)存放在安全的

地⽅,例如配置⽂件中的加密部分或操作系统环境变量中,从⽽增强应⽤程序的安全性。

② 具体配置

在Spring Boot中,可以通过在application.propertiesapplication.yml⽂件中定义不同的属性来

配置多个环境。

  1. 在 src/main/resources目录下,创建 application-{profile}.propertiesapplication-{profile}.yml文件,其中 {profile}表示环境名称。例如:application-dev.yml 或 application-prod-yml.

SpringBoot全解_配置文件_15

  1. 在各个环境的配置文件中,可以定义与 application.properties 或 application.yml 中相同的属性,覆盖原有的默认值。
    application.yml (默认配置文件)
server:
  port: 8888

application-dev.yml(开发环境配置文件)

server:
  port: 8080

application-pro.yml(生产环境配置文件)

server:
  port: 8081

application-test.yml(测试环境配置文件)

server:
  port: 8082

3.在启动应用程序时,可以通过设置 spring.profiles.active属性来指定要使用的环境名称。
application.yml

server:
  port: 8888
spring:
  profiles:
    active: dev  # 启用 application-dev.yml 的配置

如果不指定 spring.profiles.active属性,则会默认使用 application.properties 或 application.yml中的配置。

4、结果展示:

SpringBoot全解_配置文件_16


启用的端口号就为 application-dev.yml的配置。

2、日志文件配置

① 概念

日志(log)是指在软件或系统运⾏过程中记录下来的事件或状态信息。在软件或系统开发中,日志

是⼀种非常重要的调试⼯具,可以帮助开发者了解程序或系统的运⾏状态,从而快速地定位和解决问

题。

日志可以包含各种信息,例如程序或系统运⾏的时间、事件类型、发⽣时间、相关参数、异常信

息、警告信息等。通过记录这些信息,开发者可以根据需要对⽇志进⾏分析和处理,以了解程序或系统

在运⾏中发⽣的问题和异常情况。

② 功能

  1. 调试和排错:通过分析⽇志信息,可以快速定位和解决程序或系统的问题,提⾼开发效率。
  2. 监控和分析:通过对⽇志信息的监控和分析,可以了解程序或系统的运⾏情况,及时发现和解决潜

在问题,提⾼系统的稳定性和可靠性。

  1. 安全性和审计:通过对⽇志信息的记录和分析,可以跟踪和审计系统中的操作⾏为,提⾼系统的安

全性和防⽌不当操作。

③ 日志的级别

在 Springboot 项目中日志一共有 6 个级别,分别从低到高为 trace<debug<info<warn<error<fetal.

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

④ Springboot 日志配置

在 springboot 中是内置了日志框架的,所以只要运行 springboot 日志就会被打印在控制台上。但是输出的日志并不是开发者自己定义和打印的。而且,控制台上的日志是不能保存的,所以从以上两个角度出发,可以提出两个问题:

  1. 开发者自定义打印日志。
  2. 日志的持久化

日志的配置:在 application.yml 中配置:

logging:
  file:
    name: server.log                         # 输出的日志文件的名称(xxx.log)
    path: /computer/springboot-web-demo      # 输出的日志文件存放的目录(一般于项目目录相同,便于查看)
  level:
    com.yyt.controller: debug                # 日志级别 可以直接全局定义,也可以包名局部定义
  logback:
    rollingpolicy:                           # 日志滚动保存
      max-file-size: 4KB                     # 最大文件4KB,但日志文件大于4KB时,再次新建日志文件。
      file-name-pattern: server.%d{yyyy-MM-dd}.%i.log  # 新建文件的命名格式

通过以上配置,提出的两个问题都可以解决。在yml中,开发者可以自定义打印日志,可以使用logging.file.path对输出的日志文件进行持久化。

⑤ 日志的使用 (举例)

5.1 获取日志对象,打印日志(使用对象的配置)
  1. 在需要进行打印日志的操作(controller)下进行对日志对象的获取。在 controller包 下新建 PageController 。
package com.yyt.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author yyt
 * @ProjectName springboot-demo
 * @createTime 2023/3/28
 * @Desc TODO
 */

@Controller
public class PageController {

    // 获取日志对象
    private static final Logger logger= LoggerFactory.getLogger(PageController.class);

    // 每次提交/,index请求的时候生成日志文件。
    @GetMapping(value = {"/","/index"})
    public String index(){
        logger.debug("debug logging~~~");
        logger.info("info logging~~~");
        logger.warn("warn logging~~~");
        logger.error("error logging~~~");
        return "login";
    }
}

2、启动项目,输入 http://localhost:8080/,控制台输出,并生成日志文件。

SpringBoot全解_spring_17

SpringBoot全解_配置文件_18

5.2 Lombok注解 @slf4j,打印日志

通过在类上增加 @slf4j注解引入日志框架,将会获得一个全局的 log对象。效果一样,只不过不用获取对象。

package com.yyt.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;


/**
 * @author yyt
 * @ProjectName springboot-demo
 * @createTime 2023/3/28
 * @Desc TODO
 */

@Controller
@Slf4j       //引入日志框架
public class PageController {

    @GetMapping(value = {"/","/index"})
    public String index(){
        log.debug("debug logging~~~");
        log.info("info logging~~~");
        log.warn("warn logging~~~");
        log.error("error logging~~~");
        return "login";
    }
}