Java Wildfly:从配置目录读取属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27953261/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 05:21:43  来源:igfitidea点击:

wildfly: reading properties from configuration directory

javajakarta-eejbosscdiwildfly

提问by EasterBunnyBugSmasher

I'm trying to read deployment specific information from a properties file in my wildfly configuration folder. I tried this:

我正在尝试从我的 wildfly 配置文件夹中的属性文件中读取部署特定信息。我试过这个:

@Singleton
@Startup
public class DeploymentConfiguration {

  protected Properties props;

  @PostConstruct
  public void readConfig() {

    props = new Properties();
    try {
      props.load(getClass().getClassLoader().getResourceAsStream("my.properties"));
    } catch (IOException e) {
      // ... whatever
    }
  }

But apparently this is not working since the configuration folder is not in the classpath anymore. Now I can't find an easy way to do it. My favorite would be something like this:

但显然这不起作用,因为配置文件夹不再在类路径中。现在我找不到一个简单的方法来做到这一点。我最喜欢的是这样的:

@InjectProperties("my.properties")
protected Properties props;

The only solution I found on the web so far involves making my own OSGi module, but I believe there must be an easier way to do it (one without OSGi!). Can anyone show me how?

到目前为止,我在网上找到的唯一解决方案是制作我自己的 OSGi 模块,但我相信必须有一种更简单的方法(没有 OSGi!)。谁能告诉我怎么做?

采纳答案by John Ament

If you want to explicitly read a file from the configuration directory (e.g. $WILDFLY_HOME/standalone/configurationor domain/configuration) there's a system property with the path in it. Simply do System.getProperty("jboss.server.config.dir");and append your file name to that to get the file.

如果您想从配置目录(例如$WILDFLY_HOME/standalone/configurationdomain/configuration)中显式读取文件,则有一个带有路径的系统属性。只需执行System.getProperty("jboss.server.config.dir");并将您的文件名附加到该文件即可获取文件。

You wouldn't read it as a resource though, so...

不过,您不会将其视为资源,所以...

String fileName = System.getProperty("jboss.server.config.dir") + "/my.properties";
try(FileInputStream fis = new FileInputStream(fileName)) {
  properties.load(fis);
}

Then the file would be loaded for you.

然后该文件将为您加载。

Also, since WildFly doesn't ship with OSGi support anymore, I don't know how creating an OSGi module would help you here.

此外,由于 WildFly 不再提供 OSGi 支持,因此我不知道创建 OSGi 模块对您有何帮助。

回答by Harald Wellmann

The simplest thing you can do is to run standalone.shwith a -Poption referencing your properties file (you need a URL file:/path/to/my.properties, or put the file in $WILDFLY_HOME/bin).

您可以做的最简单的事情是standalone.sh使用-P引用您的属性文件的选项运行(您需要一个 URL file:/path/to/my.properties,或者将文件放入$WILDFLY_HOME/bin)。

Then all properties from the file will be loaded as system properties.

然后文件中的所有属性都将作为系统属性加载。

For injecting configuration properties into your application classes, have a look at DeltaSpike Configuration, which supports different property sources like system properties, environment variables, JNDI entries and hides the specific source from your application.

要将配置属性注入应用程序类,请查看DeltaSpike Configuration,它支持不同的属性源,如系统属性、环境变量、JNDI 条目,并向应用程序隐藏特定源。

Alternatively, to avoid setting system properties (which will be global in the sense of being visible to all applications deployed to your WildFly instance), you can also define a custom property source for DeltaSpike reading a properties file from any given location, and these properties will be local to your application.

或者,为了避免设置系统属性(对于部署到 WildFly 实例的所有应用程序都可见,这将是全局的),您还可以为 DeltaSpike 从任何给定位置读取属性文件定义自定义属性源,以及这些属性将在您的应用程序本地。

回答by Chris Ritchie

Here is a full example using just CDI, taken from this site.

这是一个仅使用 CDI 的完整示例,取自该站点

  1. Create and populate a properties file inside the WildFly configuration folder

    $ echo 'docs.dir=/var/documents' >> .standalone/configuration/application.properties
    
  2. Add a system property to the WildFly configuration file.

    $ ./bin/jboss-cli.sh --connect
    [standalone@localhost:9990 /] /system-property=application.properties:add(value=${jboss.server.config.dir}/application.properties)
    
  1. 在 WildFly 配置文件夹中创建并填充属性文件

