部署

本章节包含关于 Jmix 应用程序部署的相关内容。我们介绍一些部署的基本原则和具体场景。

典型的 Jmix 部署配置由下列组件组成:

  • 应用程序本身

  • 一个关系型数据库

  • 反向代理(可选)

与任何 Spring Boot 应用程序一样,Jmix 应用程序可以通过可执行 JAR、WAR 或 Docker 镜像部署。

所有控制台命令都在应用程序根目录执行。

创建可执行 JAR

在 Jmix Studio 中,打开 Gradle 工具窗口并双击 Tasks → build → bootJar

在命令行,执行以下命令:

./gradlew bootJar

可执行 JAR 的名称由项目名称和版本组成。例如,如果在 settings.gradle 中设置以下内容:

rootProject.name = 'myapp'

然后在 build.gradle 中:

group = 'com.company'
version = '0.0.1-SNAPSHOT'

JAR 名称将会是 myapp-0.0.1-SNAPSHOT.jar

可执行 JAR 文件创建在 /build/libs 文件夹中。可以将其复制到任何地方并按如下方式运行:

java -jar myapp-0.0.1-SNAPSHOT.jar

如需自定义打包过程或创建可部署的 WAR 文件,请参阅 Spring Boot 文档

创建 Docker 镜像

在 Jmix Studio 中,打开 Gradle 工具窗口并双击 Tasks → build → bootBuildImage 任务。

在命令行,执行以下命令:

./gradlew bootBuildImage

默认情况下,镜像的名称为项目名,镜像的标签为项目版本。

例如,如果在 settings.gradle 中设置以下内容:

rootProject.name = 'myapp'

然后在 build.gradle 中:

group = 'com.company'
version = '0.0.1-SNAPSHOT'

创建的镜像为:myapp:0.0.1-SNAPSHOT

更多关于生成镜像和自定义的内容请参阅 Spring Boot 文档

创建 WAR

如果要构建 WAR 文件部署至应用程序服务,请执行以下步骤:

  1. 确保主应用程序类继承 SpringBootServletInitializer,示例:

    @SpringBootApplication
    public class MyApplication extends SpringBootServletInitializer {
        // ...
    }
  2. build.gradle 文件中,在 plugins 添加 war 插件:

    plugins {
        // ...
        id 'war'
    }
  3. 重新加载 Gradle 项目,通过单击编辑器窗口右侧弹出窗口中的 Load Gradle Changes 按钮或单击 Gradle 工具窗口中的 Reload All Gradle Projects

  4. 打开 Gradle 工具窗口,双击 Tasks → build → bootWar,或使用以下命令:

    ./gradlew bootWar

WAR 文件创建在 /build/libs 文件夹中。文件名按照 前一节 中的描述生成。

Jmix 应用程序无法在 Tomcat 10 中运行,因为它不支持 Java EE 8(javax.* 命名空间),而是需要 Jakarta EE 9(jakarta.*),详情参阅 Tomcat 文档。因此,请使用最新的 Tomcat 9 部署 Jmix WAR。

使用 JNDI 数据源

将应用程序部署为 WAR 时,可以使用应用程序服务提供的 JNDI 数据源将连接设置交于外部管理。

下面示例展示如何使用 Spring 的 profiles 功能配置应用程序的开发环境和生产环境的主 DataSource

  1. 在你的主应用程序类中,将 @Profile("!prod") 注解添加到 dataSourcePropertiesdataSource 方法上,以确保这些 bean 仅在开发环境中创建:

    @Profile("!prod")
    @Bean
    @Primary
    @ConfigurationProperties("main.datasource")
    DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }
    
    @Profile("!prod")
    @Bean
    @Primary
    @ConfigurationProperties("main.datasource.hikari")
    DataSource dataSource(DataSourceProperties dataSourceProperties) {
        return dataSourceProperties.initializeDataSourceBuilder().build();
    }
  2. 添加创建生产环境 DataSource bean 的方法:

    @Profile("prod")
    @Bean(name = "dataSource")
    @Primary
    DataSource prodDataSource(ApplicationContext context) {
        JndiDataSourceLookup lookup = new JndiDataSourceLookup();
        DataSource dataSource = lookup.getDataSource("java:comp/env/jdbc/demo"); (1)
    
        // to avoid org.springframework.jmx.export.UnableToRegisterMBeanException:
        for (MBeanExporter mbeanExporter : context.getBeansOfType(MBeanExporter.class).values()) {
            if (JmxUtils.isMBean(((Object) dataSource).getClass())) {
                mbeanExporter.addExcludedBean("dataSource");
            }
        }
    
        return dataSource;
    }
    1 数据源的 JNDI 名称,由应用程序服务提供。
  3. 当运行应用程序服务器时,在 spring.profiles.active 应用程序属性中将启用的配置文件设置为 prod

下面是在 Tomcat 9 中部署 demo.war 应用程序并做配置的示例。

  1. 复制 demo.wartomcat/webapps 文件夹。

  2. 创建 tomcat/bin/setenv.sh 文件,包含以下内容:

    CATALINA_OPTS="-Dspring.profiles.active=prod"
  3. 创建 tomcat/conf/Catalina/localhost/demo.xml 文件,定义数据源并设置数据库连接参数:

    <Context>
        <Resource type="javax.sql.DataSource"
                  name="jdbc/demo"
                  driverClassName="org.postgresql.Driver"
                  url="jdbc:postgresql://localhost/demo"
                  username="root"
                  password="root"
                  maxIdle="2"
                  maxTotal="20"
                  maxWaitMillis="5000"
        />
    </Context>

    注意,Resource 元素的 name 属性定义 JNDI 名称,在创建 DataSource bean 时通过 JndiDataSourceLookup.getDataSource() 使用。

  4. 将合适的 JDBC 驱动程序文件(例如,postgresql-42.2.9.jar)复制到 tomcat/lib

启动 Tomcat 时,应用程序将使用 tomcat/conf/Catalina/localhost/demo.xml 文件中定义的数据源。