【问题标题】:Load java properties inside static initializer block在静态初始化块中加载 java 属性
【发布时间】:2010-11-05 21:39:28
【问题描述】:

我有一个静态实用程序类,它对一些敏感数据进行一些字符串操作。 在使用这个类之前,我需要用值初始化某些静态变量,例如用户名/密码,我更喜欢将它们存储在 .properties 文件中。

我不太熟悉在 Java 中加载 .properties 文件的工作方式,尤其是在 *Spring DI *container 之外。 任何人都可以帮助我了解如何做到这一点?

谢谢!

补充: .properties 文件的精确位置未知,但它会在类路径上。有点像classpath:/my/folder/name/myproperties.propeties

【问题讨论】:

  • 您提到了 Spring - 您是否在应用程序中使用包含此静态实用程序类的框架?
  • 嗯,这有点奇怪。类将在使用 spring 容器的应用程序中使用。然而,类本身不会使用 spring 连接,它需要只是一个静态实用程序类,由 Spring 连接的工作线程调用。我可以修改工作线程,但我不能修改这些线程的接线(所以我不能使用 PropertyPlaceHolderConfigurer)......嗯,这有意义吗? :)

标签: java properties


【解决方案1】:

首先,获取要从中加载属性的InputStream。这可能来自多个位置,包括一些最有可能的位置:

  • FileInputStream,使用硬编码或通过system property. 指定的文件名创建。名称可以是相对的(相对于 Java 进程的当前工作目录)或绝对的。
  • 资源文件(类路径上的文件),通过在Class(相对于类文件)或ClassLoader(相对于类路径的根)上调用getResourceAsStream 获得。请注意,如果资源丢失,这些方法将返回 null,而不是引发异常。
  • URL,与文件名一样,可以硬编码或通过系统属性指定。

然后创建一个新的Properties 对象,并将InputStream 传递给它的load() 方法。一定要关闭流,不管有什么异常。

在类初始化器中,必须处理像IOException 这样的已检查异常。可以抛出未经检查的异常,这将阻止类被初始化。反过来,这通常会阻止您的应用程序运行。在许多应用程序中,可能需要改用默认属性,或者回退到其他配置源,例如在交互式上下文中提示使用。

总而言之,它可能看起来像这样:

private static final String NAME = "my.properties";

private static final Properties config;

static {
  Properties fallback = new Properties();
  fallback.put("key", "default");
  config = new Properties(fallback);

  URL res = MyClass.getResource(NAME);
  if (res == null) throw new UncheckedIOException(new FileNotFoundException(NAME));
  URI uri;
  try { uri = res.toURI(); }
  catch (URISyntaxException ex) { throw new IllegalArgumentException(ex); }

  try (InputStream is = Files.newInputStream(Paths.get(uri))) { config.load(is); } 
  catch (IOException ex) { throw new UncheckedIOException("Failed to load resource", ex); }
}

