2009-04-08 17 views
6

是否有记录的Java“属性”文件的内容,包括一套行之有效的方法:最佳实践文档提供/所需的Java属性文件内容

  • 指定数据类型/预期对于给定的重点内容
  • 指定键是否是所必需的应用程序的功能
  • 提供的键的含义的说明

目前,我维持(用手)一个.P这是默认的roperties文件,我在之前的评论中撰写了关于每个键的数据类型和描述的散文描述。这不会导致程序可访问的属性文件。

我猜我寻找的是一个 “getopt的” 等价物的属性文件...

[编辑:相关]

+0

更新我的答案,包括应该让你开始的代码。 – TofuBeer 2009-04-09 16:37:51

+0

哇,我刚刚得到了“热门问题”徽章,只有3个赞...奇怪...我仍然在为它工作一个令人满意的解决方案。 – andersoj 2010-11-30 16:56:20

回答

1

我从来没有见过这样做的标准方式。我可能会做的是:

  • 包装或延长java.util.Properties
  • 倍率(延长),或提供一种方法(如包装),其写出评论的存储方法(或storeToXML等)每一行。
  • 有存储属性的方法有某种输入文件,您可以在其中描述每个属性的属性。

除了您可以用不同的方式管理信息之外,它不会为您提供任何有关手动操作的信息,例如您可以使用一个可以更容易处理的程序要阅读的评论。它可能会给你你需要的程序化访问,但它是一种自己动手的事情。

或者它可能只是太多的工作,为获得太少(这就是为什么没有明显的东西)。

如果你可以指定你想看到的评论类型,我可以采取一些措施,如果我觉得无聊:-)(这是我喜欢为乐趣而做的事情,生病我知道: - )。

好吧......我很无聊......这里是什么,至少是一个开始:-)

import java.util.HashMap; 
import java.util.Map; 
import java.util.Map.Entry; 
import java.util.Properties; 


public class PropertiesVerifier 
{ 
    private final Map<String, PropertyInfo> optionalInfo; 
    private final Map<String, PropertyInfo> requiredInfo; 

    { 
     optionalInfo = new HashMap<String, PropertyInfo>(); 
     requiredInfo = new HashMap<String, PropertyInfo>(); 
    } 

    public PropertiesVerifier(final PropertyInfo[] infos) 
    { 
     for(final PropertyInfo info : infos) 
     { 
      final Map<String, PropertyInfo> infoMap; 

      if(info.isRequired()) 
      { 
       infoMap = requiredInfo; 
      } 
      else 
      { 
       infoMap = optionalInfo; 
      } 

      infoMap.put(info.getName(), info); 
     } 
    } 

    public void verifyProperties(final Properties properties) 
    { 
     for(final Entry<Object, Object> property : properties.entrySet())  
     { 
      final String key; 
      final String value; 

      key = (String)property.getKey(); 
      value = (String)property.getValue(); 

      if(!(isValid(key, value))) 
      { 
       throw new IllegalArgumentException(value + " is not valid for: " + key); 
      } 
     } 
    } 

    public boolean isRequired(final String key) 
    { 
     return (requiredInfo.get(key) != null); 
    } 

    public boolean isOptional(final String key) 
    { 
     return (optionalInfo.get(key) != null); 
    } 

    public boolean isKnown(final String key) 
    { 
     return (isRequired(key) || isOptional(key)); 
    } 

    public Class getType(final String key) 
    { 
     final PropertyInfo info; 

     info = getPropertyInfoFor(key); 

     return (info.getType()); 
    } 

    public boolean isValid(final String key, 
          final String value) 
    { 
     final PropertyInfo info; 

     info = getPropertyInfoFor(key); 

     return (info.verify(value)); 
    } 

    private PropertyInfo getPropertyInfoFor(final String key) 
    { 
     PropertyInfo info; 

     info = requiredInfo.get(key); 

     if(info == null) 
     { 
      info = optionalInfo.get(key); 

      if(info == null) 
      { 
       // should be a better exception maybe... depends on how you 
       // want to deal with it 
       throw new IllegalArgumentException(key + " 
                is not a valid property name"); 
      } 
     } 

     return (info); 
    } 

    protected final static class PropertyInfo 
    { 
     private final String name; 
     private final boolean required; 
     private final Class clazz; 
     private final Verifier verifier; 

     protected PropertyInfo(final String nm, 
           final boolean mandatory, 
           final Class c) 
     { 
      this(nm, mandatory, c, getDefaultVerifier(c)); 
     } 

     protected PropertyInfo(final String nm, 
           final boolean mandatory, 
           final Class c, 
           final Verifier v) 
     { 
      // check for null 
      name  = nm; 
      required = mandatory; 
      clazz = c; 
      verifier = v; 
     } 

     @Override 
     public int hashCode() 
     { 
      return (getName().hashCode()); 
     } 

     @Override 
     public boolean equals(final Object o) 
     { 
      final boolean retVal; 

      if(o instanceof PropertyInfo) 
      { 
       final PropertyInfo other; 

       other = (PropertyInfo)o; 
       retVal = getName().equals(other.getName()); 
      } 
      else 
      { 
       retVal = false; 
      } 

      return (retVal); 
     } 

     public boolean verify(final String value) 
     { 
      return (verifier.verify(value)); 
     } 

     public String getName() 
     { 
      return (name); 
     } 

     public boolean isRequired() 
     { 
      return (required); 
     } 

     public Class getType() 
     { 
      return (clazz); 
     } 
    } 

    private static Verifier getDefaultVerifier(final Class clazz) 
    { 
     final Verifier verifier; 

     if(clazz.equals(Boolean.class)) 
     { 
      // shoudl use a singleton to save space... 
      verifier = new BooleanVerifier(); 
     } 
     else 
     { 
      throw new IllegalArgumentException("Unknown property type: " + 
               clazz.getCanonicalName()); 
     } 

     return (verifier); 
    } 

    public static interface Verifier 
    { 
     boolean verify(final String value); 
    } 

    public static class BooleanVerifier 
     implements Verifier 
    { 
     public boolean verify(final String value) 
     { 
      final boolean retVal; 

      if(value.equalsIgnoreCase("true") || 
       value.equalsIgnoreCase("false")) 
      { 
       retVal = true; 
      } 
      else 
      { 
       retVal = false; 
      } 

      return (retVal); 
     } 
    } 
} 

和一个简单的测试吧:

import java.util.Properties; 


public class Main 
{ 
    public static void main(String[] args) 
    { 
     final Properties   properties; 
     final PropertiesVerifier verifier; 

     properties = new Properties(); 
     properties.put("property.one", "true"); 
     properties.put("property.two", "false"); 
//  properties.put("property.three", "5"); 
     verifier = new PropertiesVerifier(
      new PropertiesVerifier.PropertyInfo[] 
      { 
       new PropertiesVerifier.PropertyInfo("property.one", 
                true, 
                Boolean.class), 
       new PropertiesVerifier.PropertyInfo("property.two", 
                false, 
                Boolean.class), 
//    new PropertiesVerifier.PropertyInfo("property.three", 
//             true, 
//             Boolean.class), 
      }); 

     System.out.println(verifier.isKnown("property.one")); 
     System.out.println(verifier.isKnown("property.two")); 
     System.out.println(verifier.isKnown("property.three")); 

     System.out.println(verifier.isRequired("property.one")); 
     System.out.println(verifier.isRequired("property.two")); 
     System.out.println(verifier.isRequired("property.three")); 

     System.out.println(verifier.isOptional("property.one")); 
     System.out.println(verifier.isOptional("property.two")); 
     System.out.println(verifier.isOptional("property.three")); 

     System.out.println(verifier.getType("property.one")); 
     System.out.println(verifier.getType("property.two")); 

     // System.out.println(verifier.getType("property.tthree")); 
     System.out.println(verifier.isValid("property.one", "true")); 
     System.out.println(verifier.isValid("property.two", "false")); 
     // System.out.println(verifier.isValid("property.tthree", "5")); 


     verifier.verifyProperties(properties); 
    } 
} 
1

一个简单的方法是使用示例属性文件分发项目,例如我的项目在svn中有一个“build.properties.example”,其中的属性根据需要进行了评论。本地正确的属性不会进入svn。

既然你提到了“getopt”,但是,我想知道你是否真的在考虑cmd行参数?如果有一个需要特定属性的“主”,我通常会在“使用”消息中输入相关说明,如果参数不正确或“-h”则会打印出来。

+0

你的第一段话告诉他要做他说他已经在做的事。你的第二段与问题无关(他明确表示他在谈论属性文件)。 – 2009-04-08 18:55:23

3

你可以在Apache Commons Configuration包中使用的一些功能。它至少提供了对你的属性的类型访问。

传统java属性文件中只有约定。我见过的一些包括提供,就像你说的,一个示例属性文件。另一个是提供所有属性的默认配置,但注释掉。

如果你真的想要一些东西,也许你不想寻找一个属性文件。您可以使用XML配置文件并指定具有数据类型和要求的模式。您可以使用jaxb将架构编译为java并以此方式读取它。通过验证,您可以确保所需的属性在那里。

您希望得到的最好结果是当您执行应用程序时,它会读取,解析和验证文件中的属性。如果你绝对必须保持基于属性,并不想去xml,但需要这个解析。您可以有一个辅助属性文件,列出可能包含的每个属性,类型以及是否需要。然后您必须编写一个属性文件验证程序,该验证程序将接受要验证的文件以及验证模式类属性文件。像

#list of required properties 
required=prop1,prop2,prop3 

#all properties and their types 
prop1.type=Integer 
prop2.type=String 

我没有看过所有的Apache配置包,但他们经常有这样的有用的实用程序。如果你能在那里找到能简化这一点的东西,我不会感到惊讶。

2

另一个签出的选项是名为OWNER的项目。在那里,您使用类型和注释来定义用作应用程序中配置对象的接口。然后,OWNER发现并解析正确的Properties文件。因此,您可以为您的界面编写一个javadoc并将其用作文档。