SpringBoot详解

前言

所有的技术框架的发展似乎都遵循了一条主线规律:

  1. 从一个复杂应用场景衍生一种规范框架, 人们只需要进行各种配置而不需要自己去实现它, 这时候强大的配置功能成了优点;
  2. 发展到一定程度之后, 人们根据实际生产应用情况, 选取其中实用功能和设计精华, 重构出一些轻量级的框架;
  3. 之后为了提高开发效率, 嫌弃原先的各类配置过于麻烦, 于是开始提倡 “约定大于配置″, 进而衍生出一些一站式的解决方案。
    这就是 Java 企业级应用 ->J2EE-> spring-> spring boot 的过程。

一、SpringBoot 是什么?

1.1、概念

  • SpringBoot 是一个 javaweb 开发的框架。
  • 对比于其他 Javaweb 框架,更简化开发,约定大于配置。

1.2、目的

  • 让大家更容易使用 spring,更容易集成各种常用的中间件、开源软件。
  • SpringBoot 基于 Spring 开发, SpringBoot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。
  • SpringBoot 不是用来替代 spring 的解决方案,而是和 spring 框架紧密结合提升 spring 开发者体验的工具。

1.3、什么是微服务

  • 微服务是一种架构风格, 它要求我们在开发一个应用的时候, 这个应用必须构建成一系列小服务的组合; 可以通过 http 的方式进行互通。
  • MVC 架构,MVVM 架构,微服务架构。
  • 微服务架构, 就是把每个功能元素独立出来。把独立出来的功能元素的动态组合, 需要的功能元素才去拿来组合, 需要多一些时可以整合多个功能元素。
  • 所以微服务架构是对功能元素进行复制, 而没有对整个应用进行复制。

优点:1. 节省了调用资源。2. 每个功能元素的服务都是一个可替换的、可独立升级的软件代码。

1.4、单体应用架构

  • 单体应用架构 (all in one) 是指,我们将一个应用的中的所有应用服务都封装在一个应用中;
  • 无论是 ERP、CRM 或是其他什么系统看,都把数据库访问,web 访问,等等各个功能放到一个 war 包内。

优点:易于开发和测试,方便部署;当需要扩展时,只需要将 war 复制多份, 然后放到多个服务器上, 再做个负载均衡就可以了。
缺点:修改一个非常小的地方, 都需要停掉整个服务, 重新打包部署这个应用 War 包;对于一个大型应用,如何维护,如何分工合作都是问题。

1.5、如何构建微服务

二、SpringBoot 原理

2.1、pom.xml

  1. spring-boot-dependencie:核心依赖在父工程中。大部分依赖的版本都是在父工程中管理着,我们拿过来调用即可,因此我们引用一些依赖时不需要指定版本。并且父工程中已经帮我们配置好资源过滤和一些插件。

2.2、启动器

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  1. 启动器其实就是 springboot 的启动场景,比如 spring-boot-starter-web 启动器会帮我们自动导入 web 环境所有依赖。
  2. springboot 会将所有的功能场景,都变成一个个启动器。
  3. 我们要使用什么功能,只需要找到对应的启动器就可以了即 starter

2.3、主程序

2.3.1、注解

@SpringBootApplication

  1. @SpringBootConfiguration:springboot 的配置。
  2. @EnableAutoConfiguration:自动导入配置。
    1. @AutoConfigurationPackage:自动配置包。
      • @Import({Registrar.class}):自动配置包注册。
    2. @Import({AutoConfigurationImportSelector.class}):自动配置导入选择器。(自动导包的核心)
  3. @ComponentScan():扫描当前主启动类同级的包。(扫描的包到 Registrar.class 注册)

自动导包的核心 AutoConfigurationImportSelector 类:选择了什么东西
AutoConfigurationImportSelector 类中的方法:

// 1.获得自动配置实体(调用“获取所有候选配置”的方法获取实体)。
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata)
// 2.获取所有候选配置(候选配置是哪些配置)。
List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes){
   
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
}
// 3.候选配置是所有标注@EnableAutoConfiguration注解的类下的所有配置。(即获取主启动类下的所有配置)
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
   
        return EnableAutoConfiguration.class;
    }
// 4.获取所有的配置从哪里来,上面第二个方法调用了loadFactoryNames方法
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
   
        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }
// 5.loadFactoryNames方法调用了loadSpringFactories方法
// 6.loadSpringFactories方法从项目资源和系统资源中获取配置文件
classLoader.getResources("META-INF/spring.factories") ClassLoader.getSystemResources("META-INF/spring.factories")

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