【讨论】:

    【解决方案2】:
    1. 查看java.util.Properties

    2. 您可以使用静态初始化程序。所以在课堂上你可以做:

    
     static {
        Properties props = new Properties();
        InputStream steam = ...; // open the file
        props.load(stream);
    
        // process properties content
        String username = props.getProperty("username");
      }
    

    【讨论】:

    • 对不起,我猜你在我做的时候已经在格式化代码了。
    • 您可能需要一些异常处理,因为我不认为可以从静态块中抛出异常。
    • RuntimeExceptions 可以从静态块中抛出。您将需要处理文件操作的检查异常。
    • 这里建议的实现主要是为了说明。要使其达到生产质量,您需要处理与文件相关的异常(例如安全性、存在性、IOException),在 finally 块中关闭连接,处理加密(我希望他不要以明文形式保存密码)等
    【解决方案3】:

    使用任一:

    CurrentClassName.class.getResourceAsStream 
    new FileInputStream(File)
    

    根据类是否在类路径中来获取输入流。然后使用

    Properties.load
    

    加载属性。

    【讨论】:

      【解决方案4】:

      已经有一段时间了,但如果我没记错的话,你只需这样做:

      Properties prop = new Properties();
      prop.load(new FileInputStream(filename));
      
      //For each property you need.
      blah = prop.getProperty(propertyname);
      

      【讨论】:

        【解决方案5】:

        对于静态属性,将它们初始化为将在类中加载一次的单例是有意义的。这是一个例子:

        class Example
        {
            public final static String PROPSFILE = "test.properties";
        
            private static Properties props;
        
            protected static Properties getProperties()
            {
                if(props == null)
                {
                    props = new Properties();
                    props.load(new FileInputStream(new File(PROPSFILE));
                }
                return props;
            }
        
            public static User getUser()
            {
                String username = getProperties().getProperty("username");
                return new User(username);
            }
        }
        

        如果您使用相对路径名,您应该确保您的类路径设置正确。

        【讨论】:

        • 那不是单例。它只是一个静态变量和方法。该问题不需要公开访问属性,但需要从属性文件初始化静态成员。
        • 好吧,我个人不喜欢静态初始化,因为它在我正在从事的项目中造成了一些麻烦。我建议尽可能使用至少静态工厂方法(我为此更新了示例)。但确实,这实际上不是问题。
        【解决方案6】:

        对我来说 MyClass.class.getClassLoader().getResourceAsStream(..) 成功了:

        private static final Properties properties;
        
        static {
            Properties fallback = new Properties();
            fallback.put(PROP_KEY, FALLBACK_VALUE);
        
            properties = new Properties(fallback);
        
            try {
                try (InputStream stream = MyClass.class.getClassLoader().getResourceAsStream("myProperties.properties")) {
                    properties.load(stream);
                }
            } catch (IOException ex) {
                // handle error
            }
        }
        

        【讨论】:

          【解决方案7】:

          我同意@Daff,也许最好使用单例类...这是我在项目中对类似要求的要求,也许它可能会有所帮助:

          类的客户可以这样使用它:

          ConfigsLoader configsLoader = ConfigsLoader.getInstance("etc/configs.xml");
          
          System.out.format("source dir %s %n", configsLoader.getSourceDir());
          

          然后是班级:

          公共类 ConfigsLoader {

          private String sourceDir;
          private String destination;
          private String activeMqUrl;
          
          private static Logger log = Logger.getLogger(ConfigsLoader.class.getName());
          
          private static ConfigsLoader instance = null;
          
          private ConfigsLoader(String configFileName) {
              log.info("loading configs");
              Properties configs = new Properties();
              try {
                  configs.loadFromXML(new FileInputStream(configFileName));
          
                  sourceDir = configs.getProperty("source.dir");
                  destination = configs.getProperty("destination");
                  activeMqUrl = configs.getProperty("activemqconnectionurl");
                  configs.setProperty("lastLoaded", new SimpleDateFormat("yyyy-M-d HH:mm").format(new Date()));
                  configs.storeToXML(new FileOutputStream(configFileName), "saving last modified dates");
          
              } catch (InvalidPropertiesFormatException e) {
                  log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
              } catch (FileNotFoundException e) {
                  log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
              } catch (IOException e) {
                  log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
              }
          }
          
          public static ConfigsLoader getInstance(String configFileName) {
              if(instance ==null) {
                  instance = new ConfigsLoader(configFileName);
              }
          
              return instance;
          }
          
          public String getSourceDir() {
              return sourceDir;
          }
          
          public void setSourceDir(String sourceDir) {
              this.sourceDir = sourceDir;
          }
          
          public String getDestination() {
              return destination;
          }
          
          public void setDestination(String destination) {
              this.destination = destination;
          }
          
          public String getActiveMqUrl() {
              return activeMqUrl;
          }
          
          public void setActiveMqUrl(String activeMqUrl) {
              this.activeMqUrl = activeMqUrl;
          }
          

          }

          【讨论】:

            【解决方案8】:

            我最终使用与正在编写静态代码块的类关联的 getResourceAsStream() 函数完成了此操作。

            //associate Property and ImputStream imports
            public class A {
                static Properties p;
                static {
                  p = new Properties();
                  try {
                      InputStream in = A.class.getResourceAsStream("filename.properties");
                      p.load(in);
                  } catch (FileNotFoundException e) {
                    System.out.println("FileNotFoundException");
                    e.printStackTrace();
                  } catch (IOException e) {
                    System.out.println("IOException");
                    e.printStackTrace();
                  }
                }
                .
                .
                .
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-01-26
              • 2011-02-04
              • 2012-09-15
              • 1970-01-01
              • 2023-03-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多