    $ echo 'docs.dir=/var/documents' >> .standalone/configuration/application.properties
    
  2. 向 WildFly 配置文件添加系统属性。

    $ ./bin/jboss-cli.sh --connect
    [standalone@localhost:9990 /] /system-property=application.properties:add(value=${jboss.server.config.dir}/application.properties)
    

This will add the following to your server configuration file (standalone.xml or domain.xml):

这会将以下内容添加到您的服务器配置文件(standalone.xml 或 domain.xml):

<system-properties>
    <property name="application.properties" value="${jboss.server.config.dir}/application.properties"/>
</system-properties>
  1. Create the singleton session bean that loads and stores the application wide properties

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    import javax.annotation.PostConstruct;
    import javax.ejb.Singleton;
    
    @Singleton
    public class PropertyFileResolver {
    
        private Logger logger = Logger.getLogger(PropertyFileResolver.class);
        private String properties = new HashMap<>();
    
        @PostConstruct
        private void init() throws IOException {
    
            //matches the property name as defined in the system-properties element in WildFly
            String propertyFile = System.getProperty("application.properties");
            File file = new File(propertyFile);
            Properties properties = new Properties();
    
            try {
                properties.load(new FileInputStream(file));
            } catch (IOException e) {
                logger.error("Unable to load properties file", e);
            }
    
            HashMap hashMap = new HashMap<>(properties);
            this.properties.putAll(hashMap);
        }
    
        public String getProperty(String key) {
            return properties.get(key);
        }
    }
    
  2. Create the CDI Qualifier. We will use this annotation on the Java variables we wish to inject into.

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import javax.inject.Qualifier;
    
    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR })
    public @interface ApplicationProperty {
    
        // no default meaning a value is mandatory
        @Nonbinding
        String name();
    }
    
  3. Create the producer method; this generates the object to be injected

    import javax.enterprise.inject.Produces;
    import javax.enterprise.inject.spi.InjectionPoint;
    import javax.inject.Inject;
    
    public class ApplicaitonPropertyProducer {
    
        @Inject
        private PropertyFileResolver fileResolver;
    
        @Produces
        @ApplicationProperty(name = "")
        public String getPropertyAsString(InjectionPoint injectionPoint) {
    
            String propertyName = injectionPoint.getAnnotated().getAnnotation(ApplicationProperty.class).name();
            String value = fileResolver.getProperty(propertyName);
    
            if (value == null || propertyName.trim().length() == 0) {
                throw new IllegalArgumentException("No property found with name " + value);
            }
            return value;
        }
    
        @Produces
        @ApplicationProperty(name="")
        public Integer getPropertyAsInteger(InjectionPoint injectionPoint) {
    
            String value = getPropertyAsString(injectionPoint);
            return value == null ? null : Integer.valueOf(value);
        }
    }
    
  4. Lastly inject the property into one of your CDI beans

    import javax.ejb.Stateless;
    import javax.inject.Inject;
    
    @Stateless
    public class MySimpleEJB {
    
        @Inject
        @ApplicationProperty(name = "docs.dir")
        private String myProperty;
    
        public String getProperty() {
            return myProperty;
        }
    }
    
  1. 创建加载和存储应用程序范围属性的单例会话 bean

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    import javax.annotation.PostConstruct;
    import javax.ejb.Singleton;
    
    @Singleton
    public class PropertyFileResolver {
    
        private Logger logger = Logger.getLogger(PropertyFileResolver.class);
        private String properties = new HashMap<>();
    
        @PostConstruct
        private void init() throws IOException {
    
            //matches the property name as defined in the system-properties element in WildFly
            String propertyFile = System.getProperty("application.properties");
            File file = new File(propertyFile);
            Properties properties = new Properties();
    
            try {
                properties.load(new FileInputStream(file));
            } catch (IOException e) {
                logger.error("Unable to load properties file", e);
            }
    
            HashMap hashMap = new HashMap<>(properties);
            this.properties.putAll(hashMap);
        }
    
        public String getProperty(String key) {
            return properties.get(key);
        }
    }
    
  2. 创建 CDI 限定符。我们将在我们希望注入的 Java 变量上使用这个注解。

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    import javax.inject.Qualifier;
    
    @Qualifier
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR })
    public @interface ApplicationProperty {
    
        // no default meaning a value is mandatory
        @Nonbinding
        String name();
    }
    
  3. 创建生产者方法;这将生成要注入的对象

    import javax.enterprise.inject.Produces;
    import javax.enterprise.inject.spi.InjectionPoint;
    import javax.inject.Inject;
    
    public class ApplicaitonPropertyProducer {
    
        @Inject
        private PropertyFileResolver fileResolver;
    
        @Produces
        @ApplicationProperty(name = "")
        public String getPropertyAsString(InjectionPoint injectionPoint) {
    
            String propertyName = injectionPoint.getAnnotated().getAnnotation(ApplicationProperty.class).name();
            String value = fileResolver.getProperty(propertyName);
    
            if (value == null || propertyName.trim().length() == 0) {
                throw new IllegalArgumentException("No property found with name " + value);
            }
            return value;
        }
    
        @Produces
        @ApplicationProperty(name="")
        public Integer getPropertyAsInteger(InjectionPoint injectionPoint) {
    
            String value = getPropertyAsString(injectionPoint);
            return value == null ? null : Integer.valueOf(value);
        }
    }
    
  4. 最后将该属性注入您的一个 CDI bean

    import javax.ejb.Stateless;
    import javax.inject.Inject;
    
    @Stateless
    public class MySimpleEJB {
    
        @Inject
        @ApplicationProperty(name = "docs.dir")
        private String myProperty;
    
        public String getProperty() {
            return myProperty;
        }
    }
    

回答by Sr Bruno

It sounds like the problem you are trying to solve is managing different (but probably similar) configuration files for running your application in different environments (ie, Production, QA, or even different customers). If that is the case, take a look at Jfig http://jfig.sourceforge.net/. It would obviate the need for storing property files outside your classpath (but you still could).

听起来您要解决的问题是管理不同(但可能相似)的配置文件,以便在不同环境(即生产、QA 甚至不同的客户)中运行您的应用程序。如果是这种情况,请查看 Jfig http://jfig.sourceforge.net/。这将消除在类路径之外存储属性文件的需要(但您仍然可以)。

What is needed is a hierarchical approach to configuration files. The ninety percent of configuration values that do not change can be maintained in a base file. The other ten percent (or less) may be maintained in their own distinct configuration file. At run time, the files are layered on top of each other to provide a flexible, manageable configuration. For example, in a development environment myhost.config.xml combines with dev.config.xml and base.config.xml to form my unique configuration.

Each configuration file may then be maintained in version control as they have unique names. Only the base files need to be modified when base values change, and it is easy to see the difference between versions. Another major benefit is that changes to the base configuration file will be exhaustively tested before deployment.

需要的是配置文件的分层方法。90% 不变的配置值可以保存在一个基本文件中。其他百分之十(或更少)可以在它们自己不同的配置文件中维护。在运行时,这些文件相互叠加,以提供灵活、可管理的配置。例如,在开发环境中 myhost.config.xml 与 dev.config.xml 和 base.config.xml 结合形成我的独特配置。

每个配置文件都可以在版本控制中维护,因为它们具有唯一的名称。基值变化时只需要修改基文件,很容易看出版本差异。另一个主要好处是在部署之前将对基本配置文件的更改进行详尽的测试。

回答by Wender

InputStream in = null;
File confDir = new File(System.getProperty("jboss.server.config.dir"));
File fileProp = new File(confDir, "my.properties");

try{
    //teste fileProp.exists etc.

    in = new FileInputStream(fileProp);
    Properties properties = new Properties();
    properties.load(in);

    //You should throws or handle FileNotFoundException and IOException
}finally{
    try{
        in.close();
    }catch(Exception ignored){
    }
}

回答by Ibrahim BEN ABDERRAHMANE

To avoid this kind of problem the issue is to set the jboss.server.config.dirin VM arguments like that :

为了避免这种问题,问题是jboss.server.config.dir在 VM 中设置这样的参数:

-Djboss.server.config.dir="[jboss_repository]/server/[default-all-standard-standalone]/conf" –server

回答by stakahop

If you have in standalone.xml property:

如果您在 standalone.xml 属性中有:

<property name="my.properties" value="propertyValue"/>

you can wasily read it with:

你可以轻松地阅读它:

static final String MY_PROPERTY = System.getProperty("my.properties");

Or if you specify context param in web.xml like:

或者,如果您在 web.xml 中指定上下文参数,例如:

<context-param>
    <param-name>MyProperty</param-name>
    <param-value>MyPropertyValue</param-value>
</context-param>

You can read it in Java bean:

您可以在 Java bean 中阅读它:

String myProperty= getServletContext().getInitParameter("MyProperty");