Spring boot快速入门(一)

· Spring Boot简介及快速搭建

· Spring Boot的配置和自动配置原理

· Spring Boot热部署与日志

· Spring Boot与Web开发

· Spring Boot集成MyBatis

· Spring Boot启动原理源码剖析

· Spring Boot自定义starters

Spring boot简介及快速搭建

1. 简介
官网:https://spring.io/projects/spring-boot

SpringBoot基于Sping4.0设计,是由Pivotal公司提供的框架。

SpringBoot基于Spring开发,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程,其设计目的是用来简化Spring应用的初始搭建以及开发过程。怎么简化的呢?就是通过提供默认配置等方式让我们更容易使用。

SpringBoot本身并不提供Spring框架的核心特性以及拓展功能,也就是说,它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。

关于SpringBoot有一句很出名的话就是约定大约配置。采用SpringBoot可以大大的简化开发模式,它集成了大量常用的第三方库配置,所有你想集成的常用框架,它都有对应的组件支持,例如Redis、MongoDB、Dubbo、kafka、ES等。SpringBoot应用中这些第三方库几乎可以零配置地开箱即用,大部分的SpringBoot应用都只需要非常少量的配置代码,开发者能更加专注于业务逻辑。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。

在这里插入图片描述
优点
快速构建一个独立的Spring应用程序;
嵌入的Tomcat、Jetty或者Undertow,无需部署WAR文件;
提供starter POMs来简化Maven配置和减少版本冲突所带来的问题;
对Sping和第三方库提供默认配置,也可以修改默认值,简化框架配置;
提供生产就绪型功能,如指标、健康检查和外部配置;
无需配置XML,无代码生成,开箱即用;

2. Why SpringBoot?
SpringBoot简化了基于Spring开发这只是最直观的一方面;还有另一个方面:也更得力于各微服务组件的支持(起初是Netflix移植到Spring),Spring,这也是谈SpringBoot必谈微服务的原因。可以说是Spring Cloud带动了SpringBoot,SpringBoot成就了SpringCloud。

在这里插入图片描述

微服务

在这里插入图片描述

快速开始SpringBoot Hello World

前置知识要求
SSM框架使用经验
熟练使用Maven进行项目构建和依赖管理
熟练使用Idea或者Eclipse

环境要求
Spring Boot RELEASE 需要Java8,并且与Java15兼容。还需要Spring Framework 5.2.10.RELEASE或者更高版本。

构建工具的支持
Maven 3.3+

开发工具
eclpise
Idea 2018+(别忘了配置Maven,Jdk)

创建一个Maven工程

项目中引入依赖

 		<!--继承springboot父项目-->   
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

	<dependencies>
		<!--引入springboot的web支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

建包并创建控制器

在这里插入图片描述

HelloController.java如下:

package com.jm.controllers;

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

@RestController
@RequestMapping("/hello")
public class HelloController {

    @RequestMapping("/world")
    public String sayHi(){
        return "hello world";
    }
}

标记SpringBoot启动类

Application如下:

package com.jm;

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

@SpringBootApplication //标记成SpringBoot启动类
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

启动启动类

启动类有且仅有一个;
在这里插入图片描述

在这里插入图片描述
查看效果

浏览器输入:http://localhost:8080/hello/world 回车
在这里插入图片描述
Tips:

在resources/application.properties中添加如下代码,可更改指定的端口号和项目虚拟路径

#端口
server.port=8088
#项目虚拟路径
server.servlet.context-path= /jm

在Maven选项卡中,双击package会在target文件下生成项目的jar,可直接在jar文件路径下,使用java -jar 文件名.jar运行。注意,要先在项目pom.xml文件下添加:

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

否则,运行jar会提示需要有主清单属性

在这里插入图片描述
是jar包里META-INF/MANIFEST.MF文件。

在这里插入图片描述

在这里插入图片描述
代码说明

在这里插入图片描述
启动类@SpringBootApplication会解析配置类Configuration的时候,会解析ComponentScan包路径,如果没有读取到,会将当前配置类所在的包当作是basePackages。解析ComponentScanAnnotationParser.java拿到basePackages属性的值,如果没有拿到就会设置当前配置类所在的包的路径给basePackages。

在这里插入图片描述
所以,SpringBootApplication启动类最好放在需要扫描包的根目录下,或者说放在所有Bean的顶层目录中。
配置文件采用约定大于配置的方式。 一定要放在resources根目录下,一定要叫application.properties或application.yml。

    <!-- 引入了父Maven项目,继承父Maven项目所有的配置信息
       spring-boot-starter-parent又引入了一个父Maven项目
       <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.5.2</version>
      </parent>
      spring-boot-dependencies  帮我们管理了SpringBoot应用中所有的依赖的版本。所有的版本号都在这里维护
      以后我们导入已有依赖就不需要写版本号了,它帮我们解决第三方库直接的版本冲突问题
      SpringBoot的版本仲裁中心
     -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
    </parent>

    <!--
         starter 场景启动器:不同的场景启动器维护了对应的所有的依赖,从而简化Maven文件的书写
         spring-boot-starter-web: 使用 Spring MVC 构建 Web(包括 RESTful)应用程序
         使用 Tomcat 作为默认的嵌入式容器
    -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <!-- 部署springboot的插件,只有加了这个插件,当运行 java -jar xxxx.jar 才能正常启动-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

Spring Boot的配置文件和自动配置原理

1.使用Spring Initializer快速创建spring项目
在这里插入图片描述
1、继承关系 SpringBoot的Maven项目
创建父项目:
在这里插入图片描述
一个都不需要勾选
在这里插入图片描述
新建的父项目如下:
在这里插入图片描述
没有src之类的文件夹,只有pom.xml文件提供给子模块去继承的。

子项目创建:

在这里插入图片描述
举例选Spring Web
在这里插入图片描述
复制父项目pom.xml里的:

    <groupId>com.jm.springboot</groupId>
    <artifactId>springboot_parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>

把子项目pom.xml 里的内容替换掉,如下:

    <parent>
        <groupId>com.jm.springboot</groupId>
        <artifactId>springboot_parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

这样才是一个正常的继承关系。
spring_initializr --> springboot_parent --> spring-boot-starter-parent

2.自定义SpringApplication
如果SpringApplication默认设置不符合您的喜好,则可以创建一个本地实例并对其进行自定义。例如,关闭横幅可以编写:

@SpringBootApplication
public class SpringInitializrApplication {

    public static void main(String[] args) {

        SpringApplication app = new SpringApplication(SpringInitializrApplication.class);
        app.setBannerMode(Banner.Mode.OFF);//关闭springboot启动横幅
        app.run(args);
    }

}

懒加载初始化
在resource/application.properties中配置:

spring.main.lazy-initialization=true

将SpringBoot容易设置为初始化懒加载:所有的Bean在Spring初始化时将不会创建Bean,而是在使用的时候才会去创建,和Bean的懒加载类似。

3.配置文件的使用
在这里插入图片描述
在这里插入图片描述
配置文件加载顺序
spring-boot-starter-parent中有:

        <includes>
          <include>**/application*.yml</include>
          <include>**/application*.yaml</include>
          <include>**/application*.properties</include>
        </includes>

加载优先级自上而下
配置有的以主优先,没有的就互补配置

外部约定配置文件加载顺序
springboot启动还会扫描以下位置的application.properties或者application.yml文件作为SpringBoot默认配置文件
⬇️
1.classpath根目录下的
在这里插入图片描述
2.classpath根config/在这里插入图片描述
3.项目根目录(实际开发不会去用)在这里插入图片描述

如果当前项目是继承/耦合关系maven项目的话,项目根目录=父maven项目的根目录。
4.项目根/config(实际开发不会去用)

在这里插入图片描述
5.直接子目录/config
在这里插入图片描述
或者

java -jar helloworld-1.0-SNAPSHOT.jar --server.port=8087
java -jar helloworld-1.0-SNAPSHOT.jar --spring.config.location=D:\config/

注意结尾用“\“。
⬇️
优先级由低到高,高优先级的配置会覆盖低优先级的配置;互补配置。
官网:
在这里插入图片描述
Profile文件的加载
Profile的意思是配置,对于应用程序来说,不同的环境需要不同的配置。

SpringBoot框架提供了多profile的管理功能,我们可以使用profile功能来区分不同环境的配置。

1.多profile文件
1.Spring官方给出的语法规则是application-{profile}. properties(.yaml/yml)。

2.如果需要创建自定义的properties文件时,可以用application-xxx.properties的命名方式。

2.激活指定profile
在这里插入图片描述
在这里插入图片描述
**所有配置文件按以下顺序考虑:**优先级从低到高
1.打包在jar中配置文件
2.打包在jar中profile
3.打包的jar之外的配置文件
4.打包的jar之外的profile
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
配置文件读取方式 低­­­–>高

  1. @PropertySource@Configuration类上的注释。请注意,Environment在刷新应用程序上下文之前,不会将此 类属性源添加到中。现在配置某些属性(如logging.*和spring.main.*在刷新开始之前先读取)为时已晚。
    a. 会和约定的配置文件形成互补
    b. 一定要指定.properties配置
@PropertySource("classpath:appSource.properties")
  1. 默认属性(通过设置指定SpringApplication.setDefaultProperties)。
    a. 会和约定的配置文件形成互补
 public static void main(String[] args) throws IOException {
  SpringApplication springApplication = new SpringApplication(ExternConfigurationApplication.class);

// 创建Properties
Properties properties = new Properties();
// 通过当前类的ClassLoader
 InputStream is= ExternConfigurationApplication.class.getClassLoader()
 .getResourceAsStream("app.properties");
 // 将输入流读取成properties
 properties.load(is);

springApplication.setDefaultProperties(properties);
springApplication.run(args);
}
  1. 配置数据(例如application.properties文件)
    a. 约定配置文件
  2. 操作系统环境变量。
    a. 会使约定配置文件失效
    b. 1.idea
    在这里插入图片描述
    c. 2.windows
set spring.config.location=D:\config/
java ‐jar 03_extern_configuration‐0.0.1‐SNAPSHOT.jar
  1. Java系统属性(System.getProperties())。
    a. 会使约定配置文件失效
    b. idea
    在这里插入图片描述
    c. 命令行java属性
java ‐Dspring.config.location=D:\config\application‐java.properties ‐jar 03_extern_configuration‐0.0.1‐SNAPSHOT.jar
  1. 的JNDI属性java:comp/env。
  2. ServletContext 初始化参数。
ServletContext 的配置标签需要写到 web‐app (根标签)中 ,具体如下:
 <context‐param> 
  <param‐name>spring.config.location</param‐name> 
   <param‐value>xxx.properties</param‐value> 
 </context‐param>
  1. ServletConfig 初始化参数。
ServletConfig 的配置标签需要写到 Servlet 标签中,标签如下: 
 <init‐param> 
  <param‐name>spring.config.location</param‐name> 
   <param‐value>xxx.properties</param‐value> 
 </init‐param>
  1. 来自的属性SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的嵌入式JSON)。
  2. 命令行参数。
    a. 会使约定配置文件失效
java ‐jar configuration_file‐0.0.1‐SNAPSHOT.jar ‐‐spring.config.location=D:/application.properties
  1. properties测试中的属性。可用于测试应用程序的特定部分@SpringBootTest的测试注释和注释。
  2. @TestPropertySource 测试中的注释。
    a. 用在单元测试上的
@TestPropertySource("classpath:appSource.properties")
  1. $HOME/.config/spring­boot当devtools处于活动状态时,目录中的Devtools全局设置属性。

配置文件值注入
将YAML映射到属性

  • 字面量:普通的值(数字,字符串,布尔)
    k: v:字面直接来写;
    字符串默认不用加上单引号或者双引号;
    “”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
    name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi
    ‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
    name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi

  • 对象、Map(属性和值)(键值对):
    k: v:在下一行来写对象的属性和值的关系;注意缩进
    对象还是k: v的方式

friends: 
 lastName: zhangsan 
 age: 20

行内写法:

friends: {lastName: zhangsan,age: 18}
  • 数组(List、Set):
    用- 值表示数组中的一个元素
pets: 
 ‐ cat 
 ‐ dog 
 ‐ pig

行内写法

pets: [cat,dog,pig]

配置文件

person: 
 lastName: hello 
 age: 18 
 boss: false 
 birth: 2017/12/12 
 maps: {k1: v1,k2: 12} 
 lists: 
  ‐ lisi 
  ‐ zhaoliu 
   dog: 
   name: 小狗 
   age: 12

javaBean:

 /** 
  * 将配置文件中配置的每一个属性的值,映射到这个组件中 
  * @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定; 
   * prefix = "person":配置文件中哪个下面的所有属性进行一一映射 
   *  
   *  只有这个组件是容器中的组件,才能容器提供的@ConfigurationProperties功能; 
   *  
   * / 
   @Component 
    @ConfigurationProperties(prefix = "person") 
    public class Person { 
    private String lastName; 
    private Integer age; 
    private Boolean boss; 
    private Date birth; 
    private Map<String,Object> maps; 
    private List<Object> lists; 
    private Dog dog;

我们可以导入配置文件处理器,以后编写配置就有提示了

<!‐‐导入配置文件处理器,配置文件进行绑定就会有提示‐‐> 
<dependency> 
<groupId>org.springframework.boot</groupId> 
<artifactId>spring‐boot‐configuration‐processor</artifactId> 
<optional>true</optional> 
</dependency>

在这里插入图片描述
properties配置文件在idea中默认utf-8可能会乱码
调整
在这里插入图片描述
松散绑定:

user: 
 USERNAME: 徐庶 
user:
 userName: 徐庶 
user: 
 user_name: 徐庶 
user: 
 user‐name: 徐庶 
 以上4种命名是可以自动绑定bean属性 User.username

@Value获取值和@ConfigurationProperties获取值比较
在这里插入图片描述
配置文件yml还是properties他们都能获取到值;

使用场景
如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;
如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

3、配置文件注入值数据校验

@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
        /**
        * <bean class="Person">
         * <property name="lastName" value="字面量/${key}从环境变量、配置文件中获取值/#
         {SpEL}"></property>
         * <bean/>
         */
        //lastName必须是邮箱格式
        @Email
        //@Value("${person.last‐name}")
        private String lastName;
        //@Value("#{11*2}")
        private Integer age;
        //@Value("true")
        private Boolean boss;
        private Date birth;
        private Map<String,Object> maps;
        private List<Object> lists;
        private Dog dog;
  • @PropertySource:加载指定的配置文件;
    在这里插入图片描述
  • @ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;
    Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;
    想让Spring的配置文件生效,加载进来;@ImportResource标注在一个配置类上
@ImportResource(locations = {"classpath:beans.xml"}) 
导入Spring的配置文件让其生效

配置文件占位符
1、随机数

${random.value}、${random.int}、${random.long} 
${random.int(10)}、${random.int[1024,65536]}

2、占位符获取之前配置的值,如果没有可以是用:指定默认值

person.last‐name=张三${random.uuid} 
person.age=${random.int} 
person.birth=2017/12/15 
person.boss=false 
person.maps.k1=v1 
person.maps.k2=14 
person.lists=a,b,c 
person.dog.name=${person.hello:hello}_dog 
person.dog.age=15

版权声明:本文为maoqiudad原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。