# 1.19.冰刀：部署

> 冰缩寒流，川凝冻霭，前回鹭渚冬晚。燕阁红炉，驼峰翠釜，曾忆花柔酒软。――刘天游《氐州第一》

* 项目地址：<https://github.com/silentbalanceyh/vertx-zero-example/>

    本篇为实战总结帖，主要用于多个项目同时运行时的统一文档，目前Zero上已经运行了几个比较重量级的项目，本文主要针对几个平台从环境搭建、开发、运行、测试到部署进行基于实战的讲解，以Step-By-Step的方式让开发人员能更加流畅搭建Zero的企业实战开发环境。本文内容和原始教程中的内容略微有些出入，是因为引用了更多Zero Extension中的模块来辅助开发，所以此文算是Zero Core和Zero Extension的交叉参考教程。

## 「壹」开发环境

### 1.1. 环境介绍

#### 1.1.1. 基础环境

    最新的依赖库版本如下：

| 依赖库           | 类型       | 版本       |
| ------------- | -------- | -------- |
| NodeJs        | 前端       | 16.14.0  |
| Yarn          | 前端       | 1.22.17  |
| Ant Design    | 前端       | 3.26.19  |
| React         | 前端       | 16.14.0  |
| JDK           | 后端       | 11       |
| Maven         | 后端       | 3.8.5    |
| Zero          | 后端       | 0.8.1 \~ |
| Vertx         | 后端       | 4.2.6    |
| ElasticSearch | 集成（全文检索） | 7.x \~   |
| Neo4j         | 集成（拓扑图）  | 4.x \~   |
| Camunda       | 集成（工作流）  | 7.x \~   |
| MySQL         | 数据库      | 5.x      |
| Oracle        | 数据库      | 12.x     |
| TiDB          | 数据库      | 5.x      |

#### 1.1.2. 特殊说明

**基础环境部分**

* JDK的版本推荐使用ZuLu的开源JDK：<https://www.azul.com/downloads/>
* Maven推荐使用mvnd工具：<https://github.com/apache/maven-mvnd/releases>
* Maven的仓库推荐使用中心仓库，以防止部分jar包无法从代理仓库下载。

**可选扩展部分**

