精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (2)
|
|
---|---|
作者 | 正文 |
发表时间:2011-12-23
编程的时候都要把一些可变的参数放到配置文件里面, 常见的配置文件就是xml, 键值对等. 但是我觉得xml有点大, 浪费; properties这种键值对有点简单了. 就仿照nginx的配置文件格式(不全一样)写了一个配置读取工具. 第一次发代码, 求指导.
首先是配置文件的格式 #注释格式 #system是一个配置段 system { #子配置段config config { #一个配置项 url : localhost #配置项的值是数组, 用[]包括, 逗号分隔 message : [not login, ok] } ok { #配置项可以只有键(配置项名)而没有值 path1 } user { /user } whoami : wenjianwzz } #也可以不包括在配置段里面 where : cd
然后就是使用方法 public static void main(String args[]) { //加载配置文件, 返回一个根配置段(文件中所有的) Config config = Config.load(ResourceUtil.getResourcePath("new.conf"), "UTF-8"); //定位配置, @表示查找配置项, 如果不加@则是查找子配置段 System.out.println(config.locateValue("/system/@whoami")); //可以用..上翻 System.out.println(config.locateValue("/system/../@where")); //数组配置的某一值 System.out.println(config.locateValue("/system/config/@message[0]")); //查找子孙配置段, 不用/打头表示从当前配置段定位, 这里因为本来就是根配置, 所以就一样了 config = config.locateConfig("system/config"); //从当前配置段定位 System.out.println(config.locateValue("@message[0]")); // 上翻的作用 System.out.println(config.locateValue("../@whoami")); } 这个用path定位的方式是受xpath启发, 觉得挺好用的
下面就是源码
package eu.jk.config; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import eu.jk.helper.ResourceUtil; /** * 配置段类 * * @author wenjianwzz * */ public final class Config { /** * 配置项 */ private Map<String, ConfigItem> items = new HashMap<String, ConfigItem>(); /** * 子配置段 */ private Map<String, Config> subconfigs = new HashMap<String, Config>(); /** * 父亲 */ private Config parent = null; /** * 配置段名 */ private String name = null; /** * 取得键对应的值,如果不存在对应的值, 返回NULL * * @param key * @return String * @see java.util.hashtable#get(Object) */ public String getValue(String key) { return items.get(key).getValue(); } /** * 取得键对应的值,如果不存在对应的值, 返回NULL * * @param key * @return String * @see java.util.hashtable#get(Object) */ public String getValue(String key, int index) { return items.get(key).getValue(index); } /** * 查找配置项 * @param key * @return */ public ConfigItem getConfigItem(String key) { return items.get(key); } /** * 是否包含指定键的配置项 * @param key * @return */ public boolean contains(String key) { return items.containsKey(key); } /** * 获取所有的配置项名称 * @return */ public Collection<String> getItemsKeys() { return items.keySet(); } /** * 获取配置段名 */ public String getName() { return name; } /** * 获取所有子配置段的名称 * @return */ public Collection<String> getSubconfigKeys() { return subconfigs.keySet(); } /** * 获取子配置段 * @param name * @return */ public Config getSubconfig(String name) { return subconfigs.get(name); } /** * 是否包含指定名称的子配置段 * @param name * @return */ public boolean containsSubconfig(String name) { return subconfigs.containsKey(name); } /** * 加载配置项 * @param id * @return */ public ConfigItem locateItem(String id) { return (ConfigItem) locate(id); } /** * 加载配置值 * @param id * @return */ public String locateValue(String id) { Object object = locate(id); if (object == null) return null; if (object instanceof ConfigItem) return ((ConfigItem)object).getValue(); if (object instanceof String) return (String) object; return null; } /** * 加载配置项 * @param id * @return */ public Config locateConfig(String id) { return (Config) locate(id); } /** * 加载 * @param id * @return */ protected Object locate(String id) { if (id == null) return null; // 定位基点 Config base = this; if (id.startsWith("/")) while (base.getParent() != null) base = base.getParent(); String[] fields = id.split("/"); for (String field : fields) { field = field.trim(); if ("".equals(field)) continue; if (field.startsWith("@")) { if (field.matches("^@.+\\[[0-9]+\\]$")) { String key = field.substring(1, field.indexOf('[')); String index = field.substring(field.indexOf('[') + 1, field.indexOf(']')); if (!isDigit(index)) return null; return base.getConfigItem(key).getValue(Integer.parseInt(index)); } return base.getConfigItem(field.substring(1)); } if ("..".equals(field)) base = base.getParent(); else base = base.getSubconfig(field); if (base == null) return null; } return base; } /** * 添加参数, 如果原来存在参数, 会接在后面成为一个数组 * * @param key * @param value */ protected void addParameters(String key, String value) { ConfigItem item = items.get(key); if (item == null) items.put(key, new ConfigItem(key, value)); else item.addValue(value); } protected void setConfigName(String configName) { this.name = configName; } protected Config(String configName) { this.name = configName; } /** * 添加子配置段 * @param subconfig */ protected void addSubconfig(Config subconfig) { subconfig.setConfigName(subconfig.getName().trim()); subconfigs.put(subconfig.getName(), subconfig); } protected void setParent(Config parent) { this.parent = parent; } protected Config getParent() { return parent; } /** * 加载配置文件, 返回根配置段 * @param path 配置文件的路径 * @param encoding 文件编码, 如果为null则使用系统默认编码 * @return 根配置 */ public static Config load(String path, String encoding) { try { return load(new FileInputStream(path), encoding, path); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } } /** * 使用系统默认编码加载配置文件, 返回根配置 * @param path 配置文件的路径 * @return 根配置 */ public static Config load(String path) { return load(path, null); } /** * 从流中加载配置, 使用系统默认编码 * @param input 输入流 * @param rootConfigName 根配置名 * @return */ public static Config load(InputStream input, String rootConfigName) { return load(input, null, rootConfigName); } /** * 从流中加载配置, 使用系统默认编码 * @param input 输入流 * @return 根配置 */ public static Config load(InputStream input) { return load(input, null, "anonymous"); } /** * 从流中加载配置, 使用指定编码 * @param input 输入流 * @param encoding 编码 * @param rootConfigName 根配置名 * @return 根配置 */ public static Config load(InputStream input, String encoding, String rootConfigName) { Config root = new Config(rootConfigName); for (String line : readLines(input, encoding)) { line = line.trim(); if (line.startsWith("#")) continue; if (line.length() == 0) continue; //SubConfig found if (line.matches("^.+\\{$")) { String name = new String(line.replace('{', '\b').trim()); Config sub = new Config(name); root.addSubconfig(sub); sub.setParent(root); root = sub; continue; } /* * 往上翻一层 */ if ("}".equals(line)) { root = root.getParent(); continue; } /* * 键值对的配置 */ if (line.contains(":")) { int index = line.indexOf(':'); String key = line.substring(0, index).trim(); String value = line.substring(index + 1).trim(); if (value.matches("^\\[.+\\]$")) { value = value.substring(1, value.length()-1); for (String sub : value.split(",")) { sub = sub.trim(); if (sub.length() == 0) continue; root.addParameters(key, sub); } continue; } root.addParameters(key, value); continue; } root.addParameters(line, null); } return root; } /** * 判断一个字符串是不是数字 * @param str * @return boolean */ private static boolean isDigit(String str) { if (str == null) return false; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (c < 48 || c > 57) return false; } return true; } /** * 从流中读取所有行 * @param path * @param encoding * @return */ private static List<String> readLines(InputStream input, String encoding) { InputStreamReader fr; List<String> list = new ArrayList<String>(); try { if (encoding != null) fr = new InputStreamReader(input, encoding); else fr = new InputStreamReader(input); BufferedReader br = new BufferedReader(fr); String line = br.readLine(); while (line != null) { list.add(line); line = br.readLine(); } br.close(); fr.close(); } catch (Exception e) { e.printStackTrace(); return null; } return list; } public static void main(String args[]) { //加载配置文件, 返回一个根配置段(文件中所有的) Config config = Config.load(ResourceUtil.getResourcePath("new.conf"), "UTF-8"); //定位配置, @表示查找配置项, 如果不加@则是查找子配置段 System.out.println(config.locateValue("/system/@whoami")); //可以用..上翻 System.out.println(config.locateValue("/system/../@where")); //数组配置的某一值 System.out.println(config.locateValue("/system/config/@message[0]")); //查找子孙配置段, 不用/打头表示从当前配置段定位, 这里因为本来就是根配置, 所以就一样了 config = config.locateConfig("system/config"); //从当前配置段定位 System.out.println(config.locateValue("@message[0]")); // 上翻的作用 System.out.println(config.locateValue("../@whoami")); } }
package eu.jk.config; import java.util.ArrayList; import java.util.List; /** * 配置项 * @author WZZ * */ public final class ConfigItem { String key; List<String> values = new ArrayList<String>(); protected ConfigItem(String key) { this.key = key; } protected ConfigItem(String key, String value) { this.key = key; values.add(value); } protected void addValue(String value) { values.add(value); } public String getKey() { return key; } public String getValue() { if (values.size() <= 0) return null; return values.get(0); } public String getValue(int index) { if (values.size() <= index || index < 0) return null; return values.get(index); } public int size() { return values.size(); } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-12-23
-一般?喜欢用commons configuration
|
|
返回顶楼 | |
发表时间:2011-12-24
nginx conf 应该可以叫dsl了吧
|
|
返回顶楼 | |
发表时间:2011-12-24
直接变成json貌似也挺方便的,用JSONObject反序列化一下就行了
|
|
返回顶楼 | |
发表时间:2011-12-25
没发现任何好处,比 properties 配置文件能小点?但代码可多了不少
|
|
返回顶楼 | |
发表时间:2011-12-25
if (field.matches("^@.+\\[[0-9]+\\]$")) {
178. String key = field.substring(1, field.indexOf('[')); 179. String index = field.substring(field.indexOf('[') + 1, field.indexOf(']')); 180. if (!isDigit(index)) 181. return null; 182. return base.getConfigItem(key).getValue(Integer.parseInt(index)); 183. } 184. return base.getConfigItem(field.substring(1)); //先看看java正则,这段代码没这么复杂 直接group就能拿到 |
|
返回顶楼 | |
发表时间:2011-12-25
请问楼主,xml如何浪费了?
|
|
返回顶楼 | |
发表时间:2011-12-26
ResourceBundle读不方便吗?
|
|
返回顶楼 | |
发表时间:2011-12-26
不评价
|
|
返回顶楼 | |
发表时间:2011-12-26
weiqiang.yang 写道 直接变成json貌似也挺方便的,用JSONObject反序列化一下就行了
这个法子好 |
|
返回顶楼 | |