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

目录

一、前言

二、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.mzph.cn/pingmian/1293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

时序分析基础(6)——input delay时序分析

1 简介 FPGA对于外部的时钟以及数据的延时信息是不知道的&#xff0c;在低速时钟且时钟发射沿在数据正中心的时候&#xff0c;一般可以不做约束来直接使用。但是到了高速时钟或者双沿采样或者发射沿和数据对齐的情况下&#xff0c;这时候就需要告诉VIVADO外部的时钟与数据情况来…

多轴机械臂/正逆解/轨迹规划/机器人运动学/Matlab/DH法 学习记录03——机械臂运动学逆解

系列文章目录 本科毕设正在做多轴机械臂相关的内容&#xff0c;这里是一个学习机械臂运动学课程的相关记录。 如有任何问题&#xff0c;可发邮件至layraliufoxmail.com问询。 1. 数学基础 2. 机械臂几何法与DH表示法 3. 机械臂运动学逆解 文章目录 系列文章目录一、引言1.手臂…

文件系统和软硬链接

文章目录 文件系统磁盘磁盘逻辑抽象inode 软硬链接软链接硬链接 文件系统 文件分为打开的文件和没有被打开的文件&#xff0c;而只有打开的文件是在内存的&#xff0c;也就是我们之前讲的&#xff0c;然而大部分文件都不是被打开的(当前不需要被访问的)&#xff0c;它们都在磁…

硬盘日常使用中的注意事项

硬盘是计算机中的重要存储设备,负责存储大量的数据。为了确保数据的完整性和硬盘的寿命,日常使用中需要注意以下几点: 避免震动和撞击:硬盘在工作时,内部的磁盘正在高速旋转,任何轻微的震动或撞击都可能导致磁盘损坏或数据丢失。因此,使用硬盘时应确保计算机放置稳定,避…

输电线路运行特性及简单电力系统潮流估算(二)

本篇为本科课程《电力系统稳态分析》的笔记。 本篇为这一章的第二篇笔记。上一篇传送门&#xff0c;下一篇传送门。 输电线路的运行特性 输电线路的空载运行特性 线路的等值电路如图所示。 由于是空载&#xff0c;则 S ~ 2 0 \widetilde{S}_20 S 2​0&#xff0c;可以计算…

4月阿里offer被毁,我该怎么进字节?

在校招求职的浪潮中&#xff0c;有些故事总是让人唏嘘不已。比如最近在社交平台上广泛讨论的一个话题&#xff1a;“4月阿里offer被毁&#xff0c;我该怎么进字节&#xff1f;”这不仅反映了当下职场的变动性&#xff0c;也映射了求职者在面对突如其来的变故时的无助与挣扎。 …

QT 按钮的工具提示tooltips设置字体大小颜色与背景

QT 按钮的工具提示tooltips设置字体颜色与背景 main.cpp添加 mainwindow.cpp添加全局配置&#xff1a; 构造函数中&#xff1a; QToolTip::setFont(font3); //按钮提示信息通用设置 如下&#xff1a; MainWindow_oq::MainWindow_oq(QWidget *parent) : QMainWindow(parent)…

光伏电站智能勘探:无人机优势及流程详解

随着科技和互联网技术的不断发展&#xff0c;无人机在各个领域的应用越来越广泛&#xff0c;其中之一就是光伏电站智能勘探。利用无人机高清摄像头和传感器等设备&#xff0c;可以对光伏电站周边环境、日照情况、房屋状态进行全方面的勘探和记录&#xff0c;搭配卫星勘探、实地…

C语言中scanf、gets、fgets的区别

scanf、gets和fgets都是C语言中用于从标准输入读取数据的函数&#xff0c;但它们之间存在一些重要的差异&#xff1a; scanf&#xff1a; scanf是一个格式化输入函数&#xff0c;它可以根据指定的格式从标准输入读取数据。使用scanf读取字符串时&#xff0c;需要小心处理缓冲区…

springboot注解开发如何映射对象型数据

创作灵感 最近在帮学校写一款小程序时&#xff0c;有这样一个数据需要展示&#xff1a;一条申请记录&#xff0c;里面包含了申请时间、申请状态、申请所提供的六条活动记录等待&#xff0c;其中&#xff0c;申请所提供的六条活动记录为一个数组&#xff0c;数组中的每个元素又…

【BUG】Hexo|GET _MG_0001.JPG 404 (Not Found),hexo博客搭建过程图片路径正确却找不到图片

我的问题 我查了好多资料&#xff0c;结果原因是图片名称开头是_则该文件会被忽略。。。我注意到网上并没有提到这个问题&#xff0c;遂补了一下这篇博客并且汇总了我找到的所有解决办法。 具体检查方式&#xff1a; hexo生成一下静态资源&#xff1a; hexo g会发现这张图片…

二维码门楼牌管理应用平台建设:网格化管理的新篇章

文章目录 前言一、二维码门楼牌管理应用平台的建设背景二、二维码门楼牌管理应用平台的功能特点三、二维码门楼牌管理应用平台的实际应用四、二维码门楼牌管理应用平台的前景展望 前言 随着信息技术的飞速发展&#xff0c;二维码门楼牌管理应用平台的建设已成为城市网格化管理…

李廉洋:4.20国际黄金,原油本周行情分析及下周一走势分析。

荷兰国际银行表示&#xff0c;所谓的美国国债期限溢价的回升&#xff0c;将为10年期国债收益率重返5%的关键水平铺平道路。从理论上来说&#xff0c;可将10年期美债收益率拆解为未来短端利率的期望期限溢价(term premium)。所谓期限溢价&#xff0c;是对投资者持有长期债券的风…

第十四届蓝桥杯省赛C/C++大学B组真题-飞机降落

思路&#xff1a;根据数据范围N<10猜测用DFS剪枝&#xff0c;因为菜狗不会状压dp。根据题目&#xff0c;一般这种飞机的题都会用到贪心的思想。思想是每架飞机都要卡极限最早降落时间&#xff0c;从而保证后面的飞机能够有充足时间降落。 代码参考博客MQy大佬有详细解答 #i…

深度学习之CNN

目录 我们为什么要用CNN&#xff0c;或者说究竟是因为什么我们要用CNN 卷积操作的实现原理 补充知识 torch.nn.Conv2d&#xff08;&#xff09; 注意 torch.nn.functional.conv2d&#xff08;&#xff09; torch.nn.functional.conv2d&#xff08;&#xff09;和torch.nn.…

Fannel和Calico

一 1、路由器下面每一个端口都是一个vlan,隔离了广播包 192.168.1.0和192.168.2.0他们属于不同的vlan,没有三层交换机或者路由器,他们通不了信 不在同一个vlan,也就是子网,包就会走向网关(也就是路由器那里,路由器有路由表。查看目的地192.168.2.0在b口,从b口出去vlan…

互联网技术知识点总览——算法和数据结构

简介 本文对算法和数据结构的知识点整体框架进行梳理和分享如下&#xff1a;

Ubuntu无法安装向日癸15.2.0.63062_amd64.deb最新版

Ubuntu安装向日葵远程控制 安装包下载 安装方式 方式一&#xff1a;运行安装包安装 方式二&#xff1a;终端命令安装 通过以下教程可以快速的安装向日葵远程控制&#xff0c;本教程适用于Ubuntu18.04/20.04/22.04 安装包下载 进入向日葵远程控制下载官网下载向日葵远程控制Lin…

黑马程序员Linux简单入门学习笔记

Linux介绍 内核提供系统最核心的功能&#xff0c;如: 调度CPU、调度内存、调度文件系统、调度网络通讯、调度等系统级应用程序&#xff0c;可以理解为出厂自带程序&#xff0c;可供用户快速上手操作系统&#xff0c;如:文件管理器、任务管理器、图片查看、音乐播放等 目录结构 …

深度学习--CNN卷积神经网络(附图)

框架 让我们先看一下CNN的框架 卷积层中后是ReLu激活函数 &#xff0c;然后是深化池&#xff0c;之后是全连接&#xff0c;最后进行Softmax进行归一化。 所以&#xff0c;我们先逐一了解一下它们各个部分 全连接层 全连接层也称感知机&#xff0c;BP神经网络 全连接层&…