* 如果使用了**动态建模** （zero-atom）功能，则需要根据您的数据库下载相关依赖库：<https://github.com/silentbalanceyh/vertx-zero/tree/master/vertx-pin/zero-vista> ，若是其他类型数据库需参考内置源代码自己写一套基础插件。
* 集成部分的ElasticSearch、Neo4j、Camunda、Redis根据您自身项目情况而定。
* **动态建模**/**动态路由**功能根据您自身项目情况而定。
* Zero的基础版本是支持微服务和K8S（Istio）的，而此功能受限于目前项目，处于**实验性版本**阶段，需启用`vertx-istio`项目。

#### 1.1.3. 脚手架数据

    本教程**假设**您的基本环境如下：

| 实体          | 必须/可选 | 类型    | 含义                             |
| ----------- | ----- | ----- | ------------------------------ |
| Maven仓库     | x     | 依赖库目录 | \~/.m2/repository              |
| 本地开发        | x     | 工作目录  | \~/runtime/develop             |
| 生产存储        | 可选    | 工作目录  | \~/runtime/zero-store/（文档管理专用） |
| 生产部署        | x     | 工作目录  | \~/server（前后端一致）               |
| `DB_UP`     | x     | 数据表   | 数据库中的主库                        |
| `DB_UP_WF`  | 可选    | 数据表   | 数据库中工作流专用库（Camunda库）           |
| `DB_UP_HIS` | 可选    | 数据表   | 数据库中的删除历史库                     |
| `DB_XX`     | 可选    | 数据表   | 动态建模专用库                        |

    **注**：可选部分根据您搭建环境过程中选择的zero extension模块进行相关定义，最新版的模块化会自动化部署相关模块已经环境内容，详细部分参考后续章节，从`0.8.1` 的版本开始，zero extension扩展模块引入了**OOB——Out Of Box**开箱即用的配置数据，若您启用了OOB功能，即使您的系统内没有任何内容，这些配置数据都会跟随本教程的发布流程进入到您的主库中。

#### 1.1.4. 默认登录

* 默认账号：falcon（开发者）
* 默认密码：11111111

***

### 1.2. zero主框架

    如果您不关注最新版的功能，直接使用`0.8.1`版本，则可**跳过该步骤**，由于zero本身是一个跟着项目成长很迅速的项目，所以在`1.0` 版本发布之前，个人推荐紧跟最新版本走。虽然最新版本是`X-SNAPSHOT`，基础功能已经经过了生产环境验证，所以该版本是可靠的；再者，最新版本会包含一部分重用性极高的新功能，如`0.9.0-SNAPSHOT`中引入的：

* 文档管理平台（FTP、SSH）
* 模块化管理平台（License、Modulat）
* 工作流标准化平台（ITSM、ISO）
* WebSocket功能（正在开发中，用于提醒）
* 短信邮件集成

    zero框架导入的**操作步骤**如下：

1. 进入目录`~/runtime/develop/`中，下载`vertx-zero`代码到环境中：

   ```shell
   # 由于是只读类型，所以可不带access_token的模式拉取开源代码
   ~/runtime/develop >> git clone https://github.com/silentbalanceyh/vertx-zero.git
   # 命令执行后的输出如下
   Cloning into 'vertx-zero'...
   remote: Enumerating objects: 62003, done.
   remote: Counting objects: 100% (17224/17224), done.
   remote: Compressing objects: 100% (6252/6252), done.
   remote: Total 62003 (delta 8657), reused 16131 (delta 8157), pack-reused 44779
   Receiving objects: 100% (62003/62003), 87.48 MiB | 15.39 MiB/s, done.
   Resolving deltas: 100% (35166/35166), done.
   Updating files: 100% (4850/4850), done.
   ```
2. 下载完成后`~/runtime/develop`中会有一个`vertx-zero`目录，使用IDEA导入该目录中的项目：
   * 2.1. 启动IDEA

     ![](/files/ZtfsXBxg9bLW9QrPGyqM)
   * 2.2. 选中下载的`vertx-zero`目录中的`pom.xml`文件（自动导入成Maven类型的项目）

     ![](/files/Si9PFPhTSYEnT7n3IASK)
   * 2.3. 在弹出的对话框中选择`Open as Project`（以项目方式打开）

     ![](/files/sRc3hYVoEP6FVR9yWQuO)
   * 2.4. 如果弹出下边对话框，直接勾选`Trust projects in ~/runtime/develop`，然后点击`Trust Project`

     ![](/files/GcHVenK1reiRuBmNiNN1)
   * 2.5. 等待右下角的项目初始化完成

     ![](/files/n61bdh3lt5IbPHAam8wm)
   * 2.6. 若您点开进度条会看到正在执行的后台任务，请等待后台任务全部完成后再执行下一步

     ![](/files/ic0lLzSF3lqulzHIcySM)
   * 2.7. 项目初始化过程中，系统会下载部分所需的Maven依赖包，您的Maven库中会开始有内容 （**注：如果之前您的Maven目录中已存在相关库，则可忽略，Demo从空Maven库开始初始化以方便初学者理解。**）： ![](/files/QrTjiDVAjFyZrp5gYlDt)
3. 导入完成后，检查IDE中的JDK运行环境是否符合：**File -> Project Structure...**，推荐**11**。

   ![](/files/QeEuM5FOInc3EKI6kfpI)

   > 此处注意Language level（语言级别），从`zero`的`0.7.x`版本开始，框架引入了`Camunda`工作流引擎，该引擎最新版本最低要求支持JDK11，基于这一点出发，`zero`也将JDK从8升级到了11，所以从该版本开始所有的Java环境以11为准。
4. 打开Terminal终端，使用内置脚本（**mvnd环境**）编译`vertx-zero`：

   ![](/files/b2ueLVHEOY1MECWDEmgF)

   ```shell
   # zero中内置脚本主要用于快速编译以及增量编译框架，其中内容如下：
   # 1）完整编译（常用）                -- zero-compile.sh
   # 2）增量编译                       -- zero-compile-increase.sh
   # 3）「部分」编译核心框架             -- zero-compile-core.sh
   # 4）「部分」编译扩展框架             -- zero-compile-extension.sh
   # 5）「部分」编译插件                -- zero-compile-infix.sh
   # 
   ~/runtime/develop/vertx-zero(master) >> ./zero-compile.sh
   ......
   # 最终输出如下
   [INFO] ------------------------------------------------------------------------
   [INFO] BUILD SUCCESS
   [INFO] ------------------------------------------------------------------------
   [INFO] Total time:  45.021 s (Wall Clock)
   [INFO] Finished at: 2022-03-27T22:32:07+08:00
   [INFO] ------------------------------------------------------------------------
   ```

   zero-compile.sh内容如：

   ```shell
   mvnd clean package install -DskipTests=true -Dmaven.javadoc.skip=true -Dmaven.compile.fork=true -T 1C
   ```

    上述步骤的编译不会触发zero的测试流程，如果使用`mvnd clean package install` 方式处理，会触发zero的测试流程，使得整个框架编译的时间拉长，所以不推荐`clean package install`方式，这种方式仅留给zero的**研发人员** 使用。编译成功后，您的开发环境Maven库中就安装了最新的zero版本，目前是`0.9.0-SNAPSHOT`。

***

### 1.3. zero插件环境（可选）

    如果您在项目中使用了动态建模功能（启用`zero-atom` ），此步骤是必须的，动态建模为高级功能，只有在引入主框架的场景下可使用，直接从中心仓库下载的依赖库中并不包含动态建模部分，此功能目前依然处于研发阶段，只有最新版可支持。

    **操作步骤**如：

1. 执行Oracle依赖库的安装脚本（动态建模**编译必须**，运行可根据您的项目情况而定）

   ```shell
   # 进入 infix-oracle 项目目录
   ~/runtime/develop/vertx-zero(master) » cd vertx-pin/zero-vista/infix-oracle
   # 进入 Maven 本地安装目录
   ~/runtime/develop/vertx-zero/vertx-pin/zero-vista/infix-oracle(master) » cd maven
   # 执行安装脚本
   ~/runtime/develop/vertx-zero/vertx-pin/zero-vista/infix-oracle/maven(master) » ./install-oracle-jar.sh
   # 脚本内容如下
   # mvn install:install-file \
   #     -Dfile=ojdbc7-12.1.0.2.jar \
   #     -DgroupId=com.oracle \
   #     -DartifactId=ojdbc7 \
   #     -Dversion=12.1.0.2 
   #     -Dpackaging=jar
   ```

   `install-oracle-jar.sh`的内容如：

   ```shell
    mvn install:install-file \
        -Dfile=ojdbc7-12.1.0.2.jar \         
        -DgroupId=com.oracle \
        -DartifactId=ojdbc7 \
        -Dversion=12.1.0.2 
        -Dpackaging=jar
   ```
2. 在IDEA的Maven窗口中添加新项目：

   ![](/files/OaJtviuB7KQePHsCo7Ti)
3. 导入项目`vertx-zero/vertx-pin/zero-vista/`（选择pom.xml文件）

   ![](/files/n2ajy6A8amT9zV741I0F)
4. 导入项目后直接编译`zero-vista`：

   ```shell
   ~/runtime/develop/vertx-zero/vertx-pin/zero-vista(master) » mvn clean package install
   .....
   # 最终输出如下
   [INFO] ------------------------------------------------------------------------
   [INFO] Reactor Summary for 「vertx-vista」Scaffold Extension 0.9.0-SNAPSHOT:
   [INFO] 
   [INFO] 「vertx-vista」Scaffold Extension .................... SUCCESS [  1.693 s]
   [INFO] Scaffold Plugin: MySQL（infix-mysql） ................ SUCCESS [  6.121 s]
   [INFO] Scaffold Plugin: Oracle（infix-oracle） .............. SUCCESS [  3.783 s]
   [INFO] ------------------------------------------------------------------------
   [INFO] BUILD SUCCESS
   [INFO] ------------------------------------------------------------------------
   [INFO] Total time:  12.339 s
   [INFO] Finished at: 2022-03-28T05:46:15+08:00
   [INFO] ------------------------------------------------------------------------
   ```
5. 如此您就可以直接在项目中使用动态建模的SQL DDL插件了，使用时只需要在`pom.xml`中引入下边片段即可（根据您使用的数据库选择合适的插件）：

   ```xml
       <!-- MySQL -->
       <dependency>
           <groupId>cn.vertxup</groupId>
           <artifactId>infix-mysql</artifactId>
           <version>${zero.version}</version>
       </dependency>

       <!-- Oracle -->
       <dependency>
           <groupId>cn.vertxup</groupId>
           <artifactId>infix-oracle</artifactId>
           <version>${zero.version}</version>
       </dependency>
   ```

   > zero中的数据库支持以MySQL和TiDB为主，目前开放的支持的数据库种类基于项目需求。

***

### 1.4. GitHub安全设置

> 注：当您作为协作者Coordinator提交代码时必须此步骤！

    由于Github站点升级，当你作为Coordinator加入到项目开发时，新版本已不推荐使用**用户名/密码**方式拉取代码，而是需要在您的账号中生成个人的`access_token` ，拉取项目代码时使用该`access_token`拉取。

    其**操作步骤**如下：

1. 登录您的Github个人账号空间，右上角选择**Settings**菜单：

   ![](/files/gKmFETLl0NKBwq5DvMiy)
2. 选择左边菜单中最下边的**Developer Settings**：

   ![](/files/gXiabwZ1iJ6HtPgjO2Ib)
3. 选择左边菜单**Personal access tokens**，然后点击**Generate new token**按钮

   ![](/files/IkG6Tc9cS00bNVdrWj5V)
4. 勾选好您所需的权限后直接点击**Genarate token**按钮：

   ![](/files/WzSVy9bXhb20D3fCGAts)
5. 在结果页记录下您的个人token：

   ![](/files/N4LzrTYNlSeLRe7IwjUN)
6. 进入您的项目环境中，执行如下**操作步骤**进行库关联，先查看目前的远程库版本：

   ```shell
   ~/runtime/develop/vertx-zero(master) » git remote -v
   origin  https://github.com/silentbalanceyh/vertx-zero.git (fetch)
   origin  https://github.com/silentbalanceyh/vertx-zero.git (push)
   ```
7. 您的远程库名称为`origin`，执行如下命令：

   ```shell
   ~/runtime/develop/vertx-zero(master) » git remote set-url origin \
       https://<TOKEN>@github.com/silentbalanceyh/vertx-zero.git 
   ```

   注意上述命令格式，token的位置介于`https://`和`github.com`之间，并且以`@`结尾。
8. 再次查看您的远程库，库路径已发生改变：

   ![](/files/HE5hPNNrsA5HgCnohqg7)

    完成上述步骤之后，基本设置就完成了，当然在后续步骤中您可以直接使用`git clone https://<Token>@<Repo>`的方式拉取代码，**则 6 \~ 8 步骤可省略** ，即下边命令：

```shell
git clone https://<TOKEN>@github.com/silentbalanceyh/vertx-zero.git
```

***

### 1.5. 项目后端

    如果从头搭建zero脚手架，使用**新建**流程，若是导入已经搭建好的项目则使用**导入**流程。

#### 1.5.1. 新建

    新建项目可直接下载最新的脚手架版本：<https://github.com/silentbalanceyh/scaffold-zero>，然后根据自身项目修改如下内容：

* [x] （参考4.1）添加hosts映射记录（团队协作开发专用）
* [x] （参考4.2）修改Maven项目标识
* [x] （参考4.3）修改各个数据库名称、账号、口令
* [x] （参考4.4）修改容器端口号，跨域配置
* [x] （参考4.5）「**数据部分**」修改初始化登录账号
* [x] （参考4.6）「**数据部分**」修改租户、应用基本信息

    其中**数据部分**需修改Excel数据文件中的内容，这部分教程在配置章节讲解，上述修改部分参考本教程的**配置篇**来详细修改，一旦搭建好环境后就不用再变更，为一次性操作。

#### 1.5.2. 导入

    导入项目时如果作为Coordinator需更改项目内容，参考《**1.4.Github安全设置**》先配置个人token，导入的**操作步骤**执行如下：

> 为了区分标准脚手架和新项目，从`scaffold-zero`中下载的项目在此章节为`smave`名称，从新建到配置完成的部分参考后续各配置章节。

1. 从仓库下载代码（带token安全下载）：

   ```shell
   git clone https://<Token>@<Repo>
   # 截图中以项目名smave为例，但该项目在私库中，所以读者无法直接访问，读者可直接访问自己创建好的Github仓库
   ```

   ![](/files/vfnCWbf2IdRE5GF1LQpU)
2. 参考《**1.3.zero插件环境**》直接添加一个新的Maven项目到IDEA环境中，添加完成后效果如：

   ![](/files/gUBzqOVXtBx6mfO56a5L)

   **注：vertx-zero和smave共存于一个IDEA窗口中**。
3. 打开终端，执行根目录的编译脚本

   ```shell
   ~/runtime/develop/smave(master) » ./build.sh
   # build.sh                      （Linux专用）
   # build.bat                     （Windows专用）
   ```
4. 编译成功后可以看到如下截图（如此后端基本开发环境就搭建完成了）

   ![](/files/7BVsNMIR9ml21j9ivBfd)

#### 1.5.3. 初始化

    Zero脚手架的初始化流程**操作步骤**如下：

1. 为了团队协作开发，先在自己本地开发环境中追加如下hosts映射（**部署时另外配置**）：

   ```shell
   # Mac位置              /private/etc/hosts
   # Windows位置          C:/Windows/System32/drivers/etc/hosts
   127.0.0.1     ox.server.cn      # 容器专用
   127.0.0.1     ox.engine.cn      # 服务专用
   127.0.0.1     ox.integration.cn # 集成专用（可选）
   ```
2. 为您的应用创建MySQL数据库账号：

   ```shell
   ~/server$ mysql -u root -p                          # 输入root密码连接到MySQL中
   mysql > USE mysql;
   mysql > CREATE USER 'smave'@'%' IDENTIFIED BY '<PASSWORD>';
   mysql > GRANT all privileges ON *.* TO smave@'%' WITH GRANT OPTION;
   ```
3. 执行数据库建库脚本

   > 账号密码位于脚本 database-reinit.sh，请自行修改，按第二步创建的账号更改即可，推荐团队开发账号统一。

   ```shell
   ~/runtime/develop/smave/script/database(master) » ./database-reinit.sh
   [Zero] 重建数据库成功!
   ```

   重建完成后，可以看到**空库**（文中仅演示了最小配置，不带**工作流库、动态库、删除历史备份库**，其他库的配置参考后续配置章节处理）：

   ![](/files/rIpCtGBCJuZBcgOSgTG6)
4. 执行初始化脚本，zero中的初始化使用liquibase完成，直接运行如下脚本：

   ```shell
   ~/runtime/develop/smave/sv-driver/ix-smave(master*) » ./run-init.sh
   # 最终输出如下：
   [INFO] ------------------------------------------------------------------------
   [INFO] 
   [INFO] ------------------------------------------------------------------------
   [INFO] BUILD SUCCESS
   [INFO] ------------------------------------------------------------------------
   [INFO] Total time:  7.531 s
   [INFO] Finished at: 2022-03-28T10:20:04+08:00
   [INFO] ------------------------------------------------------------------------
   ```

   执行完初始化脚本后可以在数据库看到生成的表结构：

   ![](/files/Wk44Z4Iju2c9ooinKCkj)
5. 「**重要！**」执行下边命令备份最新表结构用于生产发布：

   ```shell
   mysqldump -u root -pxxxx -h localhost --databases DB_SMAVE > src/main/resources/init/initialize.sql
   ```
6. 表创建好过后，执行数据导入专用程序：`cn.vertxup.SvLoader`

   ![](/files/fefyxX0EP38kmQkLc0C1)
7. 「**重要！**」从此处开始，所有直接从IDEA中运行的主程序都必须配置好运行目录，否则无法以正确路径的方式加载数据，该步骤在生产环境中是不需要的，先点击`SvLoader`的运行配置：

   ![](/files/B4DzZA591ZZYbbhtaf1E)
8. 「**重要！**」点开运行配置后设置您的主程序的运行目录并保存该配置：

   ![](/files/ny0iZ1ILqAflx5vac4Eo)

   重要的事情说三遍：

   * 注意第二个红色框，这一步对开发人员十分重要！\*
   * 注意第二个红色框，这一步对开发人员十分重要！\*
   * 注意第二个红色框，这一步对开发人员十分重要！\*
9. 然后点击运行或调试运行执行数据初始化主程序

   ![](/files/jqtusuLtjAoki9QMQVJb)

   运行完成后可看到如下日志：

   ![](/files/ZYmUG4d8wIt8AJFTZ7uq)

    如此，数据初始化就完成了，这个`SvLoader`可以在您更改了任何`/init/oob`中的数据过后执行反复初始化操作，属于高频使用的主程序，而本小节的**初始化流程** 也会在开发过程中反复使用。

#### 1.5.3. 启动

    容器启动流程**操作步骤**如下：

1. 初始化完成后，直接运行主程序：`cn.vertxup.SvAgent`：

   ![](/files/Ib0CgZM72Xuqce4ovg2w)
2. 看到如下界面，后端zero容器就启动成功了：

   ![](/files/DJ9s60Kt7BsSnk01qaFz)

***

### 1.6. 项目前端

    如果是自己从头搭建zero-ui脚手架，则使用**新建**流程，若是导入已经搭建好的项目则使用**导入**流程。

#### 1.6.1. 新建

    新建zero-ui项目先安装zero的脚本工具：<https://www.vertxai.cn/>，安装好工具之后直接运行如下命令：

![](/files/NVSDratmACQmAJYWSYjX)

    新建项目后根据自身项目修改如下内容：

* [x] （参考4.7）项目名称
* [x] （参考4.7）远程集成配置
* [x] （参考4.7）风格配置
* [x] （参考4.8）应用配置，和后端结合

#### 1.6.2. 导入/启动

    前端导入使用WebStorm，**操作步骤**如下：

1. 从仓库下载代码（带token安全下载）：

   ```shell
   git clone https://<Token>@<Repo>
   # 截图中以项目名smave-ui为例，但该项目在私库中，所以读者无法直接访问，读者可直接访问自己创建好的Github仓库
   ```

   ![](/files/IogVfqnn94ej5oDeBSTJ)
2. 将代码导入WebStorm或其他前端工具IDE中：

   ![](/files/5XqZaN28FjQA5irYWuWx)
3. 选中您下载的项目打开

   ![](/files/CziBHSjTw7H0MjJjnz3B)
4. 弹出框中选择

   ![](/files/5uUFcosexB3YDQu12eWi)
5. 安装本地依赖库，基于`yarn`，一次性执行，生产部署之前也需执行

   ```shell
   ~/runtime/develop/smave-ui(master) » ./run-update.sh
   ```

   脚本内容如下

   ```shell
   #!/usr/bin/env bash
   ncu -u                              # package.json 检查更新
   node ./scripts/zrun-package.js      # 自动化版本管理（防止依赖）
   rm -rf yarn.lock                    # 删除缓存
   yarn install                        # 重新安装依赖
   ```

   上述脚本运行完成后可看到如下截图：

   ![](/files/WsC5NaC7EO5hfxekwKk3)
6. 运行启动脚本

   ```shell
   ~/runtime/develop/smave-ui(master*) » ./run-zero.sh
   # 由于引入了TypeScript，第一次启动会十分慢，启动过一次后如果依赖包不更改启动速度会很快
   ```

   最终运行后可看到如下截图

   ![](/files/ClWI9e4dkgMsJrM6hQU2)
7. 从浏览器中打开前端：[http://ox.server.cn:PORT/zo/login/index](https://github.com/silentbalanceyh/vertx-zero-example/blob/master/document/zero/http:/ox.server.cn:PORT/zo/login/index/README.md)，此处`PORT`是前端配置的端口号： 如果连接不上后端显示

   ![](/files/CFIKq4F5dKXNQwY2IofP) 如果连接上后端则显示

   ![](/files/BaWF13iCYLrnCqRHGdnz)
8. 使用`falcon/11111111`登录可进入主界面。

## 「贰」生产环境准备

* [x] Ubuntu Server
* [ ] Red Hat

***

### 2.1. JDK

#### 2.1.1. Open JDK

1. 直接使用Ubuntu工具安装JDK 11：

   ```shell
   sudo apt install openjdk-11-jdk
   ```

   执行过后会有如下截图

   ![](/files/wIaWrs8T9qVbkH9kj0iC)
2. 验证Java是否安装成功

   ```shell
   java -version
   ```

   ![](/files/PBolFWZSQIWIsM1sPib2)
3. 最终安装路径：`/usr/lib/jvm/java-11-openjdk-amd64`，后续设置`JAVA_HOME`。

#### 2.1.2. ZuLu JDK 11（推荐配置）

* 安装包下载：<https://cdn.azul.com/zulu/bin/zulu11.54.25-ca-jdk11.0.14.1-linux_amd64.deb>

1. 安装Azul APT仓库：

   ```shell
   # install the necessary dependencies
   sudo apt-get -q update
   sudo apt-get -yq install gnupg curl 

   # add Azul's public key
   sudo apt-key adv \
   --keyserver hkp://keyserver.ubuntu.com:80 \
   --recv-keys 0xB1998361219BD9C9

   # download and install the package that adds 
   # the Azul APT repository to the list of sources 
   curl -O https://cdn.azul.com/zulu/bin/zulu-repo_1.0.0-3_all.deb

   # install the package
   sudo apt-get install ./zulu-repo_1.0.0-3_all.deb

   # update the package sources
   sudo apt-get update
   ```

   执行包安装的截图如下：

   ![](/files/fm2DS6OWmcKGVpNjH3ug)
2. 执行命令安装Zulu JDK 11：

   ```shell
   # 标准安装
   sudo apt-get install zulu11-jdk
   ```
3. 本地安装Zulu JDK 11：

   ```shell
   # 下载 deb 安装包
   wget https://cdn.azul.com/zulu/bin/zulu11.54.25-ca-jdk11.0.14.1-linux_amd64.deb
   # 执行本地安装
   sudo apt-get install ./zulu11.54.25-ca-jdk11.0.14.1-linux_amd64.deb
   ```

   安装截图如：

   ![](/files/lJ9W3Ve3W8mdFei2LidJ)
4. 检查Java版本

   ```shell
   java -version
   ```

   ![](/files/b89lTCE6TInNwZNKuSCS)
5. 最终安装地址：`/usr/lib/jvm/zulu-11-amd64`，后续设置`JAVA_HOME`。

***

### 2.2. Git

1. 直接使用Ubuntu工具安装Git：

   ```shell
   sudo apt install git
   ```
2. 验证Git是否安装完成

   ```shell
   git --version
   ```

   ![](/files/NCAlCahizLJdvPzO1ZpN)

***

### 2.3. Mvnd

* 下载地址：<https://github.com/apache/maven-mvnd/releases/download/0.7.1/mvnd-0.7.1-linux-amd64.zip>

1. 下载安装包：

   ```shell
   wget https://github.com/apache/maven-mvnd/releases/download/0.7.1/mvnd-0.7.1-linux-amd64.zip
   ```

   执行截图

   ![](/files/J7lnCi0eVKF7LchcQEGi)
2. 对安装包执行解压：

   ```shell
   unzip mvnd-0.7.1-linux-amd64.zip
   ```
3. 重命名目录

   ```shell
   mvn mvnd-0.7.1-linux-amd64.zip mvnd
   ```

   ![](/files/IgVzbyltOg3NFA3pjWY1)

***

### 2.4. 环境变量

> 该章节为2.2、2.3的补充章节。

* Java环境变量
* Mvnd环境变量

1. 执行下边命令打开环境变量文件：

   ```shell
   sudo vim /etc/profile
   ```
2. 追加如下片段（按`i`键编辑）：

   ```shell
   export JAVA_HOME=/usr/lib/jvm/zulu-11-amd64
   export MAVEN_HOME=/home/localadmin/software/mvnd
   export PATH=$PATH:$MAVEN_HOME/bin:$JAVA_HOME/bin
   ```

   截图参考

   ![](/files/iOGr4nlO9z0TfUN6YEQU)
3. 编辑完成后执行`Esc`，使用`wq`退出`vim`工具并保存，然后执行下边命令在当前会话中生效

   ```shell
   source /etc/profile
   ```
4. 检查Java和Mvnd
   * Java环境检查：`java -version`

     ![](/files/0rS20KgagsRhCNVBHxEQ)
   * Mvnd环境检查：`mvnd -v`

     ![](/files/5ozsLTeZ8Aqsfdzpe2Yy)

***

### 2.5. MySQL

1. 执行命令安装MySQL

   ```shell
   sudo apt install mysql-server
   ```

   ![](/files/VR7O3zrX7dZPDKPlHIkQ)
2. 验证安装好的服务

   ```shell
   sudo systemctl status mysql
   ```

   ![](/files/6daLS2YCJO13rpXVO2fP)
3. 新版本操作系统安装`5.7`（参考引用中教程先设置，然后执行此步骤的命令）：

   ```shell
   sudo apt install -f mysql-client=5.7* mysql-server=5.7*
   ```
4. 配置root密码

   ```shell
   sudo mysql_secure_installation
   ```
5. 配置mysql

   ```shell
   sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
   ```

   追加下边配置

   ```properties
   # Windows专用，MySQL大小写敏感
   lower_case_table_names=2 

   # 连接参数设置
   max_connections=2048
   wait_timeout=1814400
   ```

   **为了兼容Oracle数据库，zero对数据库的要求是大小写敏感的，且以大写为主，所有SQL关键字、数据库相关的内容都一律使用大写。**
6. 重启MySQL服务

   ```shell
   service mysql restart
   ```

   ![](/files/0CbheRox9YzFuAbM9v7W)
7. 验证MySQL服务和端口

   ```shell
   ps -ef|grep mysql
   netstat -an|grep 3306
   ```

   ![](/files/dZQX0AA51z0wi35C2OLT)
8. 连接MySQL

   ```shell
   mysql -u root -p
   ```

   ![](/files/ftlh77k5c9y3Cmhm099o)
9. 创建您的应用所需账号：

   ```shell
   ~/server$ mysql -u root -p # 连接到MySQL中
   mysql > USE mysql;
   mysql > CREATE USER 'smave'@'%' IDENTIFIED BY '<PASSWORD>';
   mysql > GRANT all privileges ON *.* TO smave@'%' WITH GRANT OPTION;
   ```

***

### 2.6. NodeJs

* 安装包下载：<https://nodejs.org/dist/v16.14.2/node-v16.14.2-linux-x64.tar.xz>

1. 下载NodeJs安装包：

   ```shell
   wget https://nodejs.org/dist/v16.14.2/node-v16.14.2-linux-x64.tar.xz
   ```

   ![](/files/h4RjqZxkcjXN9CEDioAG)
2. 解压

   ```shell
   tar -xvf ./node-v16.14.2-linux-x64.tar.xz
   ```
3. 重命名目录（为后续方便）：

   ```shell
   mv node-v16.14.2-linux-x64 nodejs
   ```
4. 环境变量配置

   ```shell
   sudo vim /etc/profile
   ```

   追加下边内容

   ```shell
   export NODE_HOME=/home/localadmin/software/nodejs
   export PATH=$NODE_HOME/bin:$PATH
   ```
5. 保存后执行下边命令让环境生效

   ```shell
   source /etc/profile
   ```
6. 验证环境：

   ```shell
   node -v
   ```

   ![](/files/4TPlvRTBnb4SAAjLQX3M)
7. 安装yarn，yarn在安装过程请使用全局模式安装`-g`参数。

   ```shell
   npm install -g yarn
   ```

***

### 2.7. Zero Ai安装

* Zero Ai是自研发的开发辅助工具
* （仅Linux环境）参考文档：<http://www.vertxai.cn>

1. 执行安装命令

   ```shell
   npm install -g vertx-ai
   ```
2. 检查安装结果：

   ```shell
   ai help
   ```

   ![](/files/5FApi79kNCvgr6kI3M5S)

***

### 2.8. Httpd

1. 执行命令安装服务器：

   ```shell
   sudo apt install apache2
   ```
2. 查看服务器运行状态

   ```shell
   sudo systemctl status apache2
   ```

   ![](/files/9jaalAqBemg41CxGXItU)
3. 修改端口和根目录
   * 进入默认配置目录`/etc/apache2/`

     ```shell
     # 进入配置目录
     cd /etc/apache2
     ```
   * 在文件`ports.conf`中修改内容

     ```shell
     sudo vim /etc/apache2/ports.conf
     ```

     追加下边配置

     ```shell
     NameVirtualHost *:6002
     Listen 6002
     ```

     ![](/files/OMJHjjTzbhkMBSwW3152)
   * 创建默认目录

     ```shell
     # 此处 xxx 是当前登录用户名
     mkdir -P /home/xxx/server
     # 权限必须是 755 以上
     chmod 755 /home/xxx/server
     ```
   * 修改默认配置

     ```shell
     cd sites-available/
     cp 000-default.conf 000-default.conf.bak        # 备份
     sudo vim 000-default.conf
     ```

     修改开始配置以及中间配置（注意此处目录不可使用`root`账号目录，否则）

     ```xml
     <VirtualHost *:6002>
     ....
         DocumentRoot: /home/xxx/server
     </VirtualHost>
     ```

     ![](/files/7x0JtM7R7rsfeEDaJbil)
   * 为防止403错误，需要在`/etc/apache2/apache2.conf`配置文件中追加

     ```xml
     <Directory /home/localadmin/server>
                 Options Indexes FollowSymLinks
                 AllowOverride All
                 Require all granted
     </Directory>
     ```

     此步骤是因为在配置过程中我们更改了apache2的默认目录，从`/var/www/html`修改到了`/home/localadmin/server`中，如果您没有更改默认目录则可忽略这一步。
   * 生产环境部署时，有时候会遇到刷新界面404的问题，该问题解决方案如下：

     ```shell
     # 先启用Linux中的 `mod_rewrite`
     sudo a2enmod rewrite
     ```

     在您的部署目录下追加`.htaccess`文件，该文件内容如下：

     ```xml
     <IfModule mod_rewrite.c>
             RewriteEngine On
             RewriteBase /
             RewriteRule ^index\.html$ - [L]
             RewriteCond %{REQUEST_FILENAME} !-f
             RewriteCond %{REQUEST_FILENAME} !-d
             RewriteRule . /index.html [L]
     </IfModule>
     ```
4. 最后重启apache2服务

   ```shell
   sudo systemctl restart apache2
   ```

## 「叄」部署应用

* **以 smave 为例，基本结构和在线的 scaffold-zero 一致**。

***

### 3.1. 后端部署

1. 在后端服务器中追加数据库配置，先添加hosts映射：

   ```shell
   127.0.0.1     ox.server.cn          # 前后端部署在同一台机器时前端使用该记录（开发也使用该记录）
   127.0.0.1     ox.engine.cn          # 数据库使用此映射记录
   127.0.0.1     ox.integration.cn     # 仅用于集成
   ```
2. （**本地打包忽略**）下载代码到生产环境

   ```shell
   git clone https://<TOKEN>@github.com/silentbalanceyh/smave
   ```
3. （**本地打包忽略**）执行下边命令编译打包：

   ```shell
   # vertx-zero，前文提到过
   ~/runtime/vertx-zero$ git pull
   ~/runtime/vertx-zero$ ./zero-compile.sh

   # smave，编译项目
   ~/runtime/smave$ git pull
   ~/runtime/smave$ ./build.sh
   ```
4. （**本地打包忽略**）查看编译结果

   ```shell
   ll sv-driver/ix-smave/target/
   ```

   ![](/files/Wa1ly2YTXSsbg1MwpgK0)
5. 本地编译后直接跳过 **2 \~ 4** 步骤，拷贝下边目录到容器启动目录

   ```shell
   # 创建运行目录
   mkdir ~/server
   # 将打包的内容拷贝到该目录中
   # - conf 文件夹         （配置文件位置）
   # - lib 依赖库          （jar位置）
   # - smave-app.jar       (启动程序)

   $ cp -rf \
   > runtime/smave/sv-driver/ix-smave/target/smave-app.jar \
   > runtime/smave/sv-driver/ix-smave/target/conf \
   > runtime/smave/sv-driver/ix-smave/target/lib \
   > server/
   ```

   ![](/files/UOwYnzpAoXccl6qmrwwj)
6. 查看`server`目录结构

   ```shell
   ll server
   ```

   ![](/files/JXB0a8X9QCCTMk63k9EN)
7. 在`server`目录中创建启动命令工具和容器启动的脚本
   * 程序更新脚本如下：

     ```shell
     #!/usr/bin/env bash
     rm -rf conf lib smave-app.jar
     cp -rf ../runtime/smave/sv-driver/ix-smave/target/smave-app.jar \
         ../runtime/smave/sv-driver/ix-smave/target/conf \
         ../runtime/smave/sv-driver/ix-smave/target/lib \
         .
     # 保存为 smave-update-whole.sh
     ```

     如果您更改了`conf`部分的配置，请在更新时注意先备份，更新过后再还原，如下截图：

     ![](/files/yIPLLptXivs2Z46FdpXV)
   * 表结构初始化脚本：

     ```shell
     #!/usr/bin/env bash
     mysql -u root -P 3306 -h 127.0.0.1 -p < conf/init/initialize.sql
     echo "[Zero] 数据库表初始化完成"
     ```
   * 命令行启动脚本如下：

     ```shell
     #!/usr/bin/env bash
     chmod +x smave-app.jar
     java -Djava.io.tmpdir=./tmp \
          -cp conf \
          -jar smave-app.jar config
     # 保存为 smave-console.sh
     ```
   * 容器启动脚本如：

     ```shell
     #!/usr/bin/env bash
     chmod +x smave-app.jar
     OX_OPTS="$OX_OPTS -server \
         -Xms8g -Xmx16g -XX:NewRatio=1 \
         -XX:SurvivorRatio=3 -XX:PermSize=256m \
         -XX:MaxPermSize=4g"
     # 后台运行
     nohup java $OX_OPTS -Djava.io.tmpdir=./tmp -cp conf -jar smave-app.jar start &
     # 保存为 smave-server.sh
     ```
8. 更改配置文件
   * 更改跨域配置：

     ```shell
     # 跨域配置更改
     vim conf/vertx-jooq.yml
     ```

     将最后一行内容更改为（**注意域名小写，浏览器会自动转。**）：

     ```yaml
     origin: "http://hpcs01"
     ```
   * 文件管理地址更改：

     ```shell
     # 文件存储目录变更
     vim conf/plugin/is/configuration.json
     ```

     将内容更改为：

     ```json
     {
         "storeRoot": "/home/localadmin/server/store"
     }
     ```

***

### 3.2. 数据初始化

    `database-reinit.sh`脚本在开发章节已经存在，此处不再重复，可以将该部分脚本拷贝到`~/server/script/`中。

1. （**第一次或表变更**）执行数据库初始化

   ```shell
   # 进入script/database目录去初始化
   cd script/database
   ./database-reinit.sql
   ```

   ![](/files/ozDJTmN7m0EKJpZxQZIF)
2. （**第一次或表变更**）执行建库操作，开发过程中已经导出了表结构的SQL，直接执行上边的建表的脚本

   ```shell
   # 直接执行
   ./smave-database.sh
   ```

   ![](/files/97Iz5FJUCLcHcX8aXA4H)
3. 启动命令行工具

   ```shell
   # 直接执行
   ./smave-console.sh
   ```

   ![](/files/lF7lbZKTKMGcYsFcBIxS)
4. 执行命令：`r`，`l`导入数据（Zero Ai命令）

   ```shell
   > r
   [ μηδέν ]执行命令："r", "（子系统）标准部署工具"
   [ μηδέν ] (runtime)------>>>> Sub System: （子系统）标准部署工具
   [ μηδέν ][ Production ] 请输入命令，使用 h 可查看帮助文档
   > l
   ......
   # 最终输出结果
   [ μηδέν ]您的元数据仓库已重置初始化完成！重置结果：true

   # 退出命令
   # - b：返回上一级菜单（退出子系统）
   # - q：退出整个命令行程序
   ```
5. 启动容器：

   ```shell
   # 执行启动命令
   ./smave-server.sh
   ~/server$ ./smave-server.sh
   ~/server$ nohup: appending output to 'nohup.out'
   ```
6. 启动容器后可从日志查看容器启动状态：

   ```shell
   cd ~/server/
   cat nohup.out
   ```

   最终输出如下：

   ![](/files/b5pHIdUCDPU88DCmxqzH)
7. 同时在`logs/`目录中可以看到日志清单：

   ```shell
   ll logs/2022-03-28/
   ```

   ![](/files/6YqlrRReREgLCjGJoTc2)

   * **zero-epic-fabric**目录中是核心框架日志
   * **zero-epic-extension**目录中是扩展框架日志
   * **zero-epic-fabric.log**是汇总后的日志
8. 在运行日志中确认两个配置以证明`conf`目录下的内容已生效

   ![](/files/21mA5vLtjyQLYjMue28m)
9. 执行下边命令可看到运行的java进程：

   ```shell
   # 查看运行进程
   ps auxg|grep smave-app.jar
   # 停止
   kill -9 <进程号>
   ```

***

### 3.3. 前端部署

1. 下载代码到前端服务器中

   ```shell
   cd ~/runtime/
   git clone http://<TOKEN>@github.com/silentbalanceyh/smave-ui.git
   # 下载前端代码到本机中
   ```

   ![](/files/Z26Za8I8sN6L2m8Ezkai)
2. 安装前端依赖库

   ```shell
   ~/runtime$ cd smave-ui
   ~/runtime/smave-ui$ yarn install
   # 等待前端依赖库安装结束（第一次速度很慢）
   ```

   ![](/files/JeTwxx76zaHinBUJO2Sa)
3. 由于生产环境的环境变量已经提前设置了，在`./env.production`文件中，所以安装好依赖库后，前端可直接打包

   ```shell
   # 打包消耗时间会挺长，主要原因是使用了TypeScript做部分数据结构的校验
   # 所以最好是在本地打包好了直接把 `build` 目录上传到
   ~/runtime/smave-ui$ yarn build
   ```

   ![](/files/hAiq1St3qzKIUlZMFgYP)
4. 最后将`build`中的所有内容拷贝到`~/server`中。

   ```shell
   cp -rf build/* ~/server
   ```
5. 使用浏览器打开，您就可以看到如下界面：

   ![](/files/0Tn10Hw8BNswn60jJCUj)

## 「肆」配置调整

***

### 4.1. hosts映射配置

    本章节主要解析几个常用的内置映射域名相关信息，需注意的是此处的域名只是为了团队协作开发，并不是真实存在的域名，zero系统中包含三个核心域名：

| 域名                | 含义          | 开发端映射 | 生产端映射 |
| ----------------- | ----------- | ----- | ----- |
| ox.engine.cn      | 访问数据库专用域名。  | Ok    | Ok    |
| ox.server.cn      | 访问后端容器专用域名。 | Ok    | x     |
| ox.integration.cn | 访问集成服务专用域名。 | Ok    | x     |

    这三个域名映射需要您添加到本地hosts映射中：

```shell
# Mac位置              /private/etc/hosts
# Windows位置          C:/Windows/System32/drivers/etc/hosts
127.0.0.1     ox.server.cn      # 容器域名
127.0.0.1     ox.engine.cn      # 服务域名
127.0.0.1     ox.integration.cn # 集成域名（可选）
```

    三个域名的使用结构图如下：

![](/files/qH05zPD9oT6XnzEN5OFL)

    **特殊说明**：

* 使用域名访问服务可以保证不同的开发人员直接通过调整本地域名映射访问外置服务，主要处理以下几种核心场景：
  * **开发数据库/测试数据库/生产数据库**在不改变代码的情况下自由切换。
  * 不同的集成服务在不改变代码的情况下自由切换。
  * 不同开发人员访问这些服务时在不改变代码的情况下自由切换。
* 一般在生产环境部署时，前端`zero ui`和后端`zero`只有在同一台服务器上运行时，不需要更改`ox.server.cn`的域名配置，通常部署时候我们会采用两台以上的机器分离部署，所以生产部署时会单独配置`ox.server.cn`。
* 一般在生产环境部署时，后端`zero`和所有的集成服务在同一台服务器上运行时，不需要更改`ox.integration.cn`的域名配置，但往往生产环境部署时这些集成服务和后端`zero`都是分离的，也会单独配置。
* 后端`zero`以及开发工具访问所有数据库时统一使用了`ox.engine.cn`的域名访问，除非生产环境部署时数据库和后端`zero`分离，否则不需要更改`ox.engine.cn`的域名配置。

#### 4.1.1. 服务域名

**4.1.1.1. 程序访问**

    数据库域名统一在`vertx-jooq.yml`中配置：

![](/files/PPxN8Ju5GP5ghTRUg2n9)

    在脚手架配置中您会看到下边几段配置代码（**省掉数据库连接参数**）：

```yaml
jooq:
  # 主库配置
  provider:
    driverClassName: "com.mysql.cj.jdbc.Driver"
    username: root
    password: "xxxx"
    instance: DB_UP
    hostname: "ox.engine.cn"
    jdbcUrl: "jdbc:mysql://ox.engine.cn:3306/DB_UP?...."
  # 历史数据库
  orbit:
    driverClassName: "com.mysql.cj.jdbc.Driver"
    username: root
    password: "xxxx"
    hostname: "ox.engine.cn"
    instance: DB_UP_HIS
    jdbcUrl: "jdbc:mysql://ox.engine.cn:3306/DB_UP_HIS?...."

# 工作流库
workflow:
  name: HOTEL-WORKFLOW-ENGINE
  builtIn:
  # 文件管理工作流
  - workflow/process.file.management/workflow.xlsx
  database:
    driverClassName: "com.mysql.cj.jdbc.Driver"
    username: root
    password: "xxxx"
    instance: DB_UP_WF
    hostname: "ox.engine.cn"
    jdbcUrl: "jdbc:mysql://ox.engine.cn:3306/DB_UP_WF?...."
```

**4.1.1.2. Liquibase访问**

    zero中使用使用liquibase执行数据库初始化，它的数据库配置位于文件：

![](/files/kPpDhC3rgTbVxwpKRNFB)

    该配置是一个属性文件，内容通常如：

```properties
url=jdbc:mysql://ox.engine.cn:3306/DB_QIANLI?....
driver=com.mysql.cj.jdbc.Driver
username=zero
password=xxxx
```

**4.1.1.3. Jooq代码生成访问**

    zero中的Jooq代码生成配置位于**领域模型**定义的项目中，它的数据库配置位于文件：

![](/files/eF6GP8v4x70xKy6Y62z8)

    该配置文件是一个XML文件，内容通常如：

```xml
    <jdbc>
        <driver>com.mysql.cj.jdbc.Driver</driver>
        <url>
            <![CDATA[ jdbc:mysql://ox.engine.cn:3306/DB_UP?..... ]]>
        </url>
        <username>root</username>
        <password>xxxx</password>
    </jdbc>
```

#### 4.1.2. 容器域名

**4.1.2.1. 跨域CORS**

    CORS跨域访问的域名一般位于`vertx-jooq.yml`配置文件的尾端，其片段如下：

```yaml
  origin: "http://ox.server.cn:6001"
```

**4.1.2.2. 前端Endpoint**

    当您的zero-ui前端访问后端zero容器时，前端的访问配置位于环境变量文件中：

![](/files/7C84PU1TZklnMgjNB0RF)

    环境变量文件主要有两个：

* .env.development：开发环境专用
* .env.production：生产环境专用

#### 4.1.3. 集成域名

    所有集成域名目前也位于`vertx-jooq.yml`配置文件中，只是在脚手架项目里被注释掉了，需要使用时直接打开即可：

```yaml
# ------------------- Redis专用 ----------------------
# redis:
    # host: ox.integration.cn
    # port: 6379
# ------------------- 历史备份专用 ----------------------
# 历史库专用
#trash:
#    keepDay: -1

# ------------------- 全文检索专用 ----------------------
# Es索引库
#elasticsearch:
#    hostname: ox.integration.cn
#    port: 9200
#    scheme: http
#    index: cmdb
#    username: elastic
#    password: zero

# ------------------- 拓扑图专用 ----------------------
# 图引擎库
#neo4j:
#    port: 7687
#    protocol: bolt
#    hostname: ox.integration.cn
#    username: neo4j
#    password: "zero"
```

    细心的读者已经发现，后端配置所有的域名的位置比较集中：

* 除开Jooq/Liquibase工具使用的域名需要单独配置，这两个工具主要是开发过程中使用，生产部署时不会使用，可理解成一次性配置，配置好过后不需要更改。
* 生产部署专用的域名配置全部位于`vertx-jooq.yml`文件中，这样设计的目的也是为了方便修改以及执行DevOps配置流程。

***

### 4.2. Maven项目标识

    本来这个章节是Maven的基础知识，应该是不需要教程就可以过的知识点，但为了照顾初学者，本小节可以帮助您从零开始搭建一个`scaffold-zero`的脚手架基础项目，在看章节步骤之前，先看看几个项目的作用：

| 项目                   | 类型  | 说明            |
| -------------------- | --- | ------------- |
| zo-core              | pom | 您项目模块核心层父项目。  |
| zo-core/zo-business  | jar | 您项目模块的业务逻辑层。  |
| zo-core/zo-domain    | jar | 您的项目模块的领域模型层。 |
| zo-driver            | pom | 您项目的启动器容器。    |
| zo-driver/ix-starter | jar | 您项目的启动器（主项目）。 |

    特殊说明：

1. **数据访问层**？整个项目结构中没有数据访问层是因为`zo-domain`中的**静态**领域模型是使用Jooq代码生成工具生成，生成过程中已经带有Dao层的代码，并且在编程过程中，借用zero提供的抽象数据层以及查询引擎，不需要使用任何多余代码就可以完成数据库的底层访问，所以丢弃了传统项目中的数据访问层。
2. **接口/控制层**？整个项目结构中也不存在控制层和接口部分，由于zero以及将上层逻辑全部压缩到一起了，这部分内容根据您项目的复杂度可以有所差异，您也可以自行扩展。
3. **多启动器**？`zo-driver`中可以包含一个以上的启动器，您可以书写不同种类的`main`函数作为程序入口，通常：
   * 开发过程中会使用双入口：`Loader/Agent`，一个负责数据导入，另外一个负责容器启动。
   * 生产部署过程中会使用单入口：`Entry`，该入口根据不同参数可打开**命令行工具**和**容器**，参考前文部署教程。

    Maven标识更改**操作步骤**如下（附带新建项目步骤）：

1. 删除下载下来的`scaffold-zero`中的`.git`目录，将代码推送到自己的代码仓库中。
2. 在IDEA中选中项目，点击右键：**Refactor -> Rename...**，下图中选择最后一个：**Rename module and directory**

   ![](/files/YrTtAdFk7tHIPr6FNM4L)
3. 在弹出框中输入您的主项目标识信息

   ![](/files/RrBhWuMJz15zEb79l7Tu)
4. 在所有子项目中重复**步骤 2 \~ 3**（合计五次）：

   ![](/files/X5SSrJEyCoJeHgqMu8uv)

   > 注：一般在IDEA做rename的时候，Maven的配置并不会随着IDEA发生更改。
5. 更改所有的POM文件：

   ![](/files/zS4rd0fbQMCLLtYJG58h)
6. POM文件在更改过程中需根据您自己的项目设置
   * 项目本身的三个核心属性：`groupId, artifactId, name`需酌情更改：

     ![](/files/lME4JSG7pC2pPREP86AL)
   * 父子结构调整，子项目中（除开从`vertx-import`继承的项目需调整继承部分：

     ![](/files/B4UPcSEg77J2s0sRheZr)
   * 父子结构调整，父项目中调整`module`部分

     ![](/files/LXC0ilDpZCbv1tozOCTi)
   * `name`的调整则是为IDE量身打造的，调整过后可以在Maven窗口中看到更改结果

     ![](/files/5lTivQ5hFCYV2oqurW8l)

     > 若窗口无变化点击截图中的刷新按钮看到该改变
7. 变更完成后，保证编译通过，直接运行根目录：`build.bat/build.sh`脚本，见到下边截图则您的Maven设置就完成了：

   ![](/files/edkiKgWYXxhCY0nO18KF)

***

### 4.3. 数据库

    4.1中已经说明，数据库配置部分主要在`vertx-jooq.yml`中，其中`Camunda, 历史库，主库`的配置结构基本一致，如下：

```yaml
jooq:
  provider:
    driverClassName: "com.mysql.cj.jdbc.Driver"
    username: root
    password: "xxxx"
    instance: DB_UP
    hostname: "ox.engine.cn"
    jdbcUrl: "jdbc:mysql://ox.engine.cn:3306/DB_UP?..."
  # 历史数据库，如果启用逻辑删除则需要使用该库
  orbit:
    driverClassName: "com.mysql.cj.jdbc.Driver"
    username: root
    password: "xxxx"
    hostname: "ox.engine.cn"
    instance: DB_UP_HIS
    jdbcUrl: "jdbc:mysql://ox.engine.cn:3306/DB_UP_HIS?..."

## 工作流配置
workflow:
  name: HOTEL-WORKFLOW-ENGINE
  builtIn:
  # 文件管理工作流
  - workflow/process.file.management/workflow.xlsx
  database:
    driverClassName: "com.mysql.cj.jdbc.Driver"
    username: root
    password: "xxxx"
    instance: DB_UP_WF
    hostname: "ox.engine.cn"
    jdbcUrl: "jdbc:mysql://ox.engine.cn:3306/DB_UP_WF?..."
```

    需要更改的属性表如下：

| 属性名             | 含义                    |
| --------------- | --------------------- |
| driverClassName | JDBC连接专用的数据库驱动类名      |
| instance        | 数据库名，和JDBC连接字符串同步修改   |
| hostname        | 默认使用`ox.engine.cn`    |
| username        | 数据库访问账号               |
| password        | 数据库访问口令/密码            |
| jdbcUrl         | JDBC连接字符串             |
| port            | 端口号，整数，不配置使用默认的 3306  |
| options         | JsonObject结构，额外的连接池配置 |
| category        | 数据库种类，默认值：MYSQL5      |

    特殊说明：

1. options配置的内容关联到连接池属性，系统默认使用了`HikariDataPool`连接池。
2. category目前系统中支持六种最基本的值
   * MYSQL5
   * MYSQL8
   * MYSQL（旧版专用）
   * ORACLE（旧版专用）
   * ORACLE11
   * ORACLE12
   * （保留）TIDB4
   * （保留）TIDB5
3. 默认的jdbcUrl中带的MySQL配置参数如下表格：

   > serverTimezone=Asia/Shanghai\&useUnicode=true\&characterEncoding=UTF-8\&autoReconnect=true\&failOverReadOnly=false\&useSSL=false

   | 属性名               | 默认值           | 含义                |
   | ----------------- | ------------- | ----------------- |
   | serverTimezone    | Asia/Shanghai | 数据库运行时区           |
   | useUnicode        | true          | 是否启用Unicode       |
   | characterEncoding | UTF-8         | 数据库使用的默认编码        |
   | autoReconnect     | true          | 是否自动重连            |
   | useSSL            | false         | 是否启用SSL           |
   | failOverReadOnly  | false         | 自动重连成功后，连接是否设置为只读 |

    数据库的`category`属性实际并不是数据库访问过程中必须的，最新的JDBC可以根据您提供的`driverClassName`以及`jdbcUrl`反向分析数据库类型，而此处的`category`主要设计如下：

1. 在执行Jooq持久化过程中为数据库提供更好的**Dialect**方言以适配不同数据库。
2. zero在对数据库执行DDL**动态建模/动态路由**实施过程中，可根据category执行特定的组件选择以处理不同种类数据库的兼容性问题。

    如果您启用了动态建模（zero-atom）功能，则额外的动态数据库会存储在您的`X_SOURCE`表中，表结构和配置一致，而前端开发中心您可以看到目前四个库的启用禁用情况，如下图只启用了主库，并且可以在该界面更改动态建模库的信息：

![](/files/SNzrAnMmYdCqzqWuItQ0)

***

### 4.4. 容器端口

    容器端口的配置主要分两部分：**后端端口和前端端口**。

1. 后端端口的配置如下图：

   ![](/files/QQE6donNPysFoyTkabV7)

   * 此处的`name`在微服务环境和云端环境作为节点部署时需要特别注意，单体应用（本教程中）中可根据自己的项目进行设置。
   * `host`设置成`0.0.0.0`其含义在于任意IP地址都可访问，不限制主机的运行IP。
   * 此处的`port`就是您需要配置的端口号，Scaffold的默认端口为**6000**，Zero框架中的默认端口为**6083**，此处为了做Demo改成了**6086**。
2. 前端端口的配置如下图：

   ![](/files/p3wuDxtXuZdkmCbzaMAY)

   前端端口号使用`NODE`的环境变量`PORT`进行指定，`.env.development`负责开发环境端口号，`.env.production`负责生产环境端口号。
3. 后端配置前端的跨域必须和浏览器中访问的地址一致，一般位于`vertx-jooq.yml`文件中，如：

   ```yaml
       # Cross Domain
       cors:
           credentials: true
           methods:
               - DELETE
               - GET
               - POST
               - PUT
               - OPTIONS
           headers:
               - Authorization
               - Accept
               - Content-Disposition
               - Content-Encoding
               - Content-Length
               - Content-Type
               - X-App-Id
               - X-App-Key
               - X-Sigma
               - X-Lang
               - X-Session-Id
           origin: "http://ox.server.cn:6001"
   ```

   其中`origin`的配置意味着您最终会在浏览器中输入`http://ox.server.cn:6001`来访问前端程序，而服务端只允许从这个路径的JS请求发生，这样就防止其他模式的脚本攻击，关于跨域更多信息可参考在线的跨域配置相关文档。
4. 前端跨域的基本环境变量配置如：

   ```properties
   # 访问后端的接口主地址
   Z_ENDPOINT=http://ox.server.cn:7000

   # 跨域模式的配置
   Z_CORS_MODE=cors
   Z_CORS_CREDENTIALS=include
   ```
5. 使用前后端分离配置的核心结构图如下：

   ![](/files/VwmyWzYqHt5KCz3JYAZQ)

   * 所以生产部署过程中，对外的两台服务器必须开放对应的端口，如图后端开放**7000**，前端开放**6002**。
   * 如果搭建了Nginx的反向代理则可跳过上述步骤。
   * CORS会拦截掉所有请求源非法的请求，这种情况请求本身不会进入到后端应用中。
   * 此处提到的请求主要是**JS脚本级**的请求，通常应用容器为**浏览器**，如果是直接使用程序发送请求方法除外。

***

### 4.5. 初始化登录账号

    zero脚手架中的初始化登录账号位于启动器中：

![](/files/cnO4zpzatZeXtggHTs2N)

    打开该Excel文件：

![](/files/uVmEvJrSO91yShBa3uqw)

    主要添加的记录有三张表：

| 表名            | 含义                                   |
| ------------- | ------------------------------------ |
| O\_USER       | OAuth认证模式的专用数据表，每个用户一条记录，包含了发放的唯一密钥。 |
| S\_USER       | 账号表，包括账号名、密码等。                       |
| R\_USER\_ROLE | 账号角色关联表，存储了角色和用户的关联信息。               |

    **特别说明**：

1. 密钥是一个64位的随机字符串，可使用Zero Ai命令生成：

   ```shell
   ai str -n <个数，默认1> -l <长度，默认64>
   ```

   ![](/files/DXhUtW4ckrowm7kBQrZL)
2. 主键一般是UUID格式，可直接使用Zero Ai命令生成：

   ```shell
   ai uuid -n <个数，默认20>
   ```

   ![](/files/HdQtXQfqoZs802B7OPU0)
3. 密码是MD5的加密格式，可直接使用Zero Ai命令生成（`0.3.20`版本之后）：

   ```shell
   ai md5 -i <输入字符串>
   ```

   ![](/files/78asbrWG1v60ijFRhfZ4)

    **如果是MacOs的系统，执行完命令之后可直接使用`Cmd + V`快捷键粘贴刚刚生成的字符串**。

4. 修改完成后，直接运行`Loader`程序（前文提到的数据加载程序），默认会加载`init/oob`中的所有Excel数据文件，可反复加载，加载完成后重新启动容器，则新的账号密码就会生效。

***

### 4.6. 租户应用信息

    租户信息在整个`zero`环境中以`sigma`为标识，带有租户的系统结构概念图如下：

![](/files/jtOCceIcH4ZdmUrlaEku)

    特殊说明：

* 如图所示，每一个彩色小方块表示一个独立的Docker容器，这个容器中可能包含独立数据库、存储、服务也可能多个小方块组合到一起使用，从应用层的数据去标识，每个小方块都拥有一个独立的`appId`和`appKey`。
  * `appId`用于读取基础应用数据
  * `appKey`用于读取敏感数据
* 每一种颜色则表示一个租户信息，拥有唯一的`sigma`值，最终从系统层可以看到，一个租户会有多个应用信息，而此处我们部署的前后端就充当了一个**彩色小方块**的Docker结构。

    租户信息的区分主要体现在部分信息的数据导入过程：

1. 如果您要启用Zero中提供的**命令行**，则需设置如下配置：

   ![](/files/Nl1416XS485m3QxkkYb0)

   runtime目录中的`configuration.json`是命令行专用配置，它的内容实际是引用租户文件：

   ```json
   {
       "stellar": "init/environment.json"
   }
   ```
2. 有了上述配置后，您就可以使用如下代码：

   ```java
   // 直接调用 Ok.ok() 可提取租户信息
   return Ok.ok().compose(okA -> {
           // 此处的 okA 表示租户方
           final JtApp app = okA.configApp();
           // 而此处的 okB 表示客户方（客户方即集成方）
           final OkB partyB = okA.partyB(appName);
   });
   ```
3. `init/environment.json`中的存储的数据就是租户的基本数据，格式如：

   ```json
   {
       "global": {
           "sigma": "xxxxxx",
           "appId": "xxxxxx",
           "appKey": "xxxxxx",
           "language": "cn",
           "active": true,
           "createdBy": "zero-environment",
           "scope": "vie.app.sv"
       },
       "application": {
           "name": "vie.app.ox"
       },
       "integration": {
           "customerB": {
               "name": "partyB",
               "config": "init/integration/partyB.json"
           }
       }
   }
   ```

   配置中有三个核心节点和租户信息相关，他们的用途分别为：

   * `global`：该节点提供了当前租户的基本全局信息，用于Excel数据导入过程中的默认值赋予，有了该设置后，Excel数据文件中的数据就不需任何和**应用、租户、语言**相关的信息，只包含业务数据，最终形成如下结构图：

     ![](/files/HyvNs0lMAdNtWIQiophR)

     即：**应用数据包 + environment.json = 租户数据包**。
   * `application`：PartyA专用配置数据，包括（应用数据`X_APP`，数据库配置`X_SOURCE`）等。
   * `integration`：PartyB专用配置数据，主要是集成数据，用于构造`Integration`类专用。

***

### 4.7. 前端配置

    本章节旧事重提，主要用于配置前端环境变量：

![](/files/WzYCHNd7Z0iHWiCXsHDZ)

#### 4.7.1. 项目名称

    项目的npm名称存储于`package.json`中，该名称会在`ai init`命令中直接设置：

```json
{
    "name": "smave-ui",
    "version": "0.1.0",
    "private": true,
}
```

#### 4.7.2. 远程集成配置

    集成配置环境变量如：

```properties
# 该应用使用的语言环境，X-Lang 传入值
Z_LANGUAGE=cn

# 远程容器RESTful访问端
Z_ENDPOINT=http://ox.server.cn:7000
```

#### 4.7.3. 风格配置

```properties
# 主色调处理，该色调会影响整个 Ant Design的主色调
Z_CSS_COLOR=#3457e2

# CSS自定义类名前缀
Z_CSS_PREFIX=zo

# 站点的字体设置：默认是 14px
Z_CSS_FONT=13px
```

#### 4.7.4. 开发配置

```properties
# 打开通用调试日志
Z_DEV_DEBUG=true

# 打开模拟数据专用日志（去后端独立运行前端专用设置）
Z_DEV_MOCK=true

# 打开远程请求专用配置监控请求响应信息
Z_DEV_AJAX=false

# 表单监控专用日志
Z_DEV_FORM=true

# 打开所见即所得的Monitor工具，使用键盘中的 home 拉出工具
Z_DEV_MONITOR=false
```

### 4.8. 应用配置

    应用配置在前端和后端必须对应上，前端依旧是环境变量部分：

```properties
# 应用名称，对应到 X_APP 中的 NAME 字段
Z_APP=vie.app.zo

# 应用的语言环境，和后端对应
Z_LANGUAGE=cn

# 入口信息，可对接后端的 UI_PAGE 实现动态界面渲染，目前只是用于静态的入口端
# 登录入口端
Z_ENTRY_LOGIN=/login/index
# 管理入口端
Z_ENTRY_ADMIN=/amdin/index
```

    后端配置位于下边文件中：

![](/files/it6S52t4zc2fedrrK7nR)

    表格中的数据如下

![](/files/N0cLrI2kDnMWy8jNWztG)

## 「伍」小结

    本章主要介绍了zero新脚手架的基本配置以及开发环境和生产环境的详细部署流程，根据教程中的内容开发人员可完成如下任务：

* 搭建项目的开发环境（从零起步以及直接导入）
* 部署项目到生产环境


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lang-yu.gitbook.io/zero/000.index/019.deployment.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
