自己编写的properties配置文件读取工具,备忘

本工具使用maven为包管理器,maven依赖如下

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-configuration2 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-configuration2</artifactId>
    <version>2.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.3</version>
</dependency>

工具源码如下:

package com.szq.test.util;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.commons.configuration2.FileBasedConfiguration;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.ReloadingFileBasedConfigurationBuilder;
import org.apache.commons.configuration2.builder.fluent.Parameters;
import org.apache.commons.configuration2.builder.fluent.PropertiesBuilderParameters;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.commons.configuration2.reloading.PeriodicReloadingTrigger;

public enum ConfigUtil {
    I;
    private Map<String, BuilderAndTrigger> btMap = new HashMap<>();

    /**
     * 获取配置
     * @param fileName 配置文件名,配置文件放在WEB-INF\classes目录下
     * @return
     * @throws ConfigurationException 
     */
    public ImmutableConfiguration getConfiguration(final String fileName) throws ConfigurationException {
        BuilderAndTrigger bt = btMap.get(fileName);
        FileBasedConfiguration configuration = null;
        if (bt == null) { //builder不存在,生成新builder
            ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = createConfiguration(fileName);
            configuration = builder.getConfiguration(); //检测builder是否成功生成,未成功生成则这里会抛出异常
            PeriodicReloadingTrigger trigger = new PeriodicReloadingTrigger(builder.getReloadingController(), null, 5, TimeUnit.SECONDS); //配置重载触发器,5秒触发一次重载检测
            trigger.start();
            btMap.put(fileName, new BuilderAndTrigger(builder, trigger));
        } else {
            configuration = bt.getBuilder().getConfiguration();
        }
        return ConfigurationUtils.unmodifiableConfiguration(configuration); //返回不可编辑配置,避免多线程并发问题
    }

    /**
     * 移除不再使用的配置
     * @param fileName 
     */
    public void removeConfiguration(final String fileName) {
        BuilderAndTrigger bt = btMap.get(fileName);
        if (bt != null) { //有builder和trigger存在
            bt.getTrigger().stop();
            btMap.remove(fileName);
        }
    }

    /**
     * 生成新配置builder
     * @param fileName 
     * @return 
     */
    private ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> createConfiguration(final String fileName) {
        ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder = null;
        Parameters params = new Parameters();
        PropertiesBuilderParameters proParam = params.properties();
        File file = new File(fileName);
        proParam.setFile(file); //这里在下文有其他说明,请细看
        builder = new ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class).configure(proParam);
        return builder;
    }

    /**
     * @comment 内部类,表示 builder 和其对应的 trigger
     */
    private static class BuilderAndTrigger {
        private ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder;
        private PeriodicReloadingTrigger trigger;

        public BuilderAndTrigger(ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> builder, PeriodicReloadingTrigger trigger) {
            super();
            this.builder = builder;
            this.trigger = trigger;
        }

        public ReloadingFileBasedConfigurationBuilder<FileBasedConfiguration> getBuilder() {
            return builder;
        }

        public PeriodicReloadingTrigger getTrigger() {
            return trigger;
        }

        @Override
        public String toString() {
            return "BuilderAndTrigger [builder=" + builder + ", trigger=" + trigger + "]";
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((builder == null) ? 0 : builder.hashCode());
            result = prime * result + ((trigger == null) ? 0 : trigger.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            BuilderAndTrigger other = (BuilderAndTrigger) obj;
            if (builder == null) {
                if (other.builder != null)
                    return false;
            } else if (!builder.equals(other.builder))
                return false;
            if (trigger == null) {
                if (other.trigger != null)
                    return false;
            } else if (!trigger.equals(other.trigger))
                return false;
            return true;
        }
    }
}

使用示例如下:

package test;

import org.apache.commons.configuration2.Configuration;
import org.junit.Test;

import com.szq.test.util.ConfigUtil;

public class Tjt {
    @Test
    public void t1() {
        try {
            //这俩配置文件放在WEB-INF\classes目录下
            String l1 = "l1.properties";
            String l2 = "l2.properties";
            for (int i = 0; i < 100; i++) {
                Thread.sleep(1000L);
                if (i % 7 == 0) {
                    ConfigUtil.I.removeConfiguration(l1); //移除不再使用的配置文件
                    ConfigUtil.I.removeConfiguration(l2);
                } else {
                    Configuration configuration1 = ConfigUtil.I.getConfiguration(l1); //获取配置
                    Configuration configuration2 = ConfigUtil.I.getConfiguration(l2); //第二个配置
                    System.out.println(configuration1.getString("a"));
                    System.out.println(configuration2.getString("a"));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如上,把源码保存成java文件,直接如代码2一样获取配置,然后获取配置文件内容就行了。
本工具会自动更新配置,直接修改配置文件,过一段时间程序就会自动获取到更新后的值,这期间程序不需重启。
说明:
有人可能会这样写这行代码

proParam.setFile(file).setListDelimiterHandler(new DefaultListDelimiterHandler(',')); // , 作为数组类型值得分隔符

然后在程序里这样调用

String[] a = config.getStringArray("a"); //直接从properties类型配置文件读取数组或者列表之列的数据

这样使用是有问题的,日志会报异常,如下

java.beans.IntrospectionException: bad write method arg count: public final void org.apache.commons.configuration2.AbstractConfiguration.setProperty(java.lang.String,java.lang.Object)

查看原因,网址如下:
https://issues.apache.org/jira/browse/BEANUTILS-477
所以如果要从properties类型配置文件读取数组或者列表之类的数据,最好的办法如下

String a = config.getString("a");
String[] b = a.split(","); //看你配置文件用什么分隔符,这里就写什么分隔符
List<String> c = Arrays.asList(b); //或者更进一步,做成列表

原创不易,转帖请注明出处—–shizhongqi

猜你喜欢

转载自blog.csdn.net/lianjunzongsiling/article/details/79029399