最近更新

本章节包含 Jmix 框架和 Studio 2.3 的新功能介绍,以及在升级框架版本时需要注意的一些破坏性改动。

如何升级

如需新建 Jmix 2.3 项目或者升级已有项目,需要使用 Studio 2.3 以上版本。因此,请先 升级 Jmix Studio 插件。

IntelliJ IDEA 的最低版本要求是 2023.3。

参阅 升级项目 部分的介绍了解如何使用 Studio 升级项目。自动升级迁移过程会对项目做如下修改:

  • 升级 Jmix BOM 的版本,BOM 又定义了所有依赖的版本。

  • 升级 Jmix Gradle 插件的版本。

  • Gradle 包装器版本更新到 8.7,见 gradle/wrapper/gradle-wrapper.properties

  • frontend/themes/<theme-name>/theme.json 中添加了 lumoImports 属性。

  • 在视图中注入 MessageBundle 时,改用 @ViewComponent 替换了 @Autowired

  • 设置 jmix.ui.component.filter-show-non-jpa-properties 应用程序属性为 false

  • 项目中用到 io.jmix.flowui.component.validation.group.UiCrossFieldChecks 的地方替换成了 io.jmix.core.validation.group.UiCrossFieldChecks

  • 如果项目中使用了 Oracle 数据存储,则会添加 org.eclipse.persistence.oracle 依赖,并更新 JDBC 驱动的依赖。

请参考破坏性改动的 完整列表,并在升级后做相应修复。

新功能和改进

Superset 扩展组件

新的 Superset 扩展组件可以用来在 Jmix 应用程序中集成 Apache Superset。支持在应用程序视图中创建仪表板。

参考 Superset 扩展组件 文档 了解更多信息。

支持 OpenSearch

全文搜索扩展组件除了 Elasticsearch 之外还提供了对 OpenSearch 的支持。参考扩展组件的 安装 部分了解如何选择搜索引擎。

Fragments

Fragment 是一个新的 UI 模块,可以做为视图或其他 fragment 的部分使用。

Fragment 是代码重用的一种新方式,可以将复杂的视图切分为更小,更易于管理的模块。

参考 Fragments 部分了解更多信息。

视图中使用 Data Repositories

现在可以方便地将视图中的加载和保存数据的过程委托给 Spring Data repositories。

创建实体列表或详情视图时,在向导第一页的 Advanced 部分中勾选 Use Data Repositories 复选框,然后从下拉列表中选择已有的 data repository。向导生成的代码会将加载或保存数据的逻辑代理给 data repository 中对应的方法。

继承了 JmixDataRepository 的 repository 中的加载数据方法现在支持一个 JmixDataRepositoryContext 类型的额外参数。可以将 UI 组件中的过滤、分页和排序参数传递给 LoadContext 对象。因此,genericFiltersimplePaginationdataGrid 组件的所有功能都可以通过 data repository 完成。

TabSheet 延迟加载

tabSheet 标签面板 中的 tab 现在可以标记为 lazy。也就是说,这种类型的 tab 内容不会自动加载,这样能显著提高包含多个复杂 tab 的 TabSheet 性能。

参考 Tabs 延迟加载 部分了解更多信息。

TwinColumn 双列组件

增加了新的 twinColumn 双列 组件,用户可以非常直观地在两列之间移动条目从列表或集合中进行选择。

为了修复 #3157,我们修改了 ViewNavigators 的 API:导航时需要指定一个源视图。旧的方法已经废弃,建议使用新的方法进行替换。

如果不是在视图内调用的方法,那么无法将 this 作为源视图提供,可以用 UiComponentUtils.getCurrentView(),示例:

viewNavigators.view(UiComponentUtils.getCurrentView(), viewId).navigate();

在 UI 测试用例中,当前视图可以用 UiTestUtils.getCurrentView() 获取,示例:

View<?> parent = UiTestUtils.getCurrentView();
viewNavigators.view(parent, UserListView.class).navigate();

