配置加载器
让我们分解 Configurate 的整个工作流程,从加载开始。 Configurate 提供了 ConfigurationLoader 用于常见的配置格式,并用于管理物理上的配置文件,允许你通过给定资源读取或存储数据。它们还允许你加载空配置,并给予你权利去指定硬编码的默认值,或者从一个已经写好的文件指定默认值。
小訣竅
Sponge 插件推荐使用的配置文件格式是 HOCON,这也是默认的格式。
获取配置加载器
備註
默认的 ConfigurationLoader 可用于单个 HOCON 格式的配置文件的场景。请参见 插件配置 页面的相关内容。
首先,让我们新建一个 HoconConfigurationLoader 并指向我们的配置文件。
import java.nio.file.Path;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.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
,但你仍然可以使用 YAMLConfigurationLoader 或 GsonConfigurationLoader 加载旧版配置文件。
加载和保存
当你获取到了 ConfigurationLoader
,就可以通过 createEmptyNode() 方法来获取一个空的 ConfigurationNode 。
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.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 中加载默认配置
很多开发者喜欢在插件中捆绑一份默认配置文件,并在缺失时自动复制到配置文件目录中。你可以使用 Asset API 来实现这个效果,如下面的示例所示:
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()));
備註
这样做不会影响既有的节点,所以不论服务器上是否已经有对应的配置文件都可以调用这个方法。