SpringBoot项目优雅的实现多配置文件切换以及获取配置信息

Posted GaoYang-笔迹

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot项目优雅的实现多配置文件切换以及获取配置信息相关的知识,希望对你有一定的参考价值。

SpringBoot项目优雅的实现多配置文件切换以及获取配置信息

在我们平时的生产中肯定不会单纯的的只有一个配置文件,通产会分为测试、开发、生产三个版本,做为一个刚入行的小白,记录一个实践中的技巧

一、构建项目

创建一个SpringBoot项目并在resources目录下创建像application-xxx.yml这样的配置文件。
在这里插入图片描述
进行配置文件切换

spring:
  application:
    name: test-server
  profiles:
    active: test/dev/prod ---进行切换配置文件版本

二、创建工具类进行解析yml获取对应的配置数据

  1. 创建工具类对yml进行简单的解析
public class YmlTools {
    private HashMap<String, String> ps = new LinkedHashMap<>();

    public YmlTools() {

    }

    public YmlTools(Resource resource) {
        load(resource);
    }

    public YmlTools(String path) {
        load(path);
    }

    public YmlTools load(String path) {
        ps.putAll(new YmlParser().load(path).getAll());
        return this;
    }

    public YmlTools load(Resource resource) {
        ps.putAll(new YmlParser().load(resource).getAll());
        return this;
    }

    public String getProperty(String key) {
        return ps.get(key);
    }

    public YmlTools clear() {
        ps.clear();
        return this;
    }

    public HashMap<String, String> getAll() {
        return ps;
    }

    public String dump() {
        StringBuilder sb = new StringBuilder();
        for (String key : ps.keySet()) {
            sb.append(key + ":" + ps.get(key) + "\\n");
        }
        return sb.toString();
    }


    public static class YmlParser {
        private HashMap<String, String> ps;
        private Pattern pattern = Pattern.compile("\\\\$\\\\{[0-9a-zA-Z_\\\\.]+\\\\}");


        public String getProperty(String key) {
            return ps.get(key);
        }

        public HashMap<String, String> getAll() {
            return ps;
        }

        public YmlParser load(Resource resource) {
            ps = parseYml(resource);
            ps = parsePos();
            return this;
        }


        public YmlParser load(String path) {
            String classPathPreFix = "classpath:";
            if (path.startsWith(classPathPreFix)) {
                load(new ClassPathResource(path.substring(classPathPreFix.length())));
            } else {
                load(new FileSystemResource(path));
            }
            return this;
        }

        private String joinPrefix(String old, String append) {
            if (old == null || old.length() <= 0) {
                return append;
            }
            String rs = old + "." + append;
            if (rs.endsWith(".") || rs.endsWith(":"))
                rs = rs.substring(0, rs.length() - 1);
            return rs;
        }

        private HashMap<String, String> parseYml(Resource resource) {
            HashMap<String, String> ps = new LinkedHashMap<String, String>();
            BufferedReader br = null;
            try {
                InputStream is = resource.getInputStream();
                String line = null;
                br = new BufferedReader(new InputStreamReader(is));
                String currPrefix = "";
                int lastLevel = 0;
                while ((line = br.readLine()) != null) {
                    if (line.trim().length() <= 0 || line.trim().startsWith("#"))
                        continue;
                    int leftSpace = lineLeftSpace(line);

                    boolean hasVal = line.trim().contains(": ");
                    String k = null;
                    String v = null;
                    if (hasVal) {
                        String[] kv = line.trim().split(": ");
                        k = kv[0];
                        v = kv[1];
                    } else {
                        k = line.trim().split(":")[0];
                    }

                    currPrefix = changeToLevel(currPrefix, leftSpace / 2);
                    currPrefix = joinPrefix(currPrefix, k);

                    if (hasVal && null != v) {
                        ps.put(currPrefix, v);
                    }

                    lastLevel = leftSpace;


                }
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                if (br != null)
                    try {
                        br.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }

            return ps;
        }

        private String changeToLevel(String currPrefix, int level) {
            if (null == currPrefix || currPrefix.length() <= 0 || level == 0) {
                return "";
            }
            String[] grade = currPrefix.split("\\\\.");
            if (level >= grade.length) {
                return currPrefix;
            }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < level; i++) {
                if (sb.length() > 0)
                    sb.append(".");
                sb.append(grade[i]);
            }
            return sb.toString();
        }

        private String upPrefix(String currPrefix) {
            if (null != currPrefix) {
                if (currPrefix.contains("."))
                    currPrefix = currPrefix.substring(0, currPrefix.lastIndexOf("."));
                else
                    currPrefix = "";
            }

            return currPrefix;
        }

        private int lineLeftSpace(String line) {
            int l = 0;
            for (int i = 0; i < line.length(); i++) {
                if (line.charAt(i) == ' ') {
                    l++;
                } else if (line.charAt(i) == '\\t') {
                    l += 2;
                } else {
                    break;
                }
            }
            return l;
        }

        private HashMap<String, String> parsePos() {
            HashMap<String, String> rs = new LinkedHashMap<>();
            for (String key : ps.keySet()) {
                rs.put(key, getPropertyWithParse(key));
            }
            return rs;
        }

        private String getPropertyWithParse(String key) {
            return replace(ps.get(key), new OnFind() {
                @Override
                public String replace(String source, String group, int start, int end) {
                    return getPropertyWithParse(group.substring(2, group.length() - 1));
                }
            });
        }

        private String replace(String source, OnFind onFind) {
            if(source==null){
                return source;
            }
            Matcher matcher = pattern.matcher(source);
            StringBuilder sb = new StringBuilder();

            int ls = 0;
            while (matcher.find()) {
                String group = matcher.group();
                int s = matcher.start();
                int e = matcher.end();
                sb.append(source.substring(ls, s));
                sb.append(onFind.replace(source, group, s, e));
                ls = e;
            }
            if (ls < source.length())
                sb.append(source.substring(ls));
            return sb.toString();
        }

        public interface OnFind {
            String replace(String source, String group, int start, int end);
        }
    }
}
  1. 创建一个获取配置文件的接口
/**
 * 配置文件调用接口
 */
@Service
public interface ProjectConfigService {

    /**
     * 配置文件值取得
     *
     * @param key 配置文件键
     * @return 配置文件值
     */
    String getProperty(String key);
}
  1. 实现该接口
@Service
public class ProjectConfigServiceImpl implements ProjectConfigService {

    //存储配置属性的Map集合
    private Map<String, String> conf = new HashMap<String, String>();
    public ProjectConfigServiceImpl(){
        conf.clear();
        conf.putAll(new YmlTools.YmlParser().load("classpath:application.yml").getAll());
        // 获取-后面的值
        String active = conf.get("spring.profiles.active");
        conf.putAll(new YmlTools.YmlParser().load("classpath:application-" + active + ".yml").getAll());
    }

    public String getProperty(String key) {
        return conf.get(key);
    }
}

三、测试

在这里插入图片描述

以上是关于SpringBoot项目优雅的实现多配置文件切换以及获取配置信息的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot项目优雅的实现多配置文件切换以及获取配置信息

SpringBoot项目优雅的实现多配置文件切换以及获取配置信息

springboot 多环境配置和切换

SpringBoot 的多数据源配置与动态切换

SpringBoot 的多数据源配置与动态切换

SpringBoot 的多数据源配置与动态切换