当导航至流程表单时,Jmix 现在使用 taskIdprocessDefinitionId 作为 URL 参数。这样可以安全重加载页面,也可以保留表单的深度链接。

AuthenticationPrincipalResolver

引入了一个找到当前用户对象的机制。这个机制以链式的方式代理给所有 AuthenticationPrincipalResolver 的实现,尝试找到正确的用户对象。授权服务扩展组件中的标准实现修复了无法在 REST API 请求中使用 用户属性问题

如果需要的话,应用程序项目中也可以提供自定义的 AuthenticationPrincipalResolver 实现。

资源所有者密码凭证授权

授权服务扩展组件现在实现了资源所有者密码凭证授权(Resource Owner Password Credentials grant)。可以用在受信任、旧系统、或高度可控的环境中,REST 客户端可以使用注册的 Jmix 应用程序用户进行简单认证。

参考授权服务扩展组件 文档 了解更多信息。

在通用 REST 中开放服务接口

我们提供了一个新的开放通用 REST 服务接口的方法。

以前我们需要按照通用 REST 文档 的要求创建 rest-services.xml,现在可以直接在类和方法上使用 io.jmix.rest.annotation.RestServiceio.jmix.rest.annotation.RestMethod 注解了。

参考 #1323 了解更多信息。

Liquibase Changelog 聚合

Jmix Studio 数据存储右键菜单提供了一个新的操作:Aggregate Liquibase Changelogs。这个操作可以将几个最新的 changelog 合并为一个,避免 changeset 中的重复操作。

开发者可以在提交代码前使用这个功能合并改动,这样可以维护一个比较简洁的 changelog 并加快应用程序的启动。

生成 UI 异常处理方法

现在可以用 Jmix 工具窗口的 New → Advanced → UI Exception Handler 操作生成 UI 异常处理方法

UI 组件结构改进

  • UI 结构的右键菜单的 Convert to 操作可以把一个组件转换为另一个。

  • 选中多个组件后,可以通过 Wrap into 操作把组件包含在同一个布局容器中。

破坏性改动

UI 安全配置

我们重构了 UI 安全配置。废弃了 io.jmix.securityflowui.FlowuiSecurityConfiguration 类。如果项目中扩展了这个类,必须修改项目中的配置类扩展新的 io.jmix.securityflowui.security.FlowuiVaadinWebSecurity 类。

参考 #3182 了解更多信息。

显式的 Lumo 导入

应用程序主题必须显式声明导入 Lumo 主题,示例:

frontend/themes/onboarding/theme.json
{
 "parent": "jmix-lumo",
 "lumoImports": [
  "typography",
  "color",
  "spacing",
  "badge",
  "utility"
 ]
}

Studio 迁移程序会自动处理这个改动。

参考 #3347 了解更多信息。

@ViewComponent 用于注入消息包

在视图中注入 MessageBundle 时,必须使用 @ViewComponent。Studio 迁移程序会自动修改所有的视图。

参考 #2812 了解更多信息。

延迟加载软删除一对一引用

软删除一对一引用的延迟加载问题已经修复。现在的行为与使用 fetch plan 预加载一致:

  • 软删除的实体在所有侧(owning side)按一对一引用加载。

  • 软删除的实体在映射侧(mappedBy side) 按一对一引用加载。

之前这个行为正好是反的。

参考 #2466 了解更多信息。

VectorLayer 默认样式

使用地图扩展组件时,默认样式现在通过 VectorLayer.removeAllStyles() 移除了。如果需要恢复默认样式,可以在其他样式前显式添加。示例:

@ViewComponent("map.vector")
private VectorLayer vector;

@Subscribe
private void onInit(final InitEvent event) {
    vector.removeAllStyles();
    vector.addStyles(
            Style.createDefaultStyle(),
            new Style());
}

参考 #3140 了解更多信息。

变更日志

  • Jmix 框架解决的问题:

  • Jmix Studio 解决的问题: