Java和Spring扫描加载 配置文件

在项目中有些参数经常需要修改,或者后期可能会有改动时,那我们最好把这些参数放到properties文件中,在源代码中读取properties里面的配置,这样后期只需要改动properties文件即可,不需要修改源码。

一、java加载配置文件

package readProperties;

import java.io.InputStream;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;

//import org.springframework.core.io.support.PropertiesLoaderUtils;

public class TestProperties {


    /**
     * @Description: 输出所有配置信息
     */
    private static void printAllProperty(Properties props) {
        @SuppressWarnings("rawtypes")
        Enumeration en = props.propertyNames();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            String value = props.getProperty(key);
            System.out.println(key + " : " + value);
        }
    }

    /**
     * 根据key读取value
     *
     * @Description: 第二种方式:使用缓冲输入流读取配置文件,然后将其加载,再按需操作
     * 绝对路径或相对路径, 如果是相对路径,则从当前项目下的目录开始计算,
     * 如:当前项目路径/config/config2.properties,
     * 相对路径就是config/config2.properties
     */
    public static String getProperties_2(String filePath, String keyWord) {
        Properties prop = new Properties();
        String value = null;
        try {
            // 通过输入缓冲流进行读取配置文件
            InputStream InputStream = new BufferedInputStream(new FileInputStream(new File(filePath)));
            // 加载输入流
            prop.load(InputStream);
            // 根据关键字获取value值
            value = prop.getProperty(keyWord);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 读取配置文件所有信息
     *
     * @Description: 第二种方式:使用缓冲输入流读取配置文件,然后将其加载,再按需操作
     * 绝对路径或相对路径, 如果是相对路径,则从当前项目下的目录开始计算,
     * 如:当前项目路径/config/config2.properties,
     * 相对路径就是config/config2.properties
     */
    public static void getProperties_2(String filePath) {
        Properties prop = new Properties();
        try {
            // 通过输入缓冲流进行读取配置文件
            InputStream InputStream = new BufferedInputStream(new FileInputStream(new File(filePath)));
            // 加载输入流
            prop.load(InputStream);
            printAllProperty(prop);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据key读取value
     *
     * @Description: 第三种方式:
     * 相对路径, properties文件需在classpath目录下,
     * 比如:config.properties在包com.test.config下,
     * 路径就是/com/test/config/config2.properties
     */
    public static String getProperties_3(String filePath, String keyWord) {
        Properties prop = new Properties();
        String value = null;
        try {
            //D:\project\java\config\config2.properties
            InputStream inputStream = TestProperties.class.getClassLoader().getResourceAsStream(filePath);
            prop.load(inputStream);
            value = prop.getProperty(keyWord);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 读取配置文件所有信息
     *
     * @Description: 第三种方式:
     * 相对路径, properties文件需在classpath目录下,
     * 比如:config.properties在包com.test.config下,
     * 路径就是/com/test/config/config2.properties
     */
    public static void getProperties_3(String filePath) {
        Properties prop = new Properties();
        try {
            InputStream inputStream = TestProperties.class.getResourceAsStream(filePath);
            prop.load(inputStream);
            printAllProperty(prop);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        // 注意路径问题
        String properties_2 = getProperties_2("config/config.properties", "jdbc.url");
        System.out.println("jdbc.url = " + properties_2);
        getProperties_2("config/config.properties");
        System.out.println("*********************************************");
        // 注意路径问题
        String properties_3 = getProperties_3("config/config2.properties", "username");
        System.out.println("username = " + properties_3);
        getProperties_3("/config/config2.properties");
    }
}

props.load(new FileInputStream("db.properties")); 是读取当前目录的db.properties文件
getClass.getResourceAsStream("db.properties"); 是读取当前类所在位置一起的db.properties文件
getClass.getResourceAsStream("/db.properties"); 是读取ClassPath的根的db.properties文件,注意ClassPath如果是多个路径或者jar文件的,只要在任意一个路径目录下或者jar文件里的根下都可以,如果存在于多个路径下的话,按照ClassPath中的先后顺序,使用先找到的,其余忽略. 

读取服务器路径文件这种方式:

package com.readProperties;

import org.apache.log4j.Logger;

import java.io.*;
import java.util.Properties;

 
public class SysConfig {

    private static Logger logger = Logger.getLogger(SysConfig.class);
    private static SysConfig instance;
    //系统配置文件的路径
    public static final String SYSCONFIG_PATH = "sysConfig.properties";
    public static final String USER_NAME = "username";
    public static final String PASS_WORD = "password";
    private String userName;
    private String passWord;

    public String getUserName() {
        return userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public static synchronized SysConfig getInstance() {
        if (instance == null) {
            try {
                instance = new SysConfig();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return instance;
    }

    public SysConfig() throws IOException {
        Properties properties = SysConfig.getSystemConfigProperties(SYSCONFIG_PATH);
        userName = properties.getProperty(USER_NAME);
        passWord = properties.getProperty(PASS_WORD);
    }

    public synchronized static Properties getSystemConfigProperties(String path) {
        Properties prop = new Properties();
        try (InputStream inputStream = SysConfig.class.getClassLoader().getResourceAsStream(path);) {
            prop.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("读取配置文件失败", e);
            return null;
        }
//    value = prop.getProperty(keyWord);
        logger.info("读取配置文件成功");
        return prop;
    }
}

二、spring加载配置文件

下面讨论spring两种加载方式,基于xml和基于注解的加载方式。

1. 通过xml方式加载properties文件

以Spring实例化dataSource为例,先在工程目录的src下新建一个conn.properties文件,里面写上上面dataSource的配置:

以Spring实例化dataSource为例,先在工程目录的src下新建一个conn.properties文件,里面写上上面dataSource的配置:

dataSource=com.mchange.v2.c3p0.ComboPooledDataSource  
driverClass=com.mysql.jdbc.Driver  
jdbcUrl=jdbc:mysql://localhost:3306/shop 
username=root  
password=root 

引入外部文件 :

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">
 <!-- PropertyPlaceholderConfigurer类中有个locations属性,接收的是一个数组,即我们可以在下面配好多个properties文件 -->      
    <list>  
	   <value>classpath*:*conf.properties</value>
	   <value>classpath.*.properties</value> 
    </list>  
    </property>  
</bean>

引入外部文件后,就可以在xml中用${key}替换指定的properties文件中的值,通常项目中都会将jdbc的配置放在properties文件中

然后在只需要在beans.xml中做如下修改即可:

 <!-- 这些配置Spring在启动时会去conn.properties中找 -->  
 <bean id="dataSource" class="${dataSource}"> 
 <!--<bean id="dataSource" class="cn.com.cpic.demo"--> 
    <property name="driverClass" value="${driverClass}" />  
    <property name="jdbcUrl" value="${jdbcUrl}" />  
    <property name="user" value="${user}" />  
    <property name="password" value="${password}" />  
 </bean>  

 通过demo就可以获取配置文件的username和password的值了

public class demo {
    String username;
    String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

为简化PropertyPlaceholderConfigurer的使用,Spring提供了<context:property-placeholder/>元素,启用它后,开发者便不用配置PropertyPlaceholderConfigurer对象了

配置属性文件

<!-- 数据库配置文件位置 -->
<context:property-placeholder location="classpath:jdbc.properties" />

2) 注意点:踩过的坑

在Spring中的xml中使用<context:property-placeholderlocation>标签导入配置文件时,想要导入多个properties配置文件,如下:

<context:property-placeholderlocation="classpath:db.properties " />
<context:property-placeholderlocation="classpath:zxg.properties " />

结果发现不行,第二个配置文件始终读取不到,Spring容器是采用反射扫描的发现机制,通过标签的命名空间实例化实例,当Spring探测到容器中有一个org.springframework.beans.factory.config.PropertyPlaceholderConfigurer的Bean就会停止对剩余PropertyPlaceholderConfigurer的扫描,即只能存在一个实例

如果有多个配置文件可以使用 “,” 分隔
<context:property-placeholderlocation="classpath:db.properties,classpath:monitor.properties" />

可以使用通配符 *
<context:property-placeholderlocation="classpath:*.properties" />

 

​​​2. 通过注解方式加载properties文件

第一种配置方式:

    <!-- 确保可在@Value中, 使用SeEL表达式获取资源属性 -->
    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="properties" ref="configProperties" />
    </bean>

    <bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath:config/*.properties</value>
            </list>
        </property>
    </bean>

在java代码中用@Value获取配置属性值

    @Value("${shop.url}")
    private String url;

还有一种方式更简洁:

    <bean id="prop" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> 
        <property name="fileEncoding" value="UTF-8"/> 
        <property name="locations"><!-- 这里是PropertiesFactoryBean类,它也有个locations属性,也是接收一个数组,跟上面一样 --> 
            <array>  
                <value>classpath:public.properties</value>  
            </array>  
        </property>  
    </bean> 
    <!--或者-->
    <context:property-placeholder location="classpath:**.properties" />  
  //注意,这种表达式要有set方法才能被注入进来,注解写在set方法上即可
    private String url;  
    @Value("#{prop.shop.url}")   
    //@Value表示去beans.xml文件中找id="prop"的bean,它是通过注解的方式读取properties配置文件的,然后去相应的配置文件中读取key=shop.url的对应的value值  
    public void setUrl(String url) {  
        this.token= url;  
    }

 

3.通过 @PropertySource和@Value 来读取配置文件

举个栗子:

@Component
//@PropertySource注解用来指定要读取的配置文件的路径从而读取这些配置文件,可以同时指定多个配置文件;
@PropertySource(value = {"classpath:common.properties", "classpath:abc.properties"})
public class Configs {
//@Value("${connect.api.apiKeyId}")用来读取属性key=connect.api.apiKeyId所对应的值并把值赋值给属性apiKeyId;
    @Value("${connect.api.apiKeyId}")
    public String apiKeyId;

    @Value("${connect.api.secretApiKey}")
    public String secretApiKey;

    public String getApiKeyId() {
        return apiKeyId;
    }

    public String getSecretApiKey() {
        return secretApiKey;
    }
}

4.自定义 PropertyPlaceholderConfigurer

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Spring配置文件加载优先级由以下顺序决定: 1. 在classpath根路径下寻找的application.properties或application.yml文件; 2. 在classpath根路径下寻找的application-{profile}.properties或application-{profile}.yml文件; 3. 在classpath根路径下寻找的spring.properties文件; 4. 在classpath根路径下寻找的spring.xml文件; 5. 在classpath根路径下寻找的{filename}.properties文件; 6. 在classpath根路径下寻找的{filename}.yml文件; 7. 在classpath根路径下寻找的{filename}.xml文件; 8. 在文件系统寻找的config目录下的application.properties或application.yml文件; 9. 在文件系统寻找的config目录下的application-{profile}.properties或application-{profile}.yml文件; 10. 在文件系统寻找的config目录下的{filename}.properties或{filename}.yml文件; 11. 在文件系统寻找的config目录下的{filename}.xml文件; 12. 在jar包内寻找的/META-INF/spring.factories文件。 如果有多个文件符合要求,那么它们将按照上述顺序进行合并,后加载配置将覆盖先加载配置。 ### 回答2: Spring配置文件加载优先级是根据不同的方式来决定的。在Spring,可以通过多种方式来加载配置文件,包括通过XML配置(如applicationContext.xml)、通过注解和通过Java代码配置等方式。 首先,在使用XML配置的情况下,Spring框架会首先查找默认的配置文件 applicationContext.xml 来加载配置信息,如果没有默认配置文件,框架会报错。如果存在默认配置文件,那么可以使用其它名称的XML配置文件来进行覆盖或扩充配置。例如,可以使用 `<import>` 元素来引入其它的配置文件,而引入的配置文件会按照顺序进行加载。 其次,在使用注解的情况下,Spring框架会扫描指定的包路径,查找带有相应注解的类,并将其作为配置加载。可以使用 `@ComponentScan` 注解来指定扫描的包路径,也可以使用 `@Import` 或 `@ImportResource` 注解来导入其它的配置类或XML配置文件。 最后,在使用Java代码配置的情况下,Spring框架会通过编写配置类来进行配置。可以使用 `@Configuration` 注解标识一个类为配置类,并在该类使用 `@Bean` 注解来定义需要创建的Bean。在使用Java配置时,Spring框架会将这些配置类作为参数进行加载。 总的来说,Spring配置文件加载的优先级为:默认XML配置文件 > 其它XML配置文件 > 注解扫描 > Java配置类。在加载的过程,后加载配置会覆盖前面加载配置,从而实现对配置文件的灵活管理和定制。 ### 回答3: Spring配置文件加载优先级主要取决于以下几个因素: 1. 默认配置文件位置:Spring框架会默认加载位于classpath根目录下的名为"applicationContext.xml"的配置文件。如果该文件存在,则会自动加载,优先级最高。 2. 自定义配置文件位置:开发者可以通过在web.xml或者Spring配置文件指定需要加载配置文件路径。如在web.xml配置contextConfigLocation参数,或在@Configuration注解类使用@PropertySource注解指定配置文件路径。 3. 注解配置类:使用@Configuration注解标记的Java配置类,可以替代XML配置文件Spring会自动扫描这些类,并将其作为配置文件加载。注解配置类的加载顺序比xml配置文件更早。 4. @Import注解:@Import注解可以用于导入其他配置类,以声明式地将多个配置类组织在一起。通过@Import注解导入的配置类会先于其他配置文件进行加载。 综上所述,Spring配置文件加载的优先级为:注解配置类 > @Import注解 > 自定义配置文件位置 > 默认配置文件位置。 同时,根据不同的实际项目需求,我们可以使用多个配置文件进行配置,通过上述方式控制加载的顺序和优先级,以满足不同场景下的配置需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四月天03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值