JFinal-Undertow 配置文件工作原理

1. 默认配置文件

首先要从 UndertowServer 说起,UndertowServer 有多个创建方法,不管使用哪个创建方法最终创建时创建时都需要先创建 UndertowConfig,并将这个作为参数用于创建 UndertowServer。源码摘取如下:

/**
 * 创建 UndertowServer
 * 
 * 尝试使用 "undertow.txt" 以及 "undertow-pro.txt" 初始化 undertow
 * 当配置文件不存在时不抛出异常而是使用默认值进行初始化
 */
public static UndertowServer create(Class<? extends JFinalConfig> jfinalConfigClass) {
    return new UndertowServer(new UndertowConfig(jfinalConfigClass));
}

同样的 UndertowConfig 也有多个创建方法,不管使用哪个创建方法最终创建时都是需要进行配置文件的加载和配置项的初始化,当指定配置文件名根据指定的配置文件进行加载,未指定配置文件名时将加载默认的配置文件 undertow.txt,并进行参数赋值。源码摘取如下:

public UndertowConfig(String jfinalConfigClass) {
    this.jfinalConfig = jfinalConfigClass;
    //这里未指定参数文件使用默认的undertow.txt
    p = createPropExt(UNDERTOW_CONFIG);
    if (p.notEmpty()) {
        init();
    }
}

2. 生产版本配置文件

JFinal-Undertow 将会自动尝试加载生产版本的配置文件,可以根据默认配置文件或者指定的配置文件自动获取生产版本的配置文件,源码摘取如下:

/**
 * 假定用户创建 UndertowServer 时指定 undertow 的配置文件为 abc.txt
 * 或者 abc-dev.txt 或者 abc_dev.txt,例如:
 *     UndertowServer.create(AppConfig.class, "abc.txt").start();
 * 
 * 尝试加载 abc-pro.txt 便于在 fatjar 模式下以 config 目录中通过创建
 * abc-pro.txt 配置文件覆盖打包在 jar 包中的 abc-dev.txt 配置
 */
protected String buildUndertowConfigPro(String undertowConfig) {
int index = undertowConfig.lastIndexOf('.');
if (index > 0) {
String main = undertowConfig.substring(0, index);
main = removeDevEnds(main);
String ext = undertowConfig.substring(index);
return main + "-pro" + ext;
} else {
return removeDevEnds(undertowConfig) + "-pro";
}
}

3. 配置项默认值

配置文件中的所有项在 UndertowConfig 中都是有默认值得,当没有任何一个配置文件时也就是使用这些默认值了,多数默认值都是 null,有效的几个如下:

// 开发模式才支持热加载,此配置与 jfinal 中的是不同的用途
protected volatile static boolean devMode = false;
protected int port = 80;
protected String host = "0.0.0.0";
protected String contextPath= "/";
// web 资源路径
protected String resourcePath = "src/main/webapp, WebRoot, WebContent";
protected int gzipMinLength = 1024;

4. web 资源加载路径配置

jfinal undertow 可以十分方便地从文件系统的目录以及 class path 或 jar 包中加载 web 静态资源,以下是配置示例:

undertow.resourcePath = src/main/webapp, classpath:static

如上所示 "src/main/webapp" 表示从项目根目录下的 "src/main/webapp" 下去加载 web 静态资源。 "classpath:static" 表示从 class path 以及 jar 包中的 static 路径下去加载 web 静态资源。

undertow.resourcePath 配置的另一个重点是,以 "classpath:" 为前缀的配置需要自行注意路径是否存在,尽可能只配置存在的路径。而不以 "classpath:" 打头的配置可以将开发与部署时的路径一起配置进来(逗号分隔开),jfinal undertow 会在运行时检测路径是否存在,存在才真正让其生效,从而很方便一次配置同时适用于开发、生产两种环境。

重要:PathKit.getWebRootPath() 将指向 undertow.resourcePath 配置中的第一个有效目录,而 configEngine(Engine engine) 方法中的 engine 对象已被默认配置了 engine.setBaseTemplatePath(PathKit.getWebRootPath())。所以该配置与 engine 的 baseTemplatePath 有关联。

实际测试信息记录如下:

  1. JFinal.initPathKit() 中的 servletContext.getRealPath("/"); 获取到的值,取决于 undertow.resourcePath,使用的是第一个有效目录;

  2. 根据代码观察应该是在 UndertowServer.configUndertow 中使用 di.setResourceManager(config.getResourceManager()); 逻辑将 undertow.resourcePath 和 servletContext 做了关联;

  3. 分别在 UndertowServer.start、UndertowServer.doStart、MyConfig.onStart方法中输出了多次 PathKit.getWebRootPath,控制台显示的输出顺序是在 onStart 方法前后都有输出,但是仅有 onStart 方法中输出的信息是在 undertow.txt 中配置的,UndertowServer.start、UndertowServer.doStart 都不是配置中的,这应该就是波总说的时机不对吧,但是能力有限不能很好地理解这个时机。

评论区

JFinal

2020-06-20 17:24

jfinal undertow 的代码虽然极少,但细节极多,要实现的功能十分丰富

从 jfinal undertow 项目中的配置 demo 可以获取到 95% 以上的配置项用法,剩下的需要看看源码,当然,大分部分配置不需要关注, jfinal undertow 很贴心的处理好了默认该做什么

博主的分享非常详细,通过阅读,我自己也回忆起了一篇当初写这些代码的细节。

要实现功能是极端容易的,要简单、全面、通用、体贴入微地实现这些功能是很不容易的,魔鬼都在细节之中

最后,对于人脑来说,输出才是最好的输入,将所理解的知识通过文字或者其它方式输出,才是最好地掌握这些知识的方法

永字诀

2020-06-22 09:47

@JFinal 首先感谢波总的肯定,对“输出才是最好的输入”深有感触,疫情期间利用业余时间更加完整、深入的对文档和源码进行了学习,颇有收获,正在尝试进行更多的“输出”。

JFinal

2020-06-22 17:29

@永字诀 "输出才是最好的输入" 这个是研究认知那帮人研究得出的结论,我因此受益很多年,我学东西、思考都会将精髓输出到笔记中