热部署
Jmix 支持热部署技术,该技术支持将项目更改立即应用于正在运行的应用程序,而无需重新启动应用服务。
热部署支持下列类和资源:
-
视图 XML 描述和控制器
-
视图控制器用来初始化或通过静态方法访问的类。示例请参考 后续内容。
-
本地化消息
-
菜单
-
Fetch plans
-
资源角色
-
行级角色
实体类和 Spring bean 不支持热部署。
热部署工作原理如下:
-
Studio 会检查更改的源文件:
-
如果是资源文件,Studio 将这些资源文件复制到
.jmix/conf文件夹; -
如果是 Java 或 Kotlin 源文件,Studio 会编译这些文件并复制到项目的
build/classes文件夹。
-
-
当应用程序打开新视图时,会从上述文件夹中加载新的类和资源文件。
热部署资源放置的文件夹位置通过 jmix.core.conf-dir 应用程序属性确定。在应用程序启动时,该文件夹会由 Run/Debug Configuration Settings 中配置的 Before launch 任务清空。
此外,为了确保清理工作更加可靠,且不依赖 Studio,可以使用名为 cleanConf 的 Gradle 任务。这个任务每次在通过 bootRun 启动应用程序时运行。
如果在使用清理功能时出现问题,可以在项目中禁用 cleanConf 任务,需要添加以下内容至 build.gradle:
jmix {
// ...
confDirCleanupEnabled = false
}
Studio 还会向应用程序发送信号,要求清除相应的缓存,以便加载更改后的资源。包括消息缓存、fetch plan 配置、注册的视图以及菜单项。信号是作为一个触发器文件放在 .jmix/temp/triggers 目录中(目录可通过 jmix.core.temp-dir 配置修改)。
| 应用程序可能需要 2-3 秒重新加载 Studio 保存后的类和资源文件。如果在打开的视图看不到期望的改动,可以尝试刷新网页。 |
支持热部署的类示例
以下是一些实际的例子:视图控制器使用的能支持热部署的类。
包含静态方法的工具类
当从视图控制器调用时,包含静态方法的工具类支持热部署。
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class DateUtils {
public static String formatDate(LocalDate date) {
return date.format(DateTimeFormatter.ofPattern("dd.MM.yyyy"));
}
private DateUtils(){
}
}
在视图控制器中:
@ViewComponent
private TypedTextField<String> textField;
@Subscribe
public void onInit(final InitEvent event) {
String formattedDate = DateUtils.formatDate(LocalDate.now());
textField.setValue(formattedDate);
}
热部署指示器
Studio 在支持热部署的文件顶部右上角会显示一个状态指示图标。这些文件包括视图控制器、视图 XML 描述、消息包、角色以及其他类似的资源文件,为特定文件的热部署显示一个快速反馈的状态信息。
设置这个指示器的目的主要是持续提醒开发者他们最新修改的文件是否对应用程序做了修改。图标的外观会不断变化,以反映修改是否成功部署还是在部署中,亦或部署失败,从而提供热部署状态的一个直观反馈。
下面是热部署指示器的不同状态。
-
应用程序未启动:
指示器显示为灰色的轮廓。点击指示器将弹出带有启动应用程序选项的消息。
-
应用程序正在运行,无文件修改:
指示器显示为绿色的轮廓。点击指示器将弹出文件未热部署的消息。
-
文件已修改,可以热部署:指示器变为实心的绿色。点击指示器将弹出可以热部署该文件的消息。
发起热部署之后,指示器保持实心的绿色,弹窗消息显示上次热部署的时间:
-
热部署失败:指示器变红,表示热部署由于编译错误或其他原因失败。
故障排查
在某些情况下,例如对于非标准的多模块项目配置,Jmix Studio 可能无法确定模块编译器的输出路径。从而影响热部署,因为 Studio 无法正确解析热部署编译过程所需的 classpath。
如果遇到此问题,可以在 build.gradle 脚本中使用特定属性手动指定模块编译器输出路径:
ext.jmixCompilerOutputPath = "build/classes/java/main"
该路径需设置为相对于构建脚本的目录。Jmix Studio 将在 Gradle 同步期间解析该配置,并用于热部署编译过程的 classpath 中。