// 遍历所有的资源,封装成properties供我们使用
Properties properties = PropertiesLoaderUtils.loadProperties(resource);

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

详细步骤

  1. springboot 在启动的时候, 从类路径下 / META-INF/spring.factories 获取指定的值。
  2. 将这些自动配置的类导入容器, 自动配置就会生效, 帮我进行自动配置。
  3. 以前我们需要自动配置的东西, 现在 springboot 帮我们做了。
  4. 整合 javaEE, 解决方案和自动配置的东西都在 spring-boot-autoconfigure-2.2.0.RELEASE.jar 这个包下。
  5. 它会把所有需要导入的组件, 以类名的方式返回, 这些组件就会被添加到容器中。
  6. 容器中也会存在非常多的 XXXAutoConfiguration 的文件 (@Bean), 就是这些类给容器中导入了这个场景需要的所有组件并自动配置。@Configuration(JavaConfig)
  7. 有了自动配置类, 免去了我们手动编写配置文件的工作。

2.3.2、Run 方法

main 方法中的 run 方法启动会开启一个服务。

@SpringBootApplication
public class SpringbootWeb01Application {
   
    public static void main(String[] args) {
   
        // 该方法返回一个ConfigurableApplicationContext对象
        // 参数一:应用入口的类, 参数二:命令行参数
        SpringApplication.run(SpringbootWeb01Application.class, args);
    }
}

2.3.3、SpringApplication.run 分析

主要两部分

  • 一是 SpringApplication 的实例化。
  • 二是 run 方法的执行。

2.3.4、SpringApplication 类主要做了四件事情

  • 判断应用的类型是普通项目还是 web 项目。(普通项目直接就结束了,web 项目可以一直启动)
  • 查找并加载所有可用初始化器,设置到 initializers 属性中。
  • 查找所有的应用程序监听器,设置到 listeners 属性中。(获取上下文处理 bean)
  • 推断并设置 main 方法的定义类,找到运行的主类。

2.4、自动装配再理解

springboot 配置文件能够配置的东西都有一个固有的规律:
他们都有对应的 xxxAutoConfiguration 配置类,这个配置类都会绑定一个 xxxProperties 类,xxxProperties 类和 springboot 的配置文件绑定;这样我们就可以在 springboot 配置文件中自定义配置了。

2.4.1、自动装配原理再理解

  1. springboot 启动会加载大量的自动配置类。
  2. 我们要看我们需要的功能有没有在 springboot 默认写好的自动配置类中。
  3. 我们看这个自动配置类中配置了哪些组件。(不存在就需要全部手动写,如果存在我们就不需要再手动配置;也可以自定义配置覆盖默认的配置)
  4. 给容器中自动配置类添加组件时,会从 xxxProperties 类中获取相应的属性。我们只需要在 springboot 配置中指定这些属性就可以了。
  • xxxAutoConfiguration:自动配置类(给容器中添加组件)
  • xxxProperties:封装配置文件中的属性

2.5、自动配置类中存放了大量的配置没有全部都生效的原因

spring 的底层注解:根据不同的条件,来判断当前配置或者类是否生效。@Conditionalxxx

三、SpringBoot

3.1、yaml 语法

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

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

全局配置文件的作用:修改 SpringBoot 自动配置的默认值,它会在底层帮我们自动配置。

3.1.1、基本语法

# 对象
student:
  name: 'zs'
  age: 12
# 对象的行内写法
student1: {
   name: 'zs',age: 12}
# 数组
pets:
  - cat
  - dog
  - pig
# 数组行内写法
pets1: [cat,dog,pig]

3.1.2、@ConfigurationProperties绑定 application.yml 配置的属性(属性需要 set 方法才能取值)

/*
ConfigurationProperties作用
将yml配置文件中配置的每个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和yml配置文件中相关的配置进行绑定;
参数prefix="person":将yml配置文件中的person下面的所有属性和本类属性对应。
(只有这个组件是容器中的组件,才能使用容器提供的ConfigurationProperties功能)
 */
 // 可以直接拿到复杂类型的值
@Component
@ConfigurationProperties(prefix = "person")
@Data
public class Person {
   
    private String name;
    private Integer age;
    private Boolean flag;
    private Date birth;
    private Map<String,Object> map;
    private List<Object> list;
    private Dog dog;
}
// application.yml
person:
  name: zs
  age: 12
  flag: false
  birth: 2021/04/20
  map: {
   k1: v1,k2: v2}
  list: [code,music,girl]
  dog:
    name: 旺财
    age: 3
