最近更新

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

如何升级

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

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

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

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

  • 升级 Jmix Gradle 插件的版本。

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

  • 如果项目使用了 REST API 扩展组件,需要添加 jmix.resource-server.authenticated-url-patterns 属性。参阅 下面内容

  • 将输入对话框 Builder 中的 dateTimeParameter()dateParameter()timeParameter() 方法替换为 localDateTimeParameter()localDateParameter()localTimeParameter() 方法。详情参阅 下面内容

  • 如果项目包含了数据工具扩展组件,则会添加表格导出扩展组件。详情参阅 下面内容

  • 设置 jmix.ui.component.default-trim-enabled 应用程序属性为 false。详情参阅 下面内容

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

如果项目升级并启动应用程序后,遇到以下异常:

com.vaadin.flow.server.ExecutionFailedException: Vite build exited with a non zero status

需要从项目目录删除这些文件或文件夹:node_modulespackage.jsonpnpm-lock.yamltsconfig.jsontypes.d.tsvite.config.tsvite.generated.ts

另外,如果安装了全局的 Node.js,则需要升级至 https://nodejs.org 列出的最新的 LTS 版本。

依赖更新

下列主要依赖库更新:

新功能和改进

新扩展组件

下列新的扩展组件已经可用:

  • 日历 扩展组件提供一个 UI 组件,支持在不同视图(日、周、月等)的日历中显示数据绑定的事件,并可通过拖拽和调整大小进行编辑。

  • 透视表 扩展组件提供一个 UI 组件,可以将数据集转换为汇总表,并可以使用 2D 拖放 UI 进行操作。

  • Kanban 看板 扩展组件提供一个 UI 组件用于展示项目的看板。可以显示项目不同阶段的工作流,任务显示为卡片和不同的阶段显示为看板列。

  • UI 约束 扩展组件可以通过资源角色中声明式的策略控制 UI 组件的可见性和可访问性。

  • REST 数据存储 扩展组件支持通过标准的 DataManager 接口从访问远程 Jmix 应用程序中的实体,与访问本地 JPA 实体一样。

HTML 组件的数据绑定

HTML 组件,例如 div, span, h1…​h5 等,现在支持在 XML 中通过 dataContainerproperty 属性与数据模型的实体绑定了。

很多情况下可以不用在控制器中为这些组件手动设置值了。

Fragment 渲染器

virtualList 列表dataGrid 数据网格 以及其他组件的渲染器现在可以通过 fragments 定义了。

需要使用新的 fragmentRenderer XML 元素并指定 fragment 的 Java 类,示例:

<virtualList itemsContainer="usersDc">
    <fragmentRenderer class="com.company.onboarding.view.userfragment.UserFragment"/>
</virtualList>

下面是用作渲染器 fragment 的内容:

<fragment xmlns="http://jmix.io/schema/flowui/fragment">
    <data>
        <instance id="userDc" class="com.company.onboarding.entity.User">
            <loader id="userDl"/>
        </instance>
    </data>
    <content>
            <formLayout id="form" dataContainer="userDc">
                <textField id="usernameField" property="username" readOnly="true"/>
                <textField id="firstNameField" property="firstName"/>
                <textField id="lastNameField" property="lastName"/>
                <textField id="emailField" property="email"/>
            </formLayout>
        </hbox>
    </content>
</fragment>

Fragment 渲染器类需要继承自 FragmentRenderer 基类,并使用类型参数表示 fragment 的根组件和渲染的实体,示例:

@FragmentDescriptor("user-fragment.xml")
@RendererItemContainer("userDc")
public class UserFragment extends FragmentRenderer<FormLayout, User> {
}

@RendererItemContainer 注解用于指定包含渲染实体的数据容器。

参考 GitHub issue #3699

异步任务

新的 UiAsyncTasks Bean 可以使用当前用户的安全上下文在单独的线程中执行操作,然后使用该操作的结果更新 UI。

后台任务 相比,这是一个基于 CompletableFuture 的轻量级方案。

文本字段的空白裁剪

