配置加载器

警告

这些文档是为 SpongeAPI 7 编写的,可能已经过时。 如果你觉得你可以帮助更新它们,请提交一个 PR!

让我们分解 Configurate 的整个工作流程,从加载开始。 Configurate 提供了 ConfigurationLoader 用于常见的配置格式,并用于管理物理上的配置文件,允许你通过给定资源读取或存储数据。它们还允许你加载空配置,并给予你权利去指定硬编码的默认值,或者从一个已经写好的文件指定默认值。

小訣竅

Sponge 插件推荐使用的配置文件格式是 HOCON,这也是默认的格式。

获取配置加载器

備註

默认的 ConfigurationLoader 可用于单个 HOCON 格式的配置文件的场景。请参见 插件配置 页面的相关内容。

首先,让我们新建一个 HoconConfigurationLoader 并指向我们的配置文件。

import java.nio.file.Path;
import org.spongepowered.configurate.commented.CommentedConfigurationNode;
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
import org.spongepowered.configurate.loader.ConfigurationLoader;

Path potentialFile = getConfigPath();
ConfigurationLoader<CommentedConfigurationNode> loader =
        HoconConfigurationLoader.builder().setPath(potentialFile).build();

配置加载器同时会存有一个泛型以决定其会构建什么样的节点类型。关于节点,也就是 Configuration Nodes 的内容,会在 稍后的章节 中加以阐述。

ConfigurationLoader 通常持有一个生成器( Builder )用于静态地访问和创建一个你想要的类型的新加载器。对于基本的配置,我们并不需要指定除了我们想要加载和保存的文件之外的其他东西。因此,我们需要做的全部事情就是使用 HoconConfigurationLoader.builder().setPath(path) 。然后我们通过生成器生成(build())了一个实例并将其存储在了一个变量里。

当然,这并不是加载文件的唯一方法。生成器还有一个名为 setURL(url) 的方法,如果你想要加载的资源不使用 Path 的话可以使用。时刻注意,通过 URL 创建的配置加载器是只读的,因为它们没有办法把数据写回 URL。

这一功能可以用于把你的插件 JAR 中的一个文件绑定到默认的配置上,然后将其作为初始化时的配置文件以供服务器管理员(或者插件本身)修改。

備註

这个例子中使用了 Sponge 推荐的 HoconConfigurationLoader,但你仍然可以使用 YAMLConfigurationLoaderGsonConfigurationLoader 加载旧版配置文件。

加载和保存

当你获取到了 ConfigurationLoader ,就可以通过 createEmptyNode() 方法来获取一个空的 ConfigurationNode

import org.spongerpowered.configurate.ConfigurationNode;
import org.spongerpowered.configurate.ConfigurationOptions;

Path potentialFile = getConfigPath();
ConfigurationLoader<CommentedConfigurationNode> loader =
        HoconConfigurationLoader.builder().setPath(potentialFile).build();
ConfigurationNode rootNode = loader.createEmptyNode(ConfigurationOptions.defaults());

这个方法期望一个 ConfigurationOptions 作为参数。除非你有想要使用的特性,如自定义类型的序列化方式,否则你直接使用 ConfigurationOptions#defaults() 来创建这个参数作为默认值就可以了。

可以通过使用 load() 方法在 ConfigurationLoader 创建时从指定的源加载配置内容。当然它也需要一个 ConfigurationOptions 的实例,而且同时提供一个等价于 load(ConfigurationOptions.defaults()) 的简写形式。

import java.io.IOException;

Path potentialFile = getConfigPath();
ConfigurationLoader<CommentedConfigurationNode> loader =
        HoconConfigurationLoader.builder().setPath(potentialFile).build();
ConfigurationNode rootNode;
try {
    rootNode = loader.load();
} catch(IOException e) {
    // handle error
}

如果给定的 Path 不存在,那么 load() 方法将会创建一个空的 ConfigurationNode 。任何可能的错误都将会抛出一个 IOException ,因此你需要对其进行妥善处理。

如果你使用了默认的配置加载器,我们建议你获取相应的 ConfigurationOptions 对象,因为你可以通过它序列化 Sponge 中出现的绝大部分对象。

一旦你修改了你的 ConfigurationNode 并想要保存修改过的数据,你可以通过 ConfigurationLoader 保存你的节点至你初始化时设置的文件中。如果这么一个文件不存在,那么它将被创建,如果存在,那么它将被覆盖。

try {
    loader.save(rootNode);
} catch(IOException e) {
    // handle error
}

再一次地,所有的错误都会抛出一个 IOException ,同时你必须处理它。

小訣竅

我们建议在插件加载完配置之后,也就是配置更新之后立刻保存配置文件,确保新增项目或从旧版配置转换来的项目能及时保存到硬盘上。如果不能及时保存,我们强烈建议保存的操作在非主线程上进行。参考你应当避免的不好的實現

从插件的 jar 中加载默认配置

很多开发者喜欢在插件中捆绑一份默认配置文件,并在缺失时自动复制到配置文件目录中。你可以使用 FIXME(尚未完成) 来实现这个效果,如下面的示例所示:

PluginContainer plugin = ...;
Path path = ...;

Sponge.getAssetManager().getAsset(plugin, "default.conf").get().copyToFile(path, false, true);
loader = HoconConfigurationLoader.builder().setPath(path).build();
rootNode = loader.load();

在这一示例中需要着重注意的一点是,AssetManager#getAsset(String) 这个方法是以插件的 Asset 目录为根目录查找文件的。因此,如果上面的示例中的插件 ID 为 myplugin ,那么 default.conf 不应放在 JAR 的根目录中,而是放在 assets/myplugin 目录下。本示例中使用的 Asset#copyToFile(Path, boolean, boolean) 还允许你强制覆盖已有的同名文件。

備註

若你的插件的 jar 中找不到目标配置文件,你会在调用 Optional<Asset>.get() 时得到一个 NoSuchElementException 异常。请确保你已正确配置了你的构建系统,使之能把配置文件一并打包进去。

如果你有其他的配置类,还有一个更简单的解决方案,且在配置文件缺失一部分时也能使用。参考“序列化对象”一文了解这个解决方案的具体细节。

根据默认配置更新配置文件

如果你想把新的配置节点合并入已有的配置文件中,你可以使用 CommentedConfigurationNode 来从指定 asset 中加载对应的值,具体方式上文中已经说明。它会尝试从指定 asset 中提取节点并尝试在缺失的情况下插入已有配置中。和直接覆盖不一样,这个操作只会更新原配置中缺失的内容。

PluginContainer plugin = ...;

node.mergeValuesFrom(HoconConfigurationLoader.builder()
                    .setURL(plugin.getAsset("default.conf").get().getUrl())
                    .build()
                    .load(ConfigurationOptions.defaults()));

備註

这样做不会影响既有的节点,所以不论服务器上是否已经有对应的配置文件都可以调用这个方法。