什么是 Spring BootSpring Boot 是所有基于 Spring Framework 5.0 开发的项目。Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序,并且尽可能减少你的配置文件。
设计目的: 用来简化 Spring 应用的初始搭建以及开发过程。
从最根本上来讲,Spring Boot 就是一些库的集合,它能够被任意项目所使用。它使用 “习惯优于配置” (项目中存在大量的配置,此外还内置一个习惯性的配置)的理念让你的项目快速运行起来。spring boot 其实不是什么新的框架,它默认配置了很多框架的使用方式,就像 maven 整合了所有的 jar 包,spring boot 整合了所有的框架,总结一下及几点:
为所有 Spring 开发提供一个更快更广泛的入门体验 零配置。无冗余代码生成和 XML 强制配置,遵循“约定大于配置” 集成了大量常用的第三方库的配置, Spring Boot 应用为这些第三方库提供了几乎可以零配置的开箱即用的能力 提供一系列大型项目常用的非功能性特征,如嵌入服务器等 1、SpringBoot 的特点 为基于 Spring 的开发提供更快的入门体验 开箱即用,没有代码生成,也无需 XML 配置。同时也可以修改默认值来满足特定的需求 提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、外部配置等 SpringBoot 不是对 Spring 功能上的增强,而是提供了一种快速使用 Spring 的方式 2、SpringBoot 的核心功能 起步依赖本质上是一个 Maven 项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。
简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
Spring Boot 的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定 Spring 配置应该用哪个,不该用哪个。该过程是 Spring 自动完成的。
SpringBoot 快速入门 1、代码实现 ① 创建 Maven 工程并在pom.xml
添加 SpringBoot 的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.atguigu</groupId > <artifactId > springboot_demo</artifactId > <version > 1.0-SNAPSHOT</version > <parent > <artifactId > spring-boot-starter-parent</artifactId > <groupId > org.springframework.boot</groupId > <version > 2.1.6.RELEASE</version > </parent > <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > </dependencies > </project >
添加 web 起步包,框架会自动导入其它相关包
也可以找到 tomcat 和 web
② 编写 SpringBoot 引导类
要通过 SpringBoot 提供的引导类起步,SpringBoot 才可以进行访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.atguigu;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class Application { public static void main (String[] args) { SpringApplication.run(Application.class, args); } }
③ 编写 Controller
在引导类同级包或者子级包中创建StartController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.atguigu.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/get") public class StartController { @RequestMapping("/hello") public String hello () { return "Hello SpringBoot!" ; } }
④ 测试
执行 SpringBoot 起步类的main
方法,控制台打印日志如下
浏览器访问:http://localhost:8080/get/hello
可以看到输出结果
这样就省去了 springmvc.xml 的配置
2、SpringBoot 工程热部署 我们在开发中反复修改类、页面等资源,每次修改后都是需要重新启动才生效,这样每次启动都很麻烦,浪费了大量的时间
因此我们希望可以在修改代码后不重启就能生效
① 在 pom.xml 中添加如下配置就可以实现这样的功能,我们称之为热部署
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-devtools</artifactId > </dependency > <build > <plugins > <plugin > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-maven-plugin</artifactId > </plugin > </plugins > </build >
② 开启 Intellij IEDA 自动编译,需要对 IDEA 进行自动编译的设置,如下:
Shift+Ctrl+Alt+/
,选择 Registry
勾选 compiler.automake.allow.when.app.running
结束
3、使用 idea 快速创建 SpringBoot 项目
通过 idea 快速创建的 SpringBoot 项目的 pom.xml 中已经导入了我们选择的 web 的起步依赖的坐标
SpringBoot 原理分析 1、起步依赖原理分析 ① 分析 spring-boot-starter-parent 按住 Ctrl 点击pom.xml
中的spring-boot-starter-parent
,跳转到了spring-boot-starter-parent
的 pom.xml`,xml 部分配置如下:
按住 Ctrl 点击pom.xml
中的spring-boot-starter-dependencies
,跳转到了spring-boot-starter-dependencies
的pom.xml
,xml 部分配置如下
从上面的spring-boot-starter-dependencies
的pom.xml
中我们可以发现,一部分坐标的版本、依赖管理、插件管理已经定义好,所以我们的 SpringBoot 工程继承spring-boot-starter-parent
后已经具备版本锁定等配置了(不会出现版本冲突的问题)。所以起步依赖的作用就是进行依赖的传递。
② 分析 spring-boot-starter-web 不是所有的 jar 都传递,需要指定,用到哪个 jar 包,导入哪个 jar 包
按住 Ctrl 点击 pom.xml 中的spring-boot-starter-web
,跳转到了spring-boot-starter-web
的 pom.xml,xml 部分配置如下
从上面的spring-boot-starter-web
的 pom.xml 中我们可以发现,spring-boot-starter-web
就是将 web 开发要使用的spring-web
、spring-webmvc
等坐标进行了“打包”,这样我们的工程只要引入spring-boot-starter-web
起步依赖的坐标就可以进行 web 开发了,同样体现了依赖传递的作用,同时加载 tomcat,只要启动 main 方法,就相当于起到 tomcat 进行开发;同时加载 json,支持 springmvc 的数据请求和响应。
2、自动配置原理解析 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.atguigu;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;@SpringBootApplication public class SpringbootDemo2Application { public static void main (String[] args) { ApplicationContext act = SpringApplication.run(SpringbootDemo2Application.class, args); for (String name : act.getBeanDefinitionNames()) { System.out.println(name); } } }
运行默认自动配置加载的对象
按住 Ctrl 点击查看启动类SpringbootDemo2Application
上的注解@SpringBootApplication
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) public @interface SpringBootApplication { @AliasFor( annotation = EnableAutoConfiguration.class ) Class<?>[] exclude() default {}; ... ... ... }
重点关注最后三个注解
@SpringBootConfiguration @SpringBootConfiguration
: 表示当前类具有配置类的作用
@EnableAutoConfiguration @EnableAutoConfiguration
:自动配置:根据当前引入的依赖包,猜测需要创建的工程类型,以及工程中有可能创建的对象,根据猜测自动创建工程所需的相关实例 bean,当程序启动,会自动加载扫描所有 classpath:/META-INF/spring.factories
文件 ,并且创建对应实例
详细查看:按住 Ctrl 点击查看注解 @EnableAutoConfiguration
1 2 3 4 5 6 7 8 9 10 11 12 13 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration" ; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
其中,@Import(AutoConfigurationImportSelector.class)
导入了 AutoConfigurationImportSelector
类
按住 Ctrl 点击查看 AutoConfigurationImportSelector
源码 , 下载元数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } protected AutoConfigurationEntry getAutoConfigurationEntry (AnnotationMetadata annotationMetadata) { .................... List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); .................... } protected List<String> getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), 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; }
其中,SpringFactoriesLoader.loadFactoryNames 方法的作用就是从 META-INF/spring.factories 文件中读取指定类对应的类名称列表
spring.factories
文件中有关自动配置的配置信息如下:摘抄重点,springboot
启动之后,会自动加载 dispatcherServlet
1 2 3 4 5 6 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ ... ... ... ... ... ... org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\ ... ... ... ... ... ...
上面配置文件存在大量的以 Configuration
为结尾的类名称,这些类就是存有自动配置信息的类,而SpringApplication
在获取这些类名后再加载
我们以 DispatcherServletAutoConfiguration
为例来分析:
按住Ctrl
点击 DispatcherServletAutoConfiguration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) @AutoConfigureAfter(ServletWebServerFactoryAutoConfiguration.class) public class DispatcherServletAutoConfiguration { public static final String DEFAULT_DISPATCHER_SERVLET_BEAN_NAME = "dispatcherServlet" ; ... ... ... }
@ComponentScan @componentScan
(包扫描):扫描当前包及其子包下被 @Component
,@Controller
,@Service
,@Repository
注解标记的类并纳入到 spring 容器中进行管理,所以这个注解会自动注入所有在主程序所在包下的组件。默认把当前启动类所在的包作为扫描包的起点,例如现在的测试项目,扫描 com.atguigu
包
3、举例自动配置 新建包 com.atguigu.pojo
, 创建类 User
1 2 3 4 5 6 7 8 9 package com.atguigu.pojo;public class User {}
在 resources
文件夹下面 新建 /META-INF/spring.factories
文件
1 org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.atguigu.pojo.User
运行主程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.atguigu;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.ApplicationContext;@SpringBootApplication public class SpringbootDemo2Application { public static void main (String[] args) { ApplicationContext act = SpringApplication.run(SpringbootDemo2Application.class, args); for (String name : act.getBeanDefinitionNames()) { System.out.println(name); } } }
查看结果:
SpringBoot 的配置文件 1、配置文件类型和作用 SpringBoot 是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties
或者application.yml
(application.yaml)进行配置。
SpringBoot 默认会从 Resources 目录下加载application.properties
或application.yml
(application.yaml)文件
配置application.yml
1 2 3 4 5 6 server: port: 1888 servlet: context-path: /springboot_demo02
新建 controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.atguigu.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class UserController { @RequestMapping("/get") public String save () { return "success" ; } }
运行 main 程序,访问:http://localhost:1888/springboot_demo02/get
按照上面的方式找到并打开:spring-configuration-metadata.json
为什么可以在 resources 下创建application.properties
或者application.yml
文件呢?我们查看 springboot 的启动依赖:
点击 spring-boot-starter-parent
可以看到:除了可以使用 application.propertes
文件,也可以使用 application.yml
或者 application.yaml
文件。
2、yml 配置文件简介 YML 文件格式是 YAML (YAML Aint Markup Language)编写的文件格式,YAML 是一种直观的能够被电脑识别的的数据数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持 YAML 库的不同的编程语言程序导入,比如: C/C++, Ruby, Python, Java, Perl, C#, PHP 等。YML 文件是以数据为核心的,比传统的 xml 方式更加简洁。
YML 文件的扩展名可以使用.yml 或者.yaml
yml 配置文件的语法 ① 配置普通数据 key: value
value 之前必须有一个空格!
② 配置对象数据 key: key1: value1 key2: value2 或者: key: {key1: value1,key2: value2}
1 2 3 user: username: root password: root
在 yml 语法中,相同缩进代表同一个级别,一般按一下 tab 键
在 user 类中,通过注解 @ConfigurationProperties
(prefix=“yml 配置文件中 key 的前缀”)可以将配置文件中的配置自动与实体进行映射
首先导入pom.xml
依赖
1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-configuration-processor</artifactId > <optional > true</optional > </dependency >
配置 User 实体类
1 2 3 4 5 6 7 8 9 @Component @ConfigurationProperties(value = "user") public class User implements Serializable { private String username; private String password; ... ... ...
修改 SpringbootDemo2Application
1 2 3 4 5 6 7 8 9 @SpringBootApplication public class SpringbootDemo2Application { public static void main (String[] args) { ApplicationContext act = SpringApplication.run(SpringbootDemo2Application.class, args); User user = (User) act.getBean("user" ); System.out.println(user); } }
运行程序,查看到输出
③ 配置 Map 数据 map: key: value1 key: value2
④ 配置数组(List、Set)数据 1 2 3 4 5 key: - value1 - value2 或者: key: [value1,value2]
注意:-
与 value1 之间存在一个空格
示例:
1 2 3 4 5 6 7 city: - beijing - shanghai - guangzhou city: [beijing ,shanghai ,guangzhou ]
3、配置文件与配置类的属性映射方式 使用注解@Value 映射
我们可以通过@Value 注解将配置文件中的值映射到一个 Spring 管理的 Bean 的字段上
例如:
application.yml
配置如下:
1 2 3 4 5 6 server: port: 1888 user: username: root password: root
修改 UserController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @RestController public class UserController { @RequestMapping("/get") public String save () { return "success" ; } @Value("${user.username}") private String username; @Value("${user.password}") private String password; @RequestMapping("/getUser") @ResponseBody public String quick () { return "username:" +username+",password=" +password; } }
浏览器访问地址:http://localhost:1888/getUser
页面正常显示: