【微服务】spring读取配置文件多种方式深入详解

news/2024/5/6 4:06:48

目录

一、前言

二、java配置文件介绍

2.1 java配置文件产生原因

2.2 项目使用配置文件好处

2.3 springboot项目配置文件的必要性

2.4 微服务架构下配置文件使用场景

三、java读取配置文件常用方法

3.1 使用Properties类读取配置文件

3.1.1 使用getResourceAsStream读取

3.1.2 使用getClassLoader读取

3.2 使用ClassLoader读取配置文件

四、spring中读取配置文件常用方法

4.1 使用ClassPathResource读取

4.2 使用PropertyResourceBundle读取

4.3 使用PropertiesLoaderUtils 读取

4.4 使用FileSystemResource读取

4.4.1 使用FileSystemXmlApplicationContext读取

4.4.2 使用ClassPathXmlApplicationContext读取

五、springboot读取配置文件常用方法

5.1 使用@Value注解读取

5.1.1 读取单个属性值

5.1.2 使用默认值

5.1.3 支持spel表达式

5.2 @ConfigurationProperties 读取配置文件

5.2.1 @ConfigurationProperties 读取配置文件原理

5.2.2 @ConfigurationPropertiess补充点1

5.2.2 @ConfigurationProperties补充点2

5.2.3 @ConfigurationProperties补充点3

5.2.4 @ConfigurationProperties补充点4

5.3 使用 @PropertySource 读取配置文件

5.3.1 @PropertySource 读取配置文件原理

5.4 使用Environment 读取配置文件

5.4.1 Environment读取配置文件原理

5.5 使用原生方式读取配置文件

六、springboot读取外部配置文件

6.1 操作过程

6.1.1 搭建nacos服务

6.1.2 增加两个配置文件

6.1.3 引入pom依赖

6.1.4 添加配置文件

6.1.4 增加测试接口读取配置

七、写在文末


一、前言

在使用spring或springboot项目开发中,难免会涉及到读取配置文件的各种配置参数的情况,因为当项目的规模上去之后,在单个配置文件中维护所有的配置信息很难满足实际的需要,所以随着微服务技术的流行,用于统一管理和维护配置文件的第三方组件就随之产生了,譬如大家熟悉的nacos,appollo等。

二、java配置文件介绍

2.1 java配置文件产生原因

Java项目中配置文件的产生,是为了解决软件开发中的配置管理问题。随着软件系统规模的增大和复杂程度的提高,应用程序需要的配置信息也会变得越来越多。如果将这些配置信息硬编码在代码中,结果会导致代码可读性差、维护困难,并且修改配置信息需要重新编译和部署代码,不利于灵活性和可维护性。

因此,为了更好的管理和维护配置信息,开发人员开始将配置信息从代码中分离出来,存放到外部的配置文件中。这样,开发人员可以通过修改配置文件来调整应用程序的行为,而无需修改源代码。同时,配置文件的存在使得配置信息更易于共享、重用和管理,提高了代码的可维护性和灵活性。

总结起来,Java项目配置文件的产生是为了优化配置管理、提高代码可维护性和灵活性,在实际开发中起着非常重要的作用。

2.2 项目使用配置文件好处

通过上面的介绍以及开发中总结的经验,可以说java项目引入配置文件之后优势是很明显的,具体来说包括:

  • 灵活性

    • 配置文件使得应用程序的配置信息与代码分离,可以根据需要随时修改配置而不必重新编译代码。这种灵活性使得应用程序更易于维护和扩展。

  • 安全性

    • 敏感信息(如数据库连接信息、密码等)通常不应硬编码在代码中,通过配置文件可以将这些敏感信息单独存放,加密或者做一些安全处理,避免泄露。

  • 可重用性

    • 配置文件可以被多个模块或组件共享使用,避免了重复配置的问题。同时,配置文件的内容可以在不同项目中重复利用,提高开发效率。

  • 易于管理

    • 将配置信息集中到配置文件中,便于统一管理和查看应用程序的各项配置参数,方便开发人员对配置进行修改和调整。

  • 环境适配

    • 通过配置文件可以为不同的环境(开发、测试、生产)配置不同的参数,应用程序能够方便的适配不同的部署环境。

使用配置文件能够提高Java应用程序的可维护性、灵活性和安全性,是一种良好的开发实践。

2.3 springboot项目配置文件的必要性

当前,在我们讨论微服务开发时,很容易想到底层框架使用springboot,springboot的使用让微服务的开发变得更简单,因此围绕着springboot开发来说,项目涉及到的配置文件越来越多,也越来越复杂时,使用配置文件就显得非常必要了,具体来说,Spring Boot项目配置文件的必要性在于它为开发人员提供了一种灵活且方便的方式来管理应用程序的配置信息。以下是几个主要原因:

  • 外部化配置

    • 使用配置文件,可以将应用程序的配置参数从代码中分离出来,使配置更易于修改和维护。通过配置文件,开发人员可以根据不同环境(开发、测试、生产)或需求来定制不同的配置,而无需修改代码。

  • 注入配置信息

    • Spring Boot框架支持将配置文件中的配置信息注入到应用程序中,开发人员可以通过注解或属性文件的方式轻松地获取配置参数,并在应用程序中使用这些参数。

  • 自动装配

    • Spring Boot会自动加载并解析应用程序的配置文件,根据配置信息来完成各种组件的初始化和装配工作。这样可以简化开发流程,减少手动配置的工作量。

  • 多环境支持

    • Spring Boot允许开发人员为不同的环境(如开发、测试、生产)创建不同的配置文件,使得应用程序在不同环境下能够正确加载相应的配置信息。

总之,Spring Boot项目配置文件的存在使得配置信息可灵活管理,并且与代码分离,有助于提高代码的可维护性、扩展性和可读性。因此,配置文件在Spring Boot项目中是非常必要的。

2.4 微服务架构下配置文件使用场景

在微服务开发中,配置文件可以说是必不可少的,不管是服务工程本身的配置文件,还是使用外部的配置文件,比如读取来自配置中心的配置信息,都是对现有的架构设计中很好的补充,具体来说,微服务架构中配置文件的使用场景主要有以下几个方面:

  • 服务发现与注册

    • 微服务架构中的服务通常会通过服务发现机制来注册和发现其他服务。配置文件可以包含服务的注册信息(如地址、端口等),帮助服务实例在运行时正确注册到服务注册中心,并能够让其他服务发现并调用该服务。

  • 动态配置管理

    • 微服务架构下,服务的配置可能需要频繁变更,例如数据库连接信息、日志级别、缓存设置等。通过配置文件,可以实现动态配置管理,使得服务在运行时可以根据配置文件的变化自动加载最新的配置参数,而不需要重启服务。

  • 环境切换

    • 微服务通常会部署在多个环境(如开发、测试、生产)中。通过配置文件可以区分不同环境下的配置参数,使得服务能够根据当前所处环境加载相应的配置信息,从而保证服务在不同环境下正常运行。

  • 敏感信息管理

    • 微服务架构中,一些敏感的配置信息(如密码、密钥等)往往不适宜明文写在代码中。通过配置文件可以对这些敏感信息进行加密处理,提高系统的安全性。

  • 版本控制

    • 将配置信息存放在配置文件中,有利于进行版本控制。开发团队可以轻松地跟踪配置文件的变化历史,并进行回滚或比较不同版本的配置信息。

总的来说,微服务架构中配置文件的使用场景涵盖了服务注册、动态配置管理、环境切换、敏感信息管理以及版本控制等方面,是微服务开发中不可或缺的重要组成部分。

三、java读取配置文件常用方法

在java中,可以通过多种方式读取外部的配置文件,下面提供几种常用的方式。工程目录结构如下:

3.1 使用Properties类读取配置文件

3.1.1 使用getResourceAsStream读取

在resources目录下提供一个config.properties的配置文件,配置内容如下:

server.name=testApp
server.port=8088

默认情况下,maven工程中可以读取到resources目录下的文件,而不用加resources作为绝对路径,参考如下示例:

    @Testpublic void test1() throws IOException {InputStream inputStream = this.getClass().getResourceAsStream("/config.properties");Properties properties = new Properties();properties.load(inputStream);properties.list(System.out);System.out.println("==============================================");String serverName = properties.getProperty("server.name");String serverPort = properties.getProperty("server.port");System.out.println("serverName = " + serverName);System.out.println("serverPort = " + serverPort);}

但是如果是在resources目录下自定义的其他目录下,像下面这样

此时,如果使用Properties读取里面的配置文件,可以想下面这样;

    @Testpublic void readRedisProperties() throws IOException {InputStream inputStream = this.getClass().getResourceAsStream("/config/redis.properties");Properties properties=new Properties();properties.load(inputStream);System.out.println("redis.host="+properties.getProperty("redis.host"));System.out.println("redis.port="+properties.getProperty("redis.port"));}

3.1.2 使用getClassLoader读取

如果使用getClassLoader的方式读取配置文件,此时则修改为下面的写法

    /*** 读取config.properties* @throws IOException*/@Testpublic void readProperties2() throws IOException {InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config.properties");Properties properties=new Properties();properties.load(inputStream);String serverName = properties.getProperty("server.name");String serverPort = properties.getProperty("server.port");System.out.println("serverName = " + serverName);System.out.println("serverPort = " + serverPort);}/*** 读取config/redis.properties* @throws IOException*/@Testpublic void readRedisPropertiesV2() throws IOException {InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("config/redis.properties");Properties properties=new Properties();properties.load(inputStream);System.out.println("redis.host="+properties.getProperty("redis.host"));System.out.println("redis.port="+properties.getProperty("redis.port"));}	

上面通过两种方式都可以读取到配置文件内容的信息,但是两者还是有区别的,具体来说:

  • Class.getResourceAsStream(),是 从当前类所在的位置开始查找配置文件位置;

    • 要找到config.properties和redis.properties必须加/从classpath下开始查找;

  • Class.getClassLoader().getResourceAsStream() ;

    • 默认就从classpath路径下开始查找,加上/会报空指针;

3.2 使用ClassLoader读取配置文件

也可以使用ClassLoader来进行读取和加载配置文件到Properties中

    @Testpublic void readRedisPropertiesV3() throws IOException {InputStream inputStream = ClassLoader.getSystemResourceAsStream("config.properties");Properties properties=new Properties();properties.load(inputStream);System.out.println("server.name="+properties.getProperty("server.name"));System.out.println("server.port="+properties.getProperty("server.port"));}

四、spring中读取配置文件常用方法

在spring或springboot中,除了上述java默认提供的配置文件读取的方法外,还有其他的方式,下面介绍一些常用的读取方法。

4.1 使用ClassPathResource读取

在使用spring进行开发中,可以利用ClassPathResource这个类进行加载读取

    @Testpublic void readProperties4() throws IOException {ClassPathResource resource = new ClassPathResource("config.properties");Properties properties= PropertiesLoaderUtils.loadProperties(resource);System.out.println("server.name="+properties.getProperty("server.name"));System.out.println("server.port="+properties.getProperty("server.port"));}

4.2 使用PropertyResourceBundle读取

ResourceBundle没有继承什么类,是一个单个的抽象类,该类可以说是国际化版的Properties,简单说就是可以根据本地化或语言的不同读取不同的配置文件。

    @Testpublic void readProperties5() throws IOException {InputStream inputStream = ClassLoader.getSystemResourceAsStream("config.properties");PropertyResourceBundle bundle = new PropertyResourceBundle(inputStream);System.out.println(bundle.getString("server.name"));System.out.println(bundle.getString("server.port"));}

也可以不用输入后缀,像下面这样,之所以可以这样写,与ResourceBundle自身的配置文件读取机制有关。

    @Testpublic void readProperties6()  {ResourceBundle bundle=ResourceBundle.getBundle("config/redis");System.out.println(bundle.getString("redis.host"));System.out.println(bundle.getString("redis.port"));}

4.3 使用PropertiesLoaderUtils 读取

Spring 提供的 PropertiesLoaderUtils 允许您直接通过基于类路径的文件地址加载属性资源。这种方式最大的好处就是:实时加载配置文件,修改后立即生效,不必重启。参考下面的示例:

    @Testpublic void springUtilTest() throws Exception {Properties props = PropertiesLoaderUtils.loadAllProperties("config.properties");for (Object key : props.keySet()) {System.out.print(key + ":");System.out.println(props.get(key));}}

4.4 使用FileSystemResource读取

在spring项目中,加载项目外的配置文件时,可以考虑使用FileSystemResource进行读取,比如加载配置文件中的信息为容器管理的bean时;

    @Testpublic void testFileSystemResource() {Resource resource = new FileSystemResource("D:\applicationContext.xml");BeanFactory beanFactory = new XmlBeanFactory(resource);UserService userService = (UserService) beanFactory.getBean("userService");System.out.println(userService);}

类似的,针对不同类型的配置文件,spring还提供了很多种写法,如下。

4.4.1 使用FileSystemXmlApplicationContext读取

解析并获取配置文件中定义bean的数量

    @Testpublic void test05() {FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("C:/applicationContext.xml");定义bean的总数System.out.println(context.getBeanDefinitionCount());}

4.4.2 使用ClassPathXmlApplicationContext读取

解析并获取配置文件中定义的指定的bean信息

@Test
public void test06() {String[] filepath = {"applicationContext.xml"};ClassPathXmlApplicationContext factory = new ClassPathXmlApplicationContext(filepath);UserService studentService = (UserService) factory.getBean("userService");}

五、springboot读取配置文件常用方法

springboot基于spring的基础上,做了更多功能上的扩展升级,在配置文件读取和使用方面,也做了更丰富的补充,从而完成更复杂的对于配置文件读取和加载使用的功能,Spring Boot 中读取配置文件有以下 5 种方法:

  • 使用 @Value 读取配置文件。

  • 使用 @ConfigurationProperties 读取配置文件。

  • 使用 Environment 读取配置文件。

  • 使用 @PropertySource 读取配置文件。

  • 使用原生方式读取配置文件。

如下,在springboot工程中有一个application.yml配置文件,这也是springboot项目中经常使用的最重要的配置文件之一,有如下几行配置内容:

server:port: 8088user:pro:name: jerryage: 28city: beijing

下面通过不同的方式读取上述的配置信息。首先,需要为工程引入springboot的单元测试类

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>

5.1 使用@Value注解读取

@Value注解是Spring Framework中的一个注解,它可以用来将外部配置文件中的值注入到Spring Bean中。通过在字段或setter方法上使用@Value注解,我们可以直接从属性文件、环境变量或其他地方读取配置值,并注入到Spring Bean中。

5.1.1 读取单个属性值

从配置文件中读取某个属性值,如下代码所示:

@SpringBootTest(classes = BootApp.class)
@RunWith(SpringRunner.class)
public class ConfigTest {@Value("${user.pro.name}")private String name;@Testpublic void readConfigTest1(){System.out.println("user.pro.name == " + name);}}

如果是放在一个类中,像下面这样,则表示,@Value("${my.property}")会从配置文件(如application.properties或application.yml)中读取名为my.property的属性值,并注入到myProperty字段中。

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class MyComponent {@Value("${my.property}")private String myProperty;
}

5.1.2 使用默认值

像下面这样,如果从配置文件中读取不到user.pro.work的属性值,则会使用默认值manager

    @Value("${user.pro.work:manager}")private String name;@Testpublic void readConfigTest1(){System.out.println("user.pro.name == " + name);}

5.1.3 支持spel表达式

可以使用SpEL表达式来动态计算属性值。在下面这个例子中,javaHome属性的值将会是Java安装目录的路径。

    @Value("#{systemProperties['java.home']}")private String javaHome;@Testpublic void readConfigTest1(){System.out.println("user.pro.name == " + name);System.out.println("systemProperties == " + javaHome);}

5.2 @ConfigurationProperties 读取配置文件

@ConfigurationProperties 和 @Value 的使用略微不同,@Value 是读取单个配置项的,而 @ConfigurationProperties 是读取一组配置项的,我们可以使用 @ConfigurationProperties 加实体类读取一组配置项:

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;@Data
@ConfigurationProperties(prefix = "user.pro")
@Configuration
public class UserProperties {private String name;private String city;private Integer age;}

其中 ,prefix 表示读取一组配置项的根 name,相当于 Java 中的类名,最后再把此配置类,注入到某一个类中就可以使用了,如下代码所示:

    @Autowiredprivate UserProperties userProperties;@Testpublic void readUserProperties(){System.out.println("userName :" + userProperties.getName());System.out.println("userAge == " + userProperties.getAge());System.out.println("userCity == " + userProperties.getCity());}

5.2.1 @ConfigurationProperties 读取配置文件原理

@ConfigurationProperties注解是Spring Boot中一个用于绑定配置属性的注解,通过它可以将配置文件中的属性值自动绑定到Java对象的属性上。这样可以方便地将配置文件中的属性与Java对象关联起来,实现配置信息的读取和管理。该注解实现原理如下:

  • 定义@ConfigurationProperties注解:

    • 在Java类中使用@ConfigurationProperties注解来标识需要绑定配置属性的类或属性。

  • 加载配置文件:

    • Spring Boot会加载classpath下的application.properties或application.yml等配置文件,并将这些配置文件中的属性值存储在Environment中。

  • 自动绑定配置属性:

    • 当@ConfigurationProperties注解和Java类结合使用时,Spring Boot会自动将配置文件中的属性值与Java对象的对应属性进行绑定。要求Java对象的属性名与配置文件中的属性名一致,支持驼峰命名和短横线分隔命名的映射。

  • 属性值注入:

    • 通过@ConfigurationProperties注解,可以直接将配置文件中的属性值注入到Java对象的属性中,从而实现配置信息的读取和管理。

5.2.2 @ConfigurationPropertiess补充点1

在实际使用中,有下面一点容易忽略,即在配置文件中,如果配置信息以英文-结尾,在配置类中,属性定义时可以写成驼峰形式,如下配置文件中增加一个属性:

user:pro:name: jerryage: 28city: beijingcurrent-address: shanghai

在类中则可以像下面这样编写

@Data
@ConfigurationProperties(prefix = "user.pro")
@Configuration
public class UserProperties {private String name;private String city;private Integer age;private String currentAddress;
}

5.2.2 @ConfigurationProperties补充点2

@ConfigurationProperties注解既可以在类上使用,也可以使用在@Bean注解上面,如下,我们定义一个bean,然后使用该注解将配置参数引用,使用步骤如下:

新增如下配置信息

app:config:app-name: user-appapp-url: 192.168.1.332remote-validate: true

定义一个类,类中的属性与配置文件中的属性保持一致

@Data
public class AppConfigProperties {private String appName;private String appUrl;private boolean remoteValidate;
}

定义一个配置类,再在标注为@Bean的方法上使用@ConfigurationProperties注解

@Component
public class AppConfig {@Bean@ConfigurationProperties(prefix = "app.config")public AppConfigProperties appConfigProperties(){return new AppConfigProperties();}
}

最后在需要的地方注入该AppConfigProperties类,由于被作为bean纳入到spring容器中了,在下面的接口中就可以直接使用;

@RestController
public class AppController {@Autowiredprivate AppConfigProperties appConfigProperties;//localhost:8088/getAppConfig@GetMapping("/getAppConfig")public String getAppConfig(){String appName = appConfigProperties.getAppName();String appUrl = appConfigProperties.getAppUrl();return appName +  " - " +appUrl;}
}

5.2.3 @ConfigurationProperties补充点3

在有些第三方组件的源码或spring源码中,还能看到配置类中的bean互相引用的情况,比如下面这样:

@Component
public class AppConfig {@Bean@ConfigurationProperties(prefix = "app.config")public AppConfigProperties appConfigProperties(){return new AppConfigProperties();}@Beanpublic UploadComponent uploadComponent(@Qualifier("appConfigProperties") AppConfigProperties appConfigProperties){UploadComponent uploadComponent = new UploadComponent();uploadComponent.setAppConfigProperties(appConfigProperties);return uploadComponent;}}

在当前的配置类中,除了AppConfigProperties会被实例化为一个bean,同时需要实例化的bean还有UploadComponent这个类,该类代码如下:

@Data
public class UploadComponent {private AppConfigProperties appConfigProperties;public void upload(){System.out.println("upload url :" + appConfigProperties.getAppUrl());}
}

UploadComponent作为Bean的实例化过程如下:

  • 容器示例化名为uploadComponent的bean;

  • uploadComponent实例化过程中检测到还有参数AppConfigProperties,于是检测容器中是否有AppConfigProperties实例化对象,然后作为方法参数注入进来;

    • 如果方法参数之前使用了@Qualifier,则注解中的值与上述已完成的AppConfigProperties实例bean名称一致即可;

  • uploadComponent将AppConfigProperties实例拿过来使用,设置为类的属性,最后作为spring的bean完成实例化;

5.2.4 @ConfigurationProperties补充点4

在配置文件中,如果想要将配置信息以集合的形式读取出来该怎么办呢?比如下面这样,相同的配置信息有多行:

spring:test:orders:- order-id: 001order-name: 批次订单1addr: 杭州- order-id: 002order-name: 批次订单2addr: 武汉

首先,仍然定义一个类

@Data
public class OrderProperties {private String orderId;private String orderName;private String addr;
}

定义一个配置类,属性为OrderProperties的集合,属性值为orders

@Configuration
@ConfigurationProperties(prefix = "spring.test")
@Data
public class OrderConfig {private List<OrderProperties> orders;}

然后再在使用的地方注入OrderConfig即可

    @Autowiredprivate OrderConfig orderConfig;//localhost:8088/getOrderConfig@GetMapping("/getOrderConfig")public List<OrderProperties> getOrderConfig(){List<OrderProperties> orderProperties = orderConfig.getOrders();return orderProperties;}

5.3 使用 @PropertySource 读取配置文件

使用 @PropertySource 注解可以用来指定读取某个配置文件,比如指定读取 application.properties 配置文件的配置内容,如下,仍然以读取resources目录下的config配置文件为例进行说明,首先在启动类中使用@PropertySource 注解引入该配置

@SpringBootApplication
@PropertySource("classpath:config.properties")
public class BootApp {public static void main(String[] args) {SpringApplication.run(BootApp.class,args);}}

再在需要的地方使用@Value注入即可使用,比如在下面的测试接口中即可使用

@RestController
public class TestController {@Value("${server.name}")private String serverName;//localhost:8088/get@GetMapping("/get")public String getProperties(){System.out.println(serverName);return serverName;}}

如果出现了中文乱码,可以使用下面指定编码的方式处理

@PropertySource(value = "config.properties", encoding = "utf-8")

5.3.1 @PropertySource 读取配置文件原理

在Spring框架中,@PropertySource注解用于指定外部属性文件的位置,并将其加载到Spring的Environment中,以供应用程序使用。@PropertySource注解通常与@Value注解一起使用,用于读取配置文件中的属性值。该注解的使用原理如下:

  • 注解定义:

    • 开发者在Spring配置类中使用@PropertySource注解来指定外部属性文件的位置,可指定一个或多个属性文件路径,Spring会自动加载这些文件;

  • 加载属性文件:

    • 当Spring容器启动时,会扫描带有@PropertySource注解的配置类,并加载指定的属性文件。这些属性文件通常包含键值对形式的配置信息,比如key=value;

  • 属性文件解析:

    • Spring框架会解析属性文件中的配置信息,并将其存储到Environment对象中。这样,应用程序就可以通过Environment对象来获取配置属性的值了;

  • 使用@Value注解注入:

    • 开发者可以使用@Value注解来注入属性文件中的属性值。通过@Value("${key}")的方式,可以直接从Environment中获取对应键的值,从而在代码中使用配置属性。

总结来说,@PropertySource注解作用是指定外部属性文件的位置,并将其加载到Spring的Environment中,方便应用程序读取和使用配置信息。结合@Value注解,就可以方便的在Spring应用程序中使用外部配置文件中的属性值。

5.4 使用Environment 读取配置文件

在Spring Boot中,可以使用Environment对象来读取配置文件中的属性。Environment是Spring框架中用于表示当前运行环境的接口,可以通过它来获取应用程序的配置信息。Environment的主要作用是提供统一的访问方式来获取应用程序的配置信息,包括系统属性、环境变量、命令行参数以及配置文件中的属性。它将这些配置信息统一管理,并提供了各种方法来获取和操作这些配置属性。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.core.env.Environment;@RestController
public class TestController {@Autowiredprivate Environment environment;//localhost:8088/getEnvironment@GetMapping("/getEnvironment")public String getEnvironment(){String serverPort = environment.getProperty("server.port");System.out.println(environment.getProperty("server.port"));return serverPort;}
}

5.4.1 Environment读取配置文件原理

在Spring Framework中,Environment接口代表了应用程序运行时环境,可以用于读取配置属性,在Spring Boot中,Environment的实现类是StandardEnvironment。其读取配置文件的原理如下:

  • 加载配置文件:

    • Spring Boot会自动加载classpath下的application.properties或application.yml等配置文件,这些配置文件中定义的属性会被解析并保存到Environment中。

  • 解析配置属性:

    • 通过Environment的getProperty()方法可以获取指定属性的值,该方法会首先从系统属性、环境变量、命令行参数等位置查找属性值,然后再依次从配置文件中查找。

  • 使用@Value注解:

    • 除了通过getProperty()方法获取属性值外,还可以使用@Value注解来注入属性值。@Value注解可以直接从Environment中获取配置属性的值,简化了代码编写。

5.5 使用原生方式读取配置文件

还可以使用最原始的方式 Properties 对象来读取配置文件,如下代码所示

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Properties;@Configuration
public class PropertiesConfig implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {Properties props = new Properties();try {InputStreamReader inputStreamReader = new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("config.properties"),StandardCharsets.UTF_8);props.load(inputStreamReader);System.out.println(props.getProperty("server.name"));} catch (IOException e) {System.out.println(e.getMessage());}}
}

六、springboot读取外部配置文件

如今,微服务开发在技术选型中通常会直接集成第三方框架,比如使用springcloud、dubbo等作为微服务框架进行开发,基于框架之下,通常都会使用统一的外部配置中心作为配置文件集中管理的地方,因此在读取配置文件时,会稍有区别,下面以springboot中读取nacos配置中心文件为例进行说明。

6.1 操作过程

6.1.1 搭建nacos服务

搭建nacos服务,这里我使用docker快速搭建了一个nacos2.X版本的服务

6.1.2 增加两个配置文件

在控制台界面上,增加如下两个配置文件,关于nacos配置文件的命名规则,可以参考这篇文章,nacos使用详解

nacos-config-client-dev.yml配置内容如下:

common.yml配置内容如下,common配置文件将会作为多个微服务项目的共享配置文件使用

6.1.3 引入pom依赖

需要注意的是,导入nacos依赖时,springcloud-alibaba版本与springboot版本的匹配

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.2.RELEASE</version><relativePath/></parent><!-- 统一管理jar包版本 --><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><log4j.version>1.2.17</log4j.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.2.2.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Hoxton.SR1</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.1.0.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--nacos-config 配置中心-自带动态刷新--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--nacos-discovery 注册中心-服务发现与注册--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>

6.1.4 添加配置文件

使用nacos作为配置文件中心时,在springboot工程中定义配置文件时,需要引入bootstrap.yaml配置文件,通过该文件优先加载nacos的配置文件。

bootstrap.yaml配置文件内容


server:port: 8087spring:profiles:active: devapplication:#这里的名称和nacos中的配置文件名称保持一致name: nacos-config-clientcloud:nacos:discovery:server-addr: IP:8848config:server-addr: IP:8848#指定要加载的配置文件的格式后缀名file-extension: ymlgroup: DEFAULT_GROUPext-config:- data-id: common.ymlgroup: DEFAULT_GROUPrefresh: true

application.yaml配置文件中,可以定义一些常规的配置信息即可。

6.1.4 增加测试接口读取配置

通过代码不难看出,在配置的使用上,也是通过@Value注解,将需要使用的配置内容注入即可

@RestController
@RefreshScope
public class NacosController {@Value("${config.info.name}")private String configName;@Value("${app.center.key}")private String appCenterKey;//localhost:8087/get/config@GetMapping("/get/config")public String getConfigName(){return configName;}//localhost:8087/get/key@GetMapping("/get/key")public String getCommonConfig(){return appCenterKey;}}

七、写在文末

本文通过较大的篇幅详细分享了java中读取配置文件的各种方式,从spring到springboot中各种读取配置文件的方式通过案例进行了详细的说明,可以说,对配置文件的使用和维护是日常开发中的一项重要内容,使用得当,可以给开发带来相当的便利,有必要全面深入的掌握,本篇到此结束,感谢观看。


http://www.mrgr.cn/p/02216012

相关文章

STM32 USB虚拟串口

电路原理图 usb部分 晶振部分 usb与单片机连接 配置信息 sys配置信息 rcc配置信息 usb配置信息 虚拟串口配置信息 时钟配置信息 项目配置信息 代码 包含文件 主函数代码 实验效果 修改接收波特率依然可以正常接收&#xff0c;也就是说单片机可以自动适应上位机的波特率设置。…

Linux 深入理解Linux文件系统与日志分析

在Linux系统中&#xff0c;文件名和文件数据是分开存储的 文件数据包含 元信息(即不包含文件名的文件属性) 和 实际数据 文件元信息存储在 inode(索引节点)里&#xff0c; 文件实际数据存储在 block(块)里; 文件名存储在目录块里 查看文件的元信息 stat 文件名 [ro…

HDFS详解(Hadoop)

Hadoop 分布式文件系统&#xff08;Hadoop Distributed File System&#xff0c;HDFS&#xff09;是 Apache Hadoop 生态系统的核心组件之一&#xff0c;它是设计用于存储大规模数据集并运行在廉价硬件上的分布式文件系统。 1. 分布式存储&#xff1a; HDFS 将文件分割成若干块…

【AI开发:音频】二、GPT-SoVITS使用方法和过程中出现的问题(GPU版)

1.FileNotFoundError: [Errno 2] No such file or directory: logs/guanshenxxx/2-name2text-0.txt 这个问题中包含了两个&#xff1a; 第一个&#xff1a;No module named pyopenjtalk 我的电脑出现的就是这个 解决&#xff1a;pip install pyopenjtalk 第二个&#xff1a…

Elasticsearch进阶篇(三):ik分词器的使用与项目应用

ik分词器的使用 一、下载并安装1.1 已有作者编译后的包文件1.2 只有源代码的版本1.3 安装ik分词插件 二、ik分词器的模式2.1 ik_smart演示2.2 ik_max_word演示2.3 standard演示 三、ik分词器在项目中的使用四、ik配置文件4.1 配置文件的说明4.2 自定义词库 五、参考链接 一、下…

MIMO-UNet复现,DeepRFT复现及总结

最近复现了去模糊网络MIMO-UNet及变体DeepRFT&#xff0c;并以此文做一个总结&#xff1a; 复现MIMO-UNet部分&#xff1a; 1.通过上一篇博文&#xff0c;我们已经知道了MIMO-UNet网络的大致组成结构 2.通过源网络的main.py文件&#xff0c;我们可以知道该网络间隔100轮保存一…

AI助力科研创新与效率双提升:ChatGPT深度科研应用、数据分析及机器学习、AI绘图与高效论文撰写

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其在…

Windows 安装 A UDP/TCP Assistant 网络调试助手

Windows 安装 A UDP/TCP Assistant 网络调试助手 0. 引言1. 下载地址2. 安装和使用 0. 引言 需要调试一个实时在线聊天程序&#xff0c;安装一个UDP/TCP Assistant 网络调试助手&#xff0c;方便调试。 1. 下载地址 https://github.com/busyluo/NetAssistant/releases 2. 安…

Mac多媒体播放器 Movist Pro v2.11.4中文激活版下载

Movist Pro for Mac是一款专业的媒体播放器&#xff0c;特别为Mac用户设计。它不仅界面简洁美观&#xff0c;而且功能强大&#xff0c;能满足用户各种播放需求。 Movist Pro v2.11.4中文激活版下载 首先&#xff0c;Movist Pro for Mac支持多种媒体文件的播放&#xff0c;包括视…

罗尔(Rolle)中值定理

introduce 罗尔(Rolle)中值定理是微分学中一条重要的定理,是三大微分中值定理之一,其他两个分别为:拉格朗日(Lagrange)中值定理、柯西(Cauchy)中值定理。definition 若\(f(x)\)满足下列条件:在闭区间\([a,b]\)连续在开区间\((a,b)\)可导\(f(a)=f(b)\)则必有 \(\xi\) 属于\(…

Redis入门到通关之Redis数据结构-List篇

文章目录 ☃️概述☃️数据结构☃️源码☃️其他 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博客 关于博主&#xff1a; 我是 请回答1024&#xff0c;一个追求数学与计算的边界、时间与空间的平衡&#xff0c;0与1的延伸的后端…

【NLP】大语言模型基础之GPT

大语言模型基础之GPT GPT简介1. 无监督预训练2. 有监督下游任务微调 GPT-4体系结构1. GPT-4的模型结构2. GPT-4并行策略3. GPT-4中的专家并行GPT-4的特点 参考连接 以ELMo为代表的动态词向量模型开启了语言模型预训练的大门&#xff0c;此后&#xff0c;出现了以GPT和BERT为代表…

【Linux学习】Linux进程(二)

文章目录 &#x1f4d5;查看进程&#x1f680;/proc目录&#x1f680;cwd与exe &#x1f4d5;改变进程的工作目录&#x1f680;chdir指令 &#x1f4d5;vim卡住了怎么解决 本篇文章接着【LInux进程&#xff08;一&#xff09;】继续编写。 &#x1f4d5;查看进程 &#x1f68…

《统计学习方法》 第4章 朴素贝叶斯法

文章目录 前言一、朴素贝叶斯法二、朴素贝叶斯法的学习和分类三、朴素贝叶斯算法四、贝叶斯估计总结 前言 本文只要记录一些书中的一些小知识点&#xff0c;挑一些本人认为重要的地方进行总结。 各位道友&#xff01;道长(zhǎng) 道长(chǎng) 一、朴素贝叶斯法 朴素贝叶斯…

最新AI创作系统ChatGPT网站源码Midjourney-AI绘画系统,Suno-v3-AI音乐生成大模型。

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

用于车载T-BOX汽车级的RA8900CE

用于车载T-BOX等高精度计时的汽车级时钟模块RTC:RA8900CE.车载实时时钟芯片RA8900CE内置32.768Khz的晶体&#xff0c;实现年、月、日、星期、小时、分钟和秒精准计时。RA8900CE满足AEC-Q200认证&#xff0c;内置温补功能&#xff0c;保证实时时钟的稳定可靠&#xff0c;功耗低至…

c++ - 模板(一)

文章目录 一、函数模板 一、函数模板 1、概念 函数模板代表了一个函数家族&#xff0c;该函数模板与类型无关&#xff0c;在使用时被参数化&#xff0c;根据实参类型产生函数的特定 类型版本。 2、原理 函数模板是一个蓝图&#xff0c;它本身并不是函数&#xff0c;是编译器用…

ADOP带您科普:精准分配/稳定传输:光纤耦合器的未来

光纤自环器&#xff0c;也称为光模块自环测试回路器&#xff0c;用于测试系统或网络系统中的信号回传。通过回传信号&#xff08;主要是成对连接TX发射端到RX的接收端一侧&#xff09;&#xff0c;可以检测网络链路中各种潜在的异常。 让我们深入了解一下这个设备的作用和分类&…

Spring Boot 的文件配置

SpringBoot的配置文件,有三种格式 1.properties 2.yaml 3.yml(yaml的简写) 这里主要介绍1和3格式的。 在项目中,同时存在properties和yml配置文件, properties的优先级更高 同时存在时,两个文件都生效 如果两个文件中,都包含同一个配置,以properties为主。 properties的配置…

oracle 12c+ max_string_size参数

一个客户的数据库版本是19.3,在做数据库复制的时候,目标端报错了,查看了一下问题发现表的字段长度有不对,在12c以前我们都知道varchar的长度最大是4000,但是客户这里居然有32767: 把客户的建表语句弄出来,放到我的一个19c的测试环境进行测试: 发现报错了: 这里报错很明显了,是M…