textFieldtextArea 组件新添加了一个 trimEnabled 属性,该属性控制组件是否删除字符串开头和结尾的空格。

jmix.ui.component.default-trim-enabled 应用程序属性可以设置整个应用中该属性的默认值。在新项目中,此属性为 true。Studio 迁移程序会将已有项目的该属性设置为 false,避免行为更改。

切换主题样式

新的 ThemeUtils 类中的方法可以在运行时切换主题样式。可以很容易实现应用程序的浅色和深色主题切换。

请参阅 运行时更改主题 部分中的示例。

必填字段的验证

新的 jmix.ui.component.immediate-required-validation-enabled 应用程序属性可以在视图打开时禁用必填字段的验证。

表格导出选项

使用 表格导出操作 扩展组件时,导出选项现在可以由导出操作的 setAvailableExportModes() 方法或 XML 中对应的 availableExportModes 属性定义。默认导出选项由 jmix.gridexport.default-export-modes 应用程序属性定义。

使用浏览器的时区

如果没有明确为用户设置时区,则可以在登录时从浏览器获取。该配置可以用 HasTimeZone 接口的 isAutoTimeZone() 方法控制,在创建项目时,User 实体就实现了这个方法。

在已有项目中,行为维持不变,因为该方法默认返回 '`false`。在新项目中,User 实体的脚手架代码中实现了 isAutoTimeZone() 返回 true

端点安全高级配置

在使用 Authorization Server 或 OpenID Connect 扩展组件时,有更多的选项可以配置端点安全性:

  • jmix.resource-server.authenticated-url-patternsjmix.resource-server.anonymous-url-patterns 应用程序属性

  • AuthenticatedUrlPatternsProviderAnonymousUrlPatternsProvider

  • AuthenticatedRequestMatcherProviderAnonymousRequestMatcherProvider

参阅 基于 Token 的认证 了解详情。

原来的 AuthorizedUrlsProvider 已废弃,但仍然可用,类似的还有 jmix.rest.authenticated-url-patternsjmix.rest.anonymous-url-patterns 应用程序属性。建议将配置迁移到新的接口或属性。

搜索改进

新的 @ExtendedSearch 注解可以添加到索引定义的接口,以提供 "Starts with(以…​开头)" 搜索功能。添加之后,搜索扩展组件为每个 “真实的” 字段创建额外的 “虚拟” 子字段,以存储前缀。

searchField 组件现在支持用户打开 Search settings 窗口,以设置搜索策略、结果数量,以及(可选)一组作为搜索目标的实体。如果项目中存在带有 @ExtendedSearch 的索引定义,则策略列表会包含 “Starts with”。

allTermsAnyFieldallTermsSingleField 策略已被弃用。

REST API 改进

通用 REST API 现在支持通过 /entities 端点对 DTO 实体执行 CRUD 操作。提供给 entities/:entityName/search 端点的搜索条件将转换为 Condition 树并传递给 DataManager。这样一来,便可以请求通过 REST 数据存储 加载的 REST DTO 实体。

JSON 搜索条件现在可以在属性值中包含对象,例如:

{
  "conditions": [
    {
      "property": "field1",
      "operator": "=",
      "value": {
        "_entityName": "Customer",
        "id": "00000000-0000-0000-0000-000000000001",
        "firstName": "John",
        "lastName": "Doe"
      }
    }
  ]
}

Studio 组件检查器

Jmix UI 组件检查器的属性面板现在按类别对属性进行分组:GeneralData BindingSizePositionLook & FeelOther。这项新功能可让让开发者快速找到所需的属性。

属性分类仅显示在基于 Jmix 2.4+ 的项目中。

此外,组件检查器现在为 icon 属性提供了更好的支持。可以单击值字段中的 “铅笔” 按钮,显示一个包含可用图标列表的对话框,并从中选择一个图标。

Studio 支持 OpenAPI

Jmix Studio 现在为基于 OpenAPI 的集成提供高级支持。新功能包括在项目中配置 OpenAPI 客户端生成器,以及自动生成 DTO 实体、mapper 和中间服务,因而集成外部 REST API 更加容易。

有关如何使用这些功能的实际示例和说明,请参阅 Integrating Applications Using OpenAPI 指南。

Monorepo 的组合项目

我们为计划使用 monorepo 托管代码的组合项目添加了一个新模板。项目结构更加简洁,所有子项目都位于根项目内:

composite-project/
    subproject1/
        src/
        build.gradle
        settings.gradle
    subproject2/
        src/
        build.gradle
        settings.gradle
    build.gradle
    settings.gradle
    README.md

如果不不需要使用单独的仓库存储子项目,则推荐使用这种项目结构。

废弃 AcceptsTenant 接口

当使用 多租户 扩展组件时,User 实体不再需要实现 io.jmix.multitenancy.core.AcceptsTenant 接口。只需在租户字段上带有 @TenantId 注解就足够了。

AcceptsTenant 接口已弃用,并会在将来的主版本中删除。

破坏性改动

EnableJmixDataRepositories 的构建错误

当在主应用程序类使用 @EnableJmixDataRepositories 注解,且继承 AppShellConfigurator 时,项目重新构建时会发生以下的错误:

> Task :vaadinPrepareFrontend FAILED
Could not read com.vaadin.flow.theme.Theme annotation from class com.company.onboarding.OnboardingApplication.
java.lang.TypeNotPresentException: Type [unknown] not present

该问题是由 vaadin/flow#19616 引起的,会在将来的补丁中修复。

如需现在解决此问题,请将 @EnableJmixDataRepositories 注解移动到同一包中单独的 @Configuration 类上,示例:

package com.company.onboarding;

import io.jmix.core.repository.EnableJmixDataRepositories;
import org.springframework.context.annotation.Configuration;

@EnableJmixDataRepositories
@Configuration
public class OnboardingConfiguration {
}

保护通用 REST 端点

由于端点安全配置方面的改进(参阅 上面内容),必须设置下面的应用程序属性以保护通用 REST API 端点:

jmix.resource-server.authenticated-url-patterns = /rest/**

Studio 的迁移程序会自动在 application.properties 添加该配置。

通用 REST 未认证错误

以前,如果请求受保护的端点时没有带 Authorization 请求头,则通用 REST API 会返回 HTTP 500。现在能正确返回 HTTP 401。

ListMenu 样式

listMenu 菜单列表 组件更改了样式以解决焦点环的问题:

  • 修改了 ListMenu 本身的 margin 和 padding。

  • 为子菜单加大了 margin-inline-start

  • 修改了 MenuBarItem 的 padding。

如果你有该组件的自定义样式,可能需要做一些调整。

参考 GitHub issue #3589

输入对话框的日期参数

输入对话框 builder 的 dateTimeParameter()dateParameter()timeParameter() 方法的问题已经修复:现在可以分别创建 java.util.Datejava.sql.Datejava.sql.Time 类型的参数。之前创建的是 LocalDateTimeLocalDateLocalTime 类型。

参考 GitHub issue #3499

Studio 迁移程序会自动替换这些方法的调用为 localDateTimeParameter()localDateParameter()localTimeParameter() 以保证返回值的兼容性。

表格导出操作的依赖

以前,数据工具 扩展组件包含对 表格导出操作 扩展组件的传递依赖。现在这个依赖关系已删除,因此只有在明确包含表格导出操作扩展组件时,才能使用导出操作。

如果项目包含 Data Tools 扩展组件,Studio 迁移程序会自动添加表格导出操作扩展组件。

MariaDB 的 changelog

Spring Boot 3.3 依赖 Liquibase 4.27,这个版本将 UUID 类型的列属性从 char(36) 改为了 uuid。各个改动目前在 Jmix 中不兼容 MySQL/MariaDB 数据库,会引起 UUID 值转换错误。

如果你的项目使用 MariaDB,需要在项目中添加以下依赖把 Liquibase 降级:

implementation 'org.liquibase:liquibase-core:4.25.0!!'

参考 GitHub issue #3888

变更日志