Play Framework:在多模块项目中合并多个全局对象

Play Framework: merging multiple Global objects in multi-module project

我正在使用 Play 2.3 构建一个多模块项目,Java 8. 根应用程序和每个模块都有一个全局对象。但是我们怎么知道 Play 仅使用根应用程序中的一个全局对象。

简化的文件夹结构:

/root
    /app
        Global.java
    /conf
        application.conf
    /subprojects
        /user
            /app
               UserGlobal.java
        /admin
            /app
               AdminGlobal.java

所有全局 classes 都放在未命名的包中。

我使用这种方式从子项目中合并全局对象:

1) 在根目录中声明配置变量application.conf

subprojects.with.globals="subprojectName1, subprojectName2, subprojectName3, ..."

2) 在root中添加了私有字段和私有方法Global.java

private List<GlobalSettings> subprojectGlobals = new ArrayList<>();

private void LoadSubprojectGlobals(Application app)
    throws ClassNotFoundException, IllegalAccessException, InstantiationException
{
    String subprojectNames = 
        app.configuration().getString("subprojects.with.globals");
    if (!subprojectNames.isEmpty())
    {
        Class subprojectGlobalClass = null;
        for (String subprojectName : subprojectNames.split(","))
        {
            subprojectGlobalClass = Class.forName(
                WordUtils.capitalize(subprojectName.trim().toLowerCase()) +
                "Global"
            );
            subprojectGlobals.add(
                (GlobalSettings)subprojectGlobalClass.newInstance()
            );
        }
    }
}

3) 将此类代码放入根 Global.java

中的 onStart 事件处理程序中
@Override
public void onStart(Application app)
{
    try
    {
        LoadSubprojectGlobals(app);
    }
    catch(Exception e)
    {
        new RuntimeException(e);
    }

    for(GlobalSettings subprojectGlobal: subprojectGlobals)
    {
        subprojectGlobal.onStart(app);
    }
}

现在,如果我们添加一些新的子项目,我们必须在根 application.conf 中编辑 subprojects.with.globals。如果我们想处理更多的全局设置,我们需要覆盖根目录中的适当方法 Global.java.

如果我们能够从根 onStart 中的 java 代码动态确定所有子项目名称,那将会很棒。可能吗?可能来自 root build.sbt 或来自 Application object?

更新

我使用@Mon Calamari 的方法更改了我的项目。

1) 从根 application.conf.

中删除了配置变量 subprojects.with.globals

2) 将所有子项目 Global classes 放入 globals package:

/subprojects
    /user
        /app
            /globals
                UserGlobal.java
    /admin
        /app
            /globals
                AdminGlobal.java

3) 将配置变量添加到所有子项目 conf 文件中,如

application.global= globals.UserGlobal

4) 更改了 LoadSubprojectGlobals() 实现:

private void LoadSubprojectGlobals(Application app)
    throws ClassNotFoundException, IllegalAccessException, InstantiationException
{
    Reflections reflections = new Reflections("globals");
    Set<Class<? extends GlobalSettings>> subprojectGlobalClasses = 
        reflections.getSubTypesOf(GlobalSettings.class);

    for(Class subprojectGlobalClass : subprojectGlobalClasses)
    {
        subprojectGlobals.add(
            (GlobalSettings)subprojectGlobalClass.newInstance()
        );
    }
}

现在如果我们添加一些新的子项目,我们必须遵循一些关于添加全局的约定 class 但我们不需要跟踪子项目列表。

非常感谢。

我不确定你的 modules/packages 是如何排列的,但是如果你使用 org.reflections 来获取 play.GlobalSettings 的所有扩展名怎么办 class:

Reflections reflections = new Reflections("your.package");    
Set<Class<? extends GlobalSettings>> classes = reflections.getSubTypesOf(GlobalSettings.class)