使用步骤
1. 创建Maven工程
2. 导入相关依赖(这里使用的是web模块依赖)
<?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</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<!-- spring-boot-starter就是spring的场景启动器-->
<!-- springboot将各个场景所需要的依赖抽取出来,做成一个个启动器,我们只需要导入相应场景的启动器starter即可-->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- spring热部署配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</dependencies>
<build>
<plugins>
<!-- 这个插件可以将应用打包成一个可执行的jar包-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3. 编写SpringBoot引导类
package com.atguigu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* ClassName: HelloWorldMainApplication
* Description:
* date: 2020/8/23 17:36
*
* @author July
* @since JDK 1.8
*/
//@SpringBootApplication来标注一个主程序类,说明这是一个springboot应用
//springboot在启动的时候从类路径下的spring-boot-autoconfigure-2.1.1.RELEASE.jar!META-INFspring.factories
//文件里获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到spring容器中
//J2EE的整体解决方法都在org.springframework.boot.autoconfigure包下
@SpringBootApplication
public class HelloWorldMainApplication {
public static void main(String[] args) {
//spring应用启动起来
SpringApplication.run(HelloWorldMainApplication.class,args);
}
}
注意事项:引导类只会从他所在的包路径(com.atguigu下)扫描所有包以及子包的组件
4. 编写Controller
package com.atguigu.controller;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
/**
* ClassName: HelloController
* Description:
* date: 2020/8/23 17:42
*
* @author July
* @since JDK 1.8
*/
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello(){
return "hello world!";
}
}
5. 测试
执行SpringBoot引导类的主方法,控制台打印日志如下:
tomcat已经起步,端口监听8080,web应用的虚拟工程名称为空(默认“/”)
打开浏览器访问url地址为:http://localhost:8080/hello
也可以使用idea的spring initial快速搭建项目
起步依赖原理分析
- spring-boot-starter-parent
<properties>
<activemq.version>5.15.3</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.63</appengine-sdk.version>
<artemis.version>2.4.0</artemis.version>
<aspectj.version>1.8.13</aspectj.version>
<assertj.version>3.9.1</assertj.version>
<atomikos.version>4.0.6</atomikos.version>
<bitronix.version>2.1.4</bitronix.version>
<build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
<byte-buddy.version>1.7.11</byte-buddy.version>
... ... ...
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
... ... ...
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
</plugin>
<plugin>
<groupId>org.jooq</groupId>
<artifactId>jooq-codegen-maven</artifactId>
<version>${jooq.version}</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.0.1.RELEASE</version>
</plugin>
... ... ...
</plugins>
</pluginManagement>
</build>
从spring-boot-starter-dependencies的pom.xml中我们可以发现,一部分坐标的版本、依赖管理、插件管理已经定义好,所以我们的SpringBoot工程继承spring-boot-starter-parent后已经具备版本锁定等配置了(不会出现版本冲突的问题)。所以起步依赖的作用就是进行依赖的传递。
- spring-boot-starter-web
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.1.RELEASE</version>
<name>Spring Boot Web Starter</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.0.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
<version>2.0.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.0.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.9.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
从上面的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的数据请求和响应。
自动配置注解解析
package com.atguigu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SpringbootDemo02Application {
public static void main(String[] args) {
ApplicationContext act = SpringApplication.run(SpringbootDemo02Application.class, args);
for (String name : act.getBeanDefinitionNames()) {
System.out.println(name);
}
}
}
运行默认自动配置加载的对象,可以看到spring容器中加载了大量的组件
注解@SpringBootApplication
@SpringBootApplication
封装spring注解的复合注解,包含@ComponentScan
,和@SpringBootConfiguration
,@EnableAutoConfiguration
@ComponentScan
包扫描
componentScan 扫描当前包及其子包下被 @Component,@Controller,@Service,@Repository注解标记的类并纳入到spring容器中进行管理,
所以这个注解会自动注入所有在主程序所在包下的组件。默认把当前启动类所在的包作为扫描包的起点,例如咱们的项目,扫描 com.atguigu 包
@SpringBootConfiguration
: 表示当前类具有配置类的作用,替代applicationContext.xml
配置类
自动配置:根据当前引入的依赖包,猜测需要创建的工程类型,以及工程中有可能创建的对象,根据猜测自动创建工程所需的相关实例bean
程序启动,会自动加载扫描所有 classpath:/META-INF/spring.factories文件 ,并且创建对应实例
其中,@Import(AutoConfigurationImportSelector.class)
导入了 AutoConfigurationImportSelector
类,其中,SpringFactoriesLoader.loadFactoryNames 方法的作用就是从META-INF/spring.factories文件中读取指定类对应的类名称列表
spring.factories
配置文件存在大量的以 Configuration
为结尾的类名称,这些类就是存有自动配置信息的类,而SpringApplication 在获取这些类名后再加载
SpringBoot配置文件
SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用application.properties或者application.yml(application.yaml)进行配置。
SpringBoot默认会从Resources目录下加载application.properties或application.yml(application.yaml)文件
application.properties
# tomcat 端口号
server.port=18081
# 配置项目所在的根目录
server.servlet.context-path=/springboot-demo02
自定义配置
# 需要将idea的properties文件改成utf8编码
person.name = "张三"
person.maps.k1 = "v1"
person.maps.k2 = "v2"
person.lists = "zs","ls"
person.dog.name = "qwe"
person.dog.age = 1
application.yml
语法: 具体参考yml写法
server:
error:
path: "/"
相当于propties的server.error.path="/"
注意事项:值得前面是有空格的
自定义配置xml写法
person:
name: "张三"
age: 12
boss: false
birthday: 2019/2/1
maps: {k1: v1,k2: v2}
lists:
- "zs"
- "ls"
dog:
name: "xh"
age: 1
写一个person类作为自定义配置类
@Component //只有在spring容器中的组件,容器才能提供@ConfigurationProperties功能
@ConfigurationProperties(prefix = "person") //告诉springboot这个类中的所有属性都是配置文件中的属性
//prefix:配置文件中哪个下面的所有属性进行映射
public class Person {
/**
* @Value : ${}从环境变量、配置文件中获取值
* #{} SPEL
*/
private String name;
private Integer age;
private Boolean boss;
private Date birthday;
private Map<String,Object> maps;
private List<Object> lists;
@ConfigurationProperties 和 @Value 的对比
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 在每个属性上一一指定 |
松散语法(驼峰命名) | 支持 | 不支持 |
SPEL | 不支持 | 支持 |
JSR303校验 | 支持 | 不支持 |
支持的注入类型 | 支持复杂类型 | 只支持基本类型 |
两种方式的适用场合:
-
当只需要为某个值提供注入时,推荐使用@Value方式。
-
当需要对整个对象的整体进行赋值时,使用@ConfigurationProperties。
加载外部配置文件
如果我们将所有的配置信息都写在application.yml文件中,则到时候yml文件会变得非常庞大,不太方便我们进行维护。
我们可以对配置中的内容进行拆分,拆分到多个文件中。这样就提高了配置的可维护性。
引入外部配置文件有三种方式:
-
@PropertySource(value={"classpath:student.properties"}) :导入类路径下的properties文件
需要注入的类的前面使用该注解。 -
@ImportResource(locations={"classpath:spring.xml"} :导入spring的配置文件
首先添加一个spring的配置文件,在里面添加需要映射的类。在启动的SpringBootApplication前面使用该注解 -
@Configuration和@Bean式添加一个自定义配置类。(SpringBoot推荐方式)
@Configuration //告诉springboot这是一个配置类
public class MyConfig {
//将@Bean标注的组件加入到ioc容器,默认为方法名作为id,返回值作为bean类型
@Bean
public Person person(){
return new Person();
}
}
使用profile切换环境
真实环境中,有时候需要配置多个配置文件,可以使用spring.profile.active来进行切换。
文件名:application-${profile}.yml
-
创建生成环境配置文件:application-dev.yml
-
创建开发环境配置文件:application-prod.yml
我们在application.yml中通过spring.profile.active = dev(prod)来选择需要加装的配置文件。
或者我们可以通过maven将项目打成jar包通过命令行使用以下命令来指定环境
java –jar springboot02-0.0.1-SHAPSHOT.jar –spring.profiles.active=dev</span class="hljs-attribute">
yml文档块
在yml文档中,可以适用---来将一个文档拆分为多个文档块。可以在不同文档块中分别定义不同的环境。
spring:
profiles:
active: dev //指定激活文档
---
server:
port: 8080
spring:
profiles: dev 开发环境文档块
---
server:
port: 80
spring:
profiles: prod 生产环境文档块
springboot配置文件加载位置和加载顺序
springboot启动会扫描以下位置的配置文件作为springboot的默认配置文件。
- 项目路径下的config文件夹
- 项目路径下
- classpath路径下config文件夹
- classpath路径下
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,如果冲突的情况,高优先级配置内容会覆盖低优先级配置内容。如果不冲突,形成互补配置。
我们也可以通过配置spring.config.location来改变默认配置。使用命令行方式加载,否则优先级不够。
java –jar xxxx.jar –spring.config.location=配置文件路径
外部配置加载顺序(红色为重点)
springBoot也可以从以下位置加载配置;优先级从高到低,高优先级的配置覆盖低优先级的配置,所有配置形成互补配置。
1. 命令行参数,写法:--配置项1=值1 --配置项2=值2
2. 来自java:comp/env的JNDI属性
3. Java系统属性(System.getProperties())
4. 操作系统环境变量
5. RandomValuePropertySource配置的random.*属性值
6. jar包外部的application-{profile}.prsoperties或application.yml(带spring.profile)配置文件
7. jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
8. jar包外部的application.properties或application.yml(不带spring.profile)配置文件
9. jar包内部的application.properties或application.yml(不带spring.profile)配置文件
10. @Configuration注解类上的@PropertySource
11. 通过SpringApplication.setDefaultProperties指定的默认属性
更多配置参考官方文档
SpringBoot注解查询地址
SpringBoot自动配置
SpringBoot启动会加载大量的自动配置类
SpringBoot自动配置分析步骤
-
我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;
-
我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)
-
给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;
自动配置原理:
SpringBoot启动的时候,加载主配置类,开启了自动配置功能@EnableAutoConfiguration。
利用EnableAutoConfigurationImportSelector给容器中导入一些组件。
导入的文件在都配置在文件META‐INF/spring.factories中的EnableAutoConfiguration属性来获取的。
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置。
查看springboot生效的自动配置类
在每个自动配置类(xxxAutoConfiguration类)中有大量的@ConditionnalXXX注解(按照条件注册bean),所以自动配置类必须在满足一定条件下才能生效
怎么查看这些自动配置类呢?
在application.xml或application.propties配置文件中开启debug模式
# 开启spring的debug模式
debug: true
再次启动项目时,可以在控制台看到打印的自动配置类信息
本文参考自以下链接
参考链接