Spring Boot从三到四

标签: Springboot 分类: Java 创建时间:2020-05-07 07:44:25 更新时间:2024-11-15 10:49:43

前面写了很多了关于SpringBoot入门的资料,这是第四篇。

参考文章:
1.面试官问:为什么SpringBoot的 jar 可以直接运行? (虽然不能算是入门了,但是进行了解,也有助于对整个框架的解释)

1.yml配置文件

(1) 定义多个配置文件

可以同时定义多个yml配置文件,比如:application-dev.yml、application-prod.yml、application-test.yml,通过在application.yml文件中定义:spring.profiles.active 属性,来区分要启动的配置文件,可以同时启动多个配置文件,比如:spring.profiles.active=dev,prod,test,后者与前者如果有相同的配置,则后者配置获胜,覆盖前者。

1
2
3
spring:
profiles:
active: dev,prod,test # 选择加载文件application-{test}.yml

(2) 定义和引用变量

如果一个字符串在yml中多次出现,则可以定义变量,通过变量的引用,就可以减少字符串的书写次数,也容易将字符串进行修改,修改一次字符串之后,其他的引用也都跟着变化了。yml中,引用变量的方式是通过${变量名}方式。在properties中,也是使用同样的方法进行变量引用。但是在引用pom.xml中变量还是有些区别的。

1
2
3
app-name: test

redis-name: ${app-name}-redis

(3) yml引用pom.xml中的变量

在yml中引用pom.xml中的变量,需要两步
(1) pom.xml中添加

1
2
3
4
5
6
7
8
9
10
11
<!--变量内容-->
<name>phemsjava</name>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>

(2) 在application.yml配置文件中使用@@符合替换变量

1
2
redis:
name: '@project.name@'

(3) 进行打包

1
mvn clean package

这样resources下的application.yml

被打包之后的 tarcat/class 目录下的applcation.yml中的@@就会变成了相应的pom中的变量。在debug时,修改了pom.xml的值或者是yml中的值,除了重启应用程序之外,最好也执行一遍打包命令。

(4) 也可以增加自定义的属性,在pom.xml中的properties填写自定义的属性

1
2
3
4
<properties>
<java.version>1.8</java.version>
<tk>dfd</tk>
</properties>

在application.yml中直接使用@tk@,引用pom.xml中的变量。

(4) 多模块的配置文件

如果各个模块都有自己的配置文件,就需要用到了多application.yml 合并选项。以A模块依赖于B和C模块为例,需要将B和C模块的配置文件整合到A模块的配置中。假设B模块的配置文件名为application-dev.yml,C模块的配置文件名为application-test.yml,需要将它们整合到A模块的配置文件application.yml中。

这里我本想引用 disasterapi 模块下的 src/main/resources/applicaion.yml 中的内容,结果总是找不到这个文件。使用 classpath:disasterapi/application.yml 也不行

1
2
3
4
spring:
config:
import:
- classpath:/disasterapi/application.yml

最后的解决方案,就是将 application.yml 重命名为 application-disaster.yml,这样就可以直接找到这个文件了。

1
2
3
4
spring:
config:
import:
- classpath:application-disaster.yml
参考文章:
1.maven多模块多配置文件整合方案
2.SpringBoot使用spring.config.import多种方式导入配置文件
3.Spring Boot 分离配置文件的 N 种方式 1.配置文件位置:从 classpath 下加载;从项目所在的当前目录下加载;2.额外位置;3.位置通配符;4.导入外部配置。
4.springboot 多模块配置文件 这里直接在 classpath 中写了 modul1 的配置,这个我尝试了,没有效果。
5.如何配置SpringBoot多模块多环境配置文件 详细过程解析

4.properties中使用pom中的变量

(1) 在pom.xml中添加

1
2
3
4
5
6
7
8
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>

(2) properties配置文件中使用项目的版本号

1
app.version=${project.version}

5.static静态方法中注入Bean

在静态方法中,只能使用静态的属性,所以需要

6.读取配置文件

需求是这样的,就是我有多个properities文件,但是不是系统启动必须的文件,比如:application.properties或者是bootstrap.properities文件,是一些属性文件,比如:Error.properitis、Text.properities,里面也是:key=value 这种键值队的集合,当我想要某一个属性的时候,我想通过 getString(“key”) 这样的方法获取到这个键所对应的值,我也不需要使用 @ConfigurationProperties、@PropertySource 注解,单独的写一个配置文件类,这样得不偿失,因为我有时候可能并不是需要里面的值,所以你可以看成是一个单纯的文本文件,但是我想要用更加简单的方式读取出来。

使用 ResourceBundle textBundle = PropertyResourceBundle.getBundle(“Text”),这样的方式,在打包成jar包的时候可以使用,但是我在 SpringBoot 中使用,死活不行,就是读取不到resources文件夹下的相关文件。根据参考文章5,可以将properities文件放到src文件夹下,使用相对路径进行读取,但是我最终还是失败了。

1
2
3
//config为属性文件名,放在包com.test.config下,如果是放在src下,直接用config即可  
ResourceBundle resource = ResourceBundle.getBundle("com/test/config/config");
String key = resource.getString("keyWord");

【解决方法】
这里我提供一种使用 Spring 提供的 PropertiesLoaderUtils 工具进行读取resource文件夹下的文件方法。

1
2
3
Properties properties = new Properties();
properties=PropertiesLoaderUtils.loadProperties(new ClassPathResource("config/Text.properties"));
String key = properties.getProperty("FMT01");

这里主要的就是要研究 ClassPathResource 的用法。当然还有很多其他的方法,我就不一一实验了。

参考文章:
1.SpringBoot读取application.properties文件
2.Spring Boot读取多个自定义配置文件里的配置项内容 使用Environment env加载环境变量的信息
3.配置和读取多个Properties文件 这篇文章有点老了,是spring的,还是用的xml的形式进行配置的
4.如何在SpringBoot下读取自定义properties配置文件 使用的
5.Java 读取 .properties 配置文件的几种方式 这里有三种方法:基于ClassLoder读取配置文件、基于 InputStream 读取配置文件、通过 java.util.ResourceBundle 类来读取,这种方式比使用 Properties 要方便一些,这里还列举了各种不同的东西,但是我大部分都没有实验处理,主要是关于路径的问题,但是最后的加载方式,都是使用 Properties 这个类。
6.Spring工具类之PropertiesLoaderUtils 介绍了 PropertiesLoaderUtils 的用法,有好几种,但是始终还是
7.Spring项目读取resource下的文件 介绍了ClassPathResource的用法。

6.bootstrap文件

在 Spring Boot 中有两种上下文,一种是 bootstrap,另外一种是 application。

  • bootstrap 是系统级的资源配置项,application是用户级的资源配置项。
  • boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载。
  • bootstrap 具有更高优先级,它不会被本地配置覆盖。
  • bootstrap 主要用于负责从外部源加载配置属性并解析。
  • 这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。

7.多模块共用一个相同配置文件

8.覆盖Bean

1.Bean 注册优先级:

  • 具有 @ComponentScan注解的bean优先注册
  • 具有 @Configuration 注解的bean
  • 具有 @Controller @Service @Repository @Component 等常用注解的bean
  • 被@Import注解导入的Bean
  • 被 实现了ImportSelector接口的类导入的Bean
  • 被 实现了ImportBeanDefinitionRegistrar接口的类导入的Bean
  • 被 BeanDefinitionRegistry 动态注入的Bean (属于懒加载,在没有被Spring进行getBean查找时,不会执行初始化方法)

2.覆盖bean方法
(1)使用 @Primary 进行覆盖

(2)通过指定扫描顺序 @SpringBootApplication(scanBasePackages = {“com.dji.“,”com.openmap.“}),后面的覆盖前面的。

(3)使用 BeanDefinitionRegistryPostProcessor

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
@Configuration
@Slf4j
public class DroneOsdRouter implements BeanDefinitionRegistryPostProcessor {

@Bean
public IntegrationFlow osdRouterFlow() {

}

/**
* 因为我总是处理不了 原先注入的bean,所以就用了这种方法进行
* @param beanDefinitionRegistry
* @throws BeansException
*/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
String beanName= "osdRouterFlow";
beanDefinitionRegistry.removeBeanDefinition(beanName);
}

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

}
}

(4)使用 @Order 定义 Bean 的顺序,Ordered / @Order 只控制执行顺序, 不控制Spring初始化Bean 的顺序

(5)排除需要替换的jar包中的类

(6)@ComponentScan(basePackages = {“com.dji.“,”com.openmap.“}),和SpringBootApplication一样,后面的包会覆盖前面的包,但是这个比SpringbootApplication优先级更高。

(7)使用Spring @DependsOn控制bean加载顺序

参考文章:
【1】.Spring Bean 的重写与覆盖 这里使用了 implements BeanDefinitionRegistryPostProcessor 配置的方法,就是直接使用 postProcessBeanDefinitionRegistry 方法,将注入的bean删除掉
【2】.覆盖重写 原有Spring Bean的几种方式 1.直接在自己工程中建同包同类名的类进行替换;2.采用@Primary注解;3.排除需要替换的jar包中的类;4.@Bean 覆盖;5.使用BeanDefinitionRegistryPostProcessor;
【3】.SpringBoot相同名称bean的覆盖问题 从SpringBoot 2.1.0开始,默认禁用bean名称相同时的覆盖行为。spring.main.allow-bean-definition-overriding=true
【4】.常见小bug之Spring @Configuration 注解未生效 在启动类中修改了自动扫描的包和子包,所以扫描失败了。
【5】.Spring | @Order 与 Ordered 控制加载顺序 Ordered / @Order 只控制执行顺序, 不控制Spring初始化Bean 的顺序
【6】.如何正确控制springboot中bean的加载顺序总结 而当你在项目启动时需要提前做一个业务的初始化工作时,或者你正在开发某个中间件需要完成自动装配时。你会声明自己的Configuration类,但是可能你面对的是好几个有互相依赖的Bean。如果不加以控制,这时候可能会报找不到依赖的错误。但是你明明已经把相关的Bean都注册进spring上下文了呀。这时候你需要通过一些手段来控制springboot中的bean加载顺序。 误区:1.在标注了@Configuration的类中,写在前面的@Bean一定会被先注册;2.利用@Order这个标注能进行加载顺序的控制,目前用的比较多的有以下3点:控制AOP的类的加载顺序,也就是被@Aspect标注的类;控制ApplicationListener实现类的加载顺序;控制CommandLineRunner实现类的加载顺序
【7】.Spring Bean 注册顺序优先级总结 @DependsOn;@Order;@Bean 方法参数注入;@AutoConfigureOrder;@AutoConfigureBefore 和 @AutoConfigureAfter
【8】.使用Spring @DependsOn控制bean加载顺序
【9】.SpringBoot教程(9) @DependsOn 设置Bean依赖 结合@Lazy 修改Bean加载顺序
【10】.Spring Boot |如何让你的 bean 在其他 bean 之前完成加载 这个 beanDefinitionNames 列表的顺序就决定了 Bean 的创建顺序,那么这个 beanDefinitionNames 列表又是怎么来的?答案是 ConfigurationClassPostProcessor 通过扫描你的代码和注解生成的,将 Bean 扫描解析成 Bean 定义(BeanDefinition),同时将 Bean 定义(BeanDefinition)注册到 BeanDefinitionRegistry 中,才有了 beanDefinitionNames 列表。
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。