SpringBoot02
使用Spring Initializer快速创建SpringBoot项目
- 选好模块后, idea会联网帮我们导入相应的依赖.
- 这样主程序就生成好了, 只需要我们编写自己的逻辑即可.
- resources文件夹中目录结构
- static: 保存所有的静态资源; js, css, image.
- templates: 保存所有的模板页面
- SpringBoot默认jar包使用嵌入式的Tomcat, 不支持jsp, 但可以使用模板引擎thymeleaf.
- application.properties: SpringBoot应用的配置文件, 可以修改一些默认设置.
SpringBoot配置
配置文件
- SpringBoot使用一个全局的配置文件
- application.properties
- 或application.yml
- 配置文件的作用: 修改SpringBoot自动配置的默认值.
- 配置文件放在src/main/resources目录下.
YAML语法
- 以前我们的配置文件大多是xml文件, 而yml是以数据为中心的, 比起xml, json更适合做配置文件
server: port: 8081
- 基本语法
- k: v 表示一对键值对(冒号后必须有空格)
- 以空格的缩进控制层级关系: 左对齐的一列数据都是同一层级的.
server: port: 8080 path: /hello
- 属性和值大小写敏感.
- 值的写法
- 字面量: 普通值(数字,字符串,布尔)
- k: v 字面量直接来写, 字符串默认不用加引号.
- "xxx": 双引号不会转义字符串中的特殊字符.
- 'xxx': 单引号会转义字符串中的特殊字符(特殊字符最终只是一个普通字符串输出)
- 对象: Map(键值对) 在下一行来写对象的属性和值的关系
- 对象还是k: v的形式
friends: lastName: zhangsan age: 20
- 行内写法
friends: {lastName: zhangsan, age: 18}
- 对象还是k: v的形式
- 数组(List, Set)
- 用 - 表示数组中的一个元素
pets: - cat - dog - pig
- 行内写法
pets: [cat, dog, pig]
- 用 - 表示数组中的一个元素
- 字面量: 普通值(数字,字符串,布尔)
配置文件的注入
- yml配置文件
server: port: 8081 person: lastName: zhangsan age: 18 boss: false birth: 2020/5/11 map: {k1: v1, k2: v2} list: - lisi - zhaoliu dog: name: 小狗 age: 2
- 实体类
/** * 将配置文件中每个属性的值映射到这个组件中 * @ConfigurationProperties: 告诉SpringBoot将本类中所有属性和配置文件中的相关配置绑定 * prefix = "person": 与配置文件中哪个属性的下面一一对应. * 只有这个组件是容器的组件, 才能提供@ConfigurationProperties的功能. */ @Component @ConfigurationProperties(prefix = "person") @Data @NoArgsConstructor @AllArgsConstructor public class Person { private String lastName; private Integer age; private Boolean boss; private Date birth; private Map<String, Object> map; private List<Object> list; private Dog dog; }
- 再pom.xml中导入配置文件处理器, 这样以后写yml时就有提示了
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
- 测试程序
/** * SpringBoot单元测试 * 可以在测试期间类似编码一样进行自动注入等容器功能 */ @RunWith(SpringRunner.class) @SpringBootTest public class SpringBoot02ConfigApplicationTests { @Autowired Person person; @Test public void contextLoads() { System.out.println(person); } }
- properties配置文件注入的写法
person.last-name=张三 person.age=18 person.birth=2017/12/15 person.boss=false person.map.k1=v1 person.map.k2=14 person.list=a,b,c person.dog.name=dog person.dog.age=15
- 倘若出现了中文的乱码问题
配置文件注入时的对比
- @Value获取值和@ConfigurationProperties获取值比较
- @ConfigurationProperties: 批量注入配置文件中的属性
- 支持松散绑定语法
- 不支持SpEL表达式
- 支持JSR303数据校验
- 支持复杂类型的封装
- @Value: 一个一个指定注入
- 不支持松散绑定语法
- 支持SpeL表达式
- 不支持JSR303数据校验
- 不支持复杂类型的封装
- @ConfigurationProperties: 批量注入配置文件中的属性
- 松散绑定
- 如 lastName 和 last-name 和 last_name 同义
- SpEL表达式
/** * <bean class="Person"> * <property name="lastName" value="${SpeL}"></property> * </bean> */ ${}内是表达式的值, 可以放在配置文件中. @Value("${person.last-name}") private String lastName;
- JSR303数据校验: 类上带 @Validated
@Component @ConfigurationProperties(prefix = "person") @Validated @Data @NoArgsConstructor @AllArgsConstructor public class Person { @Email private String lastName; private Integer age; }
- 这样lastName必须为email格式的数据, 否则将报错.
- 总结
- 如果我们只是在某个业务逻辑中获取下配置文件中的某项值, 使用@Value, 如
@RestController public class HelloController { @Value("${person.last-name}") private String name; @RequestMapping("/sayHello") public String sayHello() { return "Hello " + name; } }
- 如果我们专门编写javaBean来和配置文件进行映射, 则用@ConfigurationProperties
- 如果我们只是在某个业务逻辑中获取下配置文件中的某项值, 使用@Value, 如
@PropertySource和@ImportSource
- @PropertySource: 加载指定的配置文件(不写的话会加载全局配置文件)
- value属性: 指定要加载的配置文件的位置
@Component @PropertySource(value = "classpath:person.properties") @ConfigurationProperties(prefix = "person") @Data @NoArgsConstructor @AllArgsConstructor public class Person { private Integer age; private Boolean boss; private Date birth; private Map<String, Object> map; private List<Object> list; private Dog dog; }
- value属性: 指定要加载的配置文件的位置
- @ImportResource: 导入Spring的配置文件, 让配置文件中的内容生效.
- SpringBoot里边没有Spring的配置文件(xxx.xml), 我们自己编写, 也不能自动识别; 想让Spring的配置文件生效, 就需要把@ImportResource标注在配置类上
@ImportResource(locations = {"classpath:beans.xml"}) @SpringBootApplication public class MainType { public static void main(String[] args) { SpringApplication.run(MainType.class, args); } }
- 编写beans.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="helloService" class="top.binwenhome.service.HelloService"></bean> </beans>
- SpringBoot里边没有Spring的配置文件(xxx.xml), 我们自己编写, 也不能自动识别; 想让Spring的配置文件生效, 就需要把@ImportResource标注在配置类上
- SpringBoot推荐给容器添加组件的方式: 使用全注解的方式
- 不用加@ImportResource了
- 配置类@Configuration
- 使用@Bean给容器中添加组件
/** * 指明这是一个配置类, 来替代Spring的配置文件 */ @Configuration public class MyAppConfig { /** * 将方法的返回值添加到容器中, 容器中这个组件默认id是方法名 */ @Bean public HelloService helloService() { System.out.println("添加组件了"); return new HelloService(); } }
- 测试程序
@RunWith(SpringRunner.class) @SpringBootTest public class SpringBoot02ConfigApplicationTests { @Autowired ApplicationContext ioc; @Test public void test() { boolean b = ioc.containsBean("helloService"); System.out.println(b); } }
配置文件占位符
- 随机数
${random.value}, ${random.int}, ${random.long} ${random.int(10)}, ${random.int[100,1000]}
- 属性配置占位符
- 可以在配置文件中引用前面配置过的属性.
- 可以引用随机数
- ${xxx.xxx: 指定默认值}
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
Profile
- Profile是Spring对不同环境提供不同配置功能的支持, 可以通过激活指定参数等方式快速切换环境.
- 多profile文件形式
- 文件名格式: application-{profile}.properties/yml
#application.properties
server.port=8080
spring.profiles.active=dev #指定要用的环境
==================分界线===================#application-dev.properties server.port=8081 ==================分界线=================== #application-product.properties server.port=8082
- 文件名格式: application-{profile}.properties/yml
- yml支持多文档块方式
server: port: 8081 spring: profiles: active: prod #指定用哪个环境 --- server: port: 8082 spring: profiles: dev --- server: port: 8084 spring: profiles: product
- 激活指定profile
- 在配置文件中指定: spring.profiles.active=dev
- 命令行方式: --spring.profiles.active=dev
- 虚拟机参数: -Dspring.profiles.active=dev
配置文件加载位置
- springboot启动后会扫描以下位置的application.properties/yml文件作为springboot的默认配置文件.
- -file: ./config/
- -file: ./
- -classpath: /config/
- -classpath: /
- 优先级从高到低, 高优先级的配置会覆盖低优先级的配置, 并且是互补配置.
- 另外, 我们可以通过spring.config.location来改变默认的配置文件位置
- 项目打包好以后, 我们可以使用命令行参数的形式, 启动项目时来指定配置文件新位置, 同样是互补配置.
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties
- 项目打包好以后, 我们可以使用命令行参数的形式, 启动项目时来指定配置文件新位置, 同样是互补配置.
外部配置的加载顺序
- springboot也可以从以下位置加载配置: 优先级从高到低, 高优先级覆盖低优先级, 互补配置.
- 命令行参数.
- 所有的配置都可以在命令行上进行指定
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
- 多个配置用空格分开; --配置项=值
- 当然, 这样写比较复杂, 我们可以通过命令行的方式访问外部配置文件.
- 所有的配置都可以在命令行上进行指定
- jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件.
- jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
- jar包外部的application.properties或application.yml(不带spring.profile)配置文件
- jar包内部的application.properties或application.yml(不带spring.profile)配置文件
- 命令行参数.
- 当然, 实际上有17种加载来源, 其他的用的不多