wildfly:从配置目录读取属性

Posted

技术标签:

【中文标题】wildfly:从配置目录读取属性【英文标题】:wildfly: reading properties from configuration directory 【发布时间】:2015-03-13 05:53:59 【问题描述】:

我正在尝试从 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
    
  

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

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

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

【问题讨论】:

如果文件在 WildFly 配置文件夹中,那么它是全局的,而不是特定于部署的。这有点令人困惑...... 也许我误用了“特定于部署”这个词。该文件位于 wildfly/standalone/configuration 文件夹中。 如果我记得清楚的话,我曾经在这个文件夹下有我的配置,我只是通过简单地做 File("myfile.properties") 解析到这个路径(我想这可能是工作目录老板) 【参考方案1】:

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

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

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

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

【讨论】:

所以我在 deltaspike 网站上找到了这个 sn-p:@Inject @InjectableResource("myfile.properties") private InputStream inputStream;我还没有下载 DeltaSpike,所以我还不能测试它。我的问题是:如果配置文件夹不在类路径中并且我没有配置查找位置,DeltaSpike 如何从配置文件夹中读取此文件? WildFly 读取文件,而不是 DeltaSpike - DeltaSpike 读取 WildFly 设置的系统属性。要通过 DeltaSpike(我的回答的最后一段)读取文件,您需要实现自定义 DeltaSpike 配置源并将其注册到 DeltaSpike。您将使用文件路径,而不是类路径来访问该文件。 感谢您的输入,但对我来说有点太复杂了。 this github repo 显示了 Harald 在代码中的含义【参考方案2】:

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

你不会把它当作资源来阅读,所以......

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

然后将为您加载文件。

另外,由于 WildFly 不再支持 OSGi,我不知道创建 OSGi 模块对您有什么帮助。

【讨论】:

这么简单,为什么不是我自己想出来的呢?我在考虑类路径。 输入流保持打开状态。不要直接传递给 properties.load 你是对的@Wender,但老实说,我只是想把它当作伪代码。 注意 jboss.server.config.dir 与 jboss.domain.config.dir 不同。如果您的应用同时部署到独立环境和域环境,则需要进行一些调整。【参考方案3】:

这是一个仅使用 CDI 的完整示例,取自 site。

    在 WildFly 配置文件夹中创建并填充属性文件

    $ echo 'docs.dir=/var/documents' >> .standalone/configuration/application.properties
    

    向 WildFly 配置文件添加系统属性。

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

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

<system-properties>
    <property name="application.properties" value="$jboss.server.config.dir/application.properties"/>
</system-properties>

    创建加载和存储应用程序范围属性的单例会话 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);
        
    
    

    创建 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();
    
    

    创建生产者方法;这会生成要注入的对象

    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);
        
    
    

    最后将属性注入您的 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;
        
    
    

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:
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)
    

【讨论】:

【参考方案6】:

为避免此类问题,问题是在 VM 参数中设置 jboss.server.config.dir,如下所示:

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

【讨论】:

添加更多描述。【参考方案7】:

如果你有standalone.xml 属性:

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

你可以用以下方式阅读它:

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

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

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

你可以在 Java bean 中阅读它:

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

【讨论】:

以上是关于wildfly:从配置目录读取属性的主要内容,如果未能解决你的问题,请参考以下文章

Wildfly 10 - 以编程方式读取配置参数

如何使用 JPA/EJB3 和 WildFly 读取未提交的数据?

如何从类路径中读取log4j属性文件

如何配置从 Eclipse 到 Wildfly 的部署

JPA 未在 WildFly 16 上保存到数据库

Wildfly 8.1.0 以备用配置独立运行