<!--spring-boot-configuration-processor依赖可以在yml配置时给出提示-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

3.1.3、@Configuration@Value配合取值(没有 set 方法也可以取值)

// 复杂类型不能用@Value直接取值
@Configuration
@Data
public class Person {
   
    @Value("${person222.name}")
    private String name;
    @Value("${person222.age}")
    private Integer age;
    @Value("${person222.flag}")
    private Boolean flag;
    @Value("${person222.birth}")
    private Date birth;
    private Map<String,Object> map;
    private List<Object> list;
    private Dog dog;
}
// application.yml
person222:
  name: zs
  age: 12
  flag: false
  birth: 2021/04/20
  map: {
   k1: v1,k2: v2}
  list: [code,music,girl]
  dog:
    name: 旺财
    age: 3

3.1.4、@PropertySource读取 xxx.properties 配置(没有 set 方法也可以取值)

@Component
@PropertySource(value = "classpath:test.properties")//可以这样配置@PropertySource({"classpath:test.properties"})
@Data
public class Person {
   
    // SPEL表达式取出配置文件的值
    @Value("${name}")
    private String name;
    @Value("${age}")
    private Integer age;
    private Boolean flag;
    private Date birth;
    private Map<String,Object> map;
    private List<Object> list;
    private Dog dog;
}
// test.properties
name=zhangsan
age=13

3.1.5、松散绑定

yml 配置属性的 - 可以和实体属性的驼峰对应绑定

@Component
@ConfigurationProperties(prefix = "person")
@Data
public class Person {
   
    private String firstName;
}
// application.yml
person:
  first-name: zs

3.1.6、JSR303 数据校验

@Component
@ConfigurationProperties(prefix = "person")
@Data
@Validated //数据校验
public class Person {
   
    @Email(message="邮箱格式错误")
    private String name;
}

HibernateValidator 是 BeanValidation 的参考实现;HibernateValidator 提供了 JSR 303 规范中所有内置 constraint 的实现;和附加的 constraint

HibernateValidator 附加的 constraint

3.2、多环境配置和配置文件位置

3.2.1、配置文件位置

3.2.2、多环境配置切换

四、SpringBootWeb 开发

4.1、SpringBootWeb 开发需要解决的问题

  • 导入静态资源
  • 首页定制
  • 模板引擎 Thymeleaf
  • 装配扩展 springMVC
  • 增删改查
  • 拦截器
  • 国际化
  • SpringMvcConfig 配置
  • 错误页定制

4.2、静态资源导入

  1. 在 SpringBoot,可以使用以下方式处理静态资源。
    • webjars 文件夹下:映射访问 localhost:8080/webjars/
    • public 文件夹,static 文件夹,resources 文件夹下和 /**(即 classpath:):映射访问 localhost:8080/
  2. 文件夹优先级(即访问一个静态文件先查找 resources 文件夹):resources>static>public

4.3、首页定制和图标定制

4.3.1、首页定制

  1. 首页名称需要是 index.html
  2. index.html 放在静态资源文件夹下(resources,static,public)
  3. localhost:8080 / 就可以访问到 index.html 页面

4.3.2、老版本 springboot 支持 (2.1.7)

  1. favicom.ico 图标放在 static 文件夹下。
  2. 配置关闭默认的图标 spring.mvc.favicon.ico.enabled=false

4.4、模板引擎 Thymeleaf

4.4.1、thymeleaf 使用步骤

  1. 导入 jar 包
<!--thymeleaf,我们都是基于3.x开发;2.x项目会报错-->
<dependency>
 <groupId>org.thymeleaf</groupId>
 <artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
 <groupId>org.thymeleaf.extras</groupId>
 <artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
  1. ThymeleafProperties 默认配置
  2. controller 跳转
  3. xxx.html 放在 templates 文件夹下

    xxx.html 页面上使用 thymeleaf 语法,需要引入头文件
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>首页</title>
</head>
<body>
<div th:text="${msg}"></div>
</body>
</html>

4.4.2、thymeleaf 语法

  1. html和css的元素都可以被thymeleaf接管。
  2. ${}用来取值,
  3. @{}用来表示url。
  4. 消息文字的表达式#{} 。
  5. 提取公共页面。
    • th:fragment=”siderbar”

4.5、扩展 springMVC

package com.sywl.config;
import org.springframework.context.annotation.Configuration;
import org.springframework
  • 13
    点赞
  • 148
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值