Spring Boot是所有基于Spring 开发的项目的起点,尽可能减少配置文件。
案例需求:请求Controller中的方法,并将返回值响应到页面
<?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>org.example</groupId> <artifactId>springbootdemo1</artifactId> <version>1.0-SNAPSHOT</version> <!-- 所用的springBoot项目都会直接或者间接的继承spring-boot-starter-parent 1.指定项目的编码格式为UTF-8 2.指定JDK版本为1.8 3.对项目依赖的版本进行管理,当前项目再引入其他常用的依赖时就需要再指定版本号,避免版本 冲突的问题 4.默认的资源过滤和插件管理 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.4.RELEASE</version> </parent> <dependencies> <!--引入Spring Web及Spring MVC相关的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <!--可以将project打包为一个可以执行的jar--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
package com.rf.controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") public class HelloController { @RequestMapping("/boot") public String hello(){ return "hello,spring boot!!!"; } }
package com.rf; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * SpringBoot的启动类通常放在二级包中,比如:com.lagou.SpringBootDemo1Application * 因为SpringBoot项目在做包扫描,会扫描启动类所在的包及其子包下的所有内容。 */ //标识当前类为SpringBoot项目的启动类 @SpringBootApplication public class SpringBootDemo1Application { public static void main(String[] args) { SpringApplication.run(SpringBootDemo1Application.class,args); } }
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
package com.rf; import com.rf.controller.HelloController; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; /**
* SpringJUnit4ClassRunner.class:Spring运行环境
* JUnit4.class:JUnit运行环境
* SpringRunner.class:Spring Boot运行环境
*/ @RunWith(SpringRunner.class) @SpringBootTest //标记为当前类为SpringBoot测试类,加载项目的ApplicationContext上下文环境 public class Springbootdemo1ApplicationTests {
/**
* 需求:调用HelloController的hello方法
*/ @Autowired private HelloController helloController; @Test public void contextLoads(){ String res = helloController.hello(); System.out.println("res = " + res); } }
<!-- 引入热部署依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency>
#解决中文乱码
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
#服务器端口号
server.port=8888
#自定义配置jdbcTemplate连接数据库驱动
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306
spring.datasource.username=root
spring.datasource.password=123456
# person属性
person.id=1000
person.name=于谦
person.hobby=抽烟,喝酒,烫头
person.family=妻子,儿女
person.map.k1=v1
person.map.k2=v2
person.pet.type=dog
person.pet.name=旺财
@ConfigurationProperties(prefix = "person")注解的作用是将配置文件中以person开头的属性值通过setXX()方法注入到实体类对应属性中
@Component注解的作用是将当前注入属性值的Person类对象作为Bean组件放到Spring容器中,只有这样才能被@ConfigurationProperties注解进行赋值
application.yaml配置文件
YAML文件格式是Spring Boot支持的一种JSON文件格式,相较于传统的Properties配置文件,YAML文
件以数据为核心,是一种更为直观且容易被电脑识别的数据序列化格式。application.yaml配置文件的
工作原理和application.properties是一样的,只不过yaml格式配置文件看起来更简洁一些。
YAML文件的扩展名可以使用.yml或者.yaml。
application.yml文件使用 “key:(空格)value”格式配置属性,使用缩进控制层级关系。
SpringBoot的三种配置文件是可以共存的:
这里,针对不同数据类型的属性值,介绍一下YAML
(1)value值为普通数据类型(例如数字、字符串、布尔等)
当YAML配置文件中配置的属性值为普通数据类型时,可以直接配置对应的属性值,同时对于字符
串类型的属性值,不需要额外添加引号,示例代码如下
(2)value值为数组和单列集合
当YAML配置文件中配置的属性值为数组或单列集合类型时,主要有两种书写方式:缩进式写法和行内
式写法。
其中,缩进式写法还有两种表示形式,示例代码如下
或者使用如下示例形式
上述代码中,在YAML配置文件中通过两种缩进式写法对person对象的单列集合(或数组)类型的爱好
hobby赋值为play、read和sleep。其中一种形式为“-(空格)属性值”,另一种形式为多个属性值之前加
英文逗号分隔(注意,最后一个属性值后不要加逗号)。
通过上述示例对比发现,YAML配置文件的行内式写法更加简明、方便。另外,包含属性值的中括
号“[]”还可以进一步省略,在进行属性赋值时,程序会自动匹配和校对
(3)value值为Map集合和对象
当YAML配置文件中配置的属性值为Map集合或对象类型时,YAML配置文件格式同样可以分为两种书写
方式:缩进式写法和行内式写法。
其中,缩进式写法的示例代码如下
对应的行内式写法示例代码如下
在YAML配置文件中,配置的属性值为Map集合或对象类型时,缩进式写法的形式按照YAML文件格式编
写即可,而行内式写法的属性值要用大括号“{}”包含。
接下来,在Properties配置文件演示案例基础上,通过配置application.yaml配置文件对Person对象进
行赋值,具体使用如下
(1)在项目的resources目录下,新建一个application.yaml配置文件,在该配置文件中编写为Person
类设置的配置属性
(2)再次执行测试
Person{id=1, name=‘王二麻子‘, hobby=[play, read, sleep], family=[妻, 妾], map={k1=value1,
k2=value2}, pet=Pet{type=‘狗‘, name=‘哈士奇‘}}
可以看出,测试方法configurationTest()同样运行成功,并正确打印出了Person实体类对象。
需要说明的是,本次使用application.yaml配置文件进行测试时需要提前将application.properties配置
文件中编写的配置注释,这是因为application.properties配置文件会覆盖application.yaml配置文件
配置文件属性值的注入
配置文件的优先级如下: 从低到高
使用Spring Boot全局配置文件设置属性时:
person:
map: {k1: v1,k2: v2}
#对实体类对象Person进行属性配置
person:
id: 1
name: 王二麻子
family:
- 妻
- 妾
hobby:
- play
- read
- sleep
map:
k1: value1
k2: value2
pet:
type: 狗
name: 哈士奇
<includes>
<include>**/application*.yml</include>
<include>**/application*.yaml</include>
<include>**/application*.properties</include>
</includes>
如果配置属性是Spring Boot已有属性,例如服务端口server.port,那么Spring Boot内部会自动扫描并
读取这些配置文件中的属性值并覆盖默认属性。
如果配置的属性是用户自定义属性,例如刚刚自定义的Person实体类属性,还必须在程序中注入这些配
置属性方可生效。
Spring Boot支持多种注入配置文件属性的方式,下面来介绍如何使用注解@ConfigurationProperties和
@Value注入属性
1.7.1 使用@ConfigurationProperties注入属性 |
Spring Boot提供的@ConfigurationProperties注解用来快速、方便地将配置文件中的自定义属性值批量 |
注入到某个Bean对象的多个对应属性中。假设现在有一个配置文件,如果使用 |
@ConfigurationProperties注入配置文件的属性,示例代码如下: |
上述代码使用@Component和@ConfigurationProperties(prefix = “person”)将配置文件中的每个属性
映射到person类组件中。
1.7.2 使用@Value注入属性
@Value注解是Spring框架提供的,用来读取配置文件中的属性值并逐个注入到Bean对象的对应属性
中,Spring Boot框架从Spring框架中对@Value注解进行了默认继承,所以在Spring Boot框架中还可以
使用该注解读取和注入配置文件属性值。使用@Value注入属性的示例代码如下
上述代码中,使用@Component和@Value注入Person实体类的id属性。其中,@Value不仅可以
将配置文件的属性注入Person的id属性,还可以直接给id属性赋值,这点是@ConfigurationProperties
不支持的
演示@Value注解读取并注入配置文件属性的使用:
(1)在com.lagou.pojo包下新创建一个实体类Student,并使用@Value注解注入属性
@Component
//将配置文件中所有以person开头的配置信息注入当前类中
//前提1:必须保证配置文件中person.xx与当前Person类的属性名一致
//前提2:必须保证当前Person中的属性都具有set方法
@ConfigurationProperties(prefix = "person")
public class Person {
private | int | id; | //id |
private | String | name; | //名称 |
private | List | hobby; | //爱好 |
private | String[] | family; | //家庭成员 |
private | Map | map; | |
private | Pet | pet; | //宠物 |
} |
@
Component
public class Person {
@Value("${person.id}")
private int id;
}
Student类使用@Value注解将配置文件的属性值读取和注入。
从上述示例代码可以看出,使用@Value注解方式需要对每一个属性注入设置,同时又免去了属性的
setXX()方法
(2)再次打开测试类进行测试
打印结果:
可以看出,测试方法studentTest()运行成功,同时正确打印出了Student实体类对象。需要说明的
是,本示例中只是使用@Value注解对实例中Student对象的普通类型属性进行了赋值演示,而@Value注
解对于包含Map集合、对象以及YAML文件格式的行内式写法的配置文件的属性注入都不支持,如果赋
值会出现错误
自定义配置
spring Boot免除了项目中大部分的手动配置,对于一些特定情况,我们可以通过修改全局配置文
件以适应具体生产环境,可以说,几乎所有的配置都可以写在application.yml文件中,Spring Boot会自
动加载全局配置文件从而免除我们手动加载的烦恼。但是,如果我们自定义配置文件,Spring Boot是无
法识别这些配置文件的,此时就需要我们手动加载。接下来,将针对Spring Boot的自定义配置文件及其
加载方式进行讲解
1.8.1 使用@PropertySource加载配置文件
对于这种加载自定义配置文件的需求,可以使用@PropertySource注解来实现。
@PropertySource注解用于指定自定义配置文件的具体位置
和名称
当然,如果需要将自定义配置文件中的属性值注入到对应类的属性中,可以使用
@ConfigurationProperties或者@Value注解进行属性值注入
演示:
@Component
public class Student {
@Value("${person.id}")
private int id;
@Value("${person.name}")
private String name; //名称
//省略toString
}
@Autowired
private Student student;
@Test
public void studentTest() {
System.out.println(student);
}
(1)打开Spring Boot项目的resources目录,在项目的类路径下新建一个test.properties自定义配
置文件,在该配置文件中编写需要设置的配置属性
(2)在com.lagou.pojo包下新创建一个配置类MyProperties,提供test.properties自定义配置文件
中对应的属性,并根据@PropertySource注解的使用进行相关配置
主要是一个自定义配置类,通过相关注解引入了自定义的配置文件,并完成了自定义属性值的注
入。针对示例中的几个注解,具体说明如下
@PropertySource("classpath:test.properties")注解指定了自定义配置文件的位置和名称,此示例
表示自定义配置文件为classpath类路径下的test.properties文件;
@ConfigurationProperties(prefix = "test")注解将上述自定义配置文件test.properties中以test开
头的属性值注入到该配置类属性中。
(3)进行测试
打印结果:
1.8.2 使用@Configuration编写自定义配置类
在Spring Boot框架中,推荐使用配置类的方式向容器中添加和配置组件
在Spring Boot框架中,通常使用@Configuration注解定义一个配置类,Spring Boot会自动扫描和识别
配置类,从而替换传统Spring框架中的XML配置文件。
当定义一个配置类后,还需要在类中的方法上使用@Bean注解进行组件配置,将方法的返回对象注入到
Spring容器中,并且组件名称默认使用的是方法名,当然也可以使用@Bean注解的name或value属性自
定义组件的名称
#对实体类对象MyProperties进行属性配置
test.id=110
test.name=test
@Component // 自定义配置类
@PropertySource("classpath:test.properties") // 指定自定义配置文件位置和名称
@ConfigurationProperties(prefix = "test") // 指定配置文件注入属性前缀
public class MyProperties {
private int id;
private String name;
// 省略属性getXX()和setXX()方法
// 省略toString()方法
}
@Autowired
private MyProperties myProperties;
@Test
public void myPropertiesTest() {
System.out.println(myProperties);
}
演示:
(1)在项目下新建一个com.lagou.config包,并在该包下新创建一个类MyService,该类中不需要编写
任何代码
创建了一个空的MyService类,而该类目前没有添加任何配置和注解,因此还无法正常被Spring Boot扫
描和识别
(2) 在项目的com.lagou.config包下,新建一个类MyConfig,并使用@Configuration注解将该类声明
一个配置类,内容如下:
MyConfig是@Configuration注解声明的配置类(类似于声明了一个XML配置文件),该配置类会
被Spring Boot自动扫描识别;使用@Bean注解的myService()方法,其返回值对象会作为组件添加到了
Spring容器中(类似于XML配置文件中的标签配置),并且该组件的id默认是方法名myService
(3)测试类
上述代码中,先通过@Autowired注解引入了Spring容器实例ApplicationContext,然后在测试方法
iocTest()中测试查看该容器中是否包括id为myService的组件。
执行测试方法iocTest() ,查看控制台输出效果,结果如下:
从测试结果可以看出,测试方法iocTest()