关于后端:FoxnicWeb-代码生成-1-开始生成代码

31次阅读

共计 9202 个字符,预计需要花费 24 分钟才能阅读完成。

Foxnic-Web 代码生成 (1) —— 开始生成代码

基本原理

  应用 Foxnic-Web 以及 Foxnic-SQL 进行利用开发时,都能够反对代码生成。他们的区别是,基于 Foxnic-SQL 的疾速 main 函数启动的利用,只须要生成 Model 和 Service 即可。基于 Foxnic-Web 开发 Web 利用时,除了生成 Model 和 Service 以外,还要生成 Proxy、Controller、UI 界面等。

  Foxnic 的代码生成是基于数据表的,所以当表构造变更,甚至只是正文的调整,咱们也是倡议从新生成必要的代码。在 Foxnic 的体系中,咱们认为最后的表结构设计、ER 图设计,就是这个零碎设计的终点。后续的程序设计或数据结构设计都是表结构设计的连续。

  Foxnic 的代码生成体系心愿开发者能够有一个较高的开发终点,能够基于生成的代码间接开发利用,甚至是代码生成后无需批改就能够间接应用了。另一方面,咱们又不敞开二次开发的开放性,毕竟自在的批改代码才是软件系统能够按需定制的终极门路。这也是 Foxnic 体系没有走无代码或低代码平台的起因。

  本文中的示例代码均可在 https://gitee.com/LeeFJ/foxni… 我的项目中找到。

生成表构造元数据

  代码生成的第一步是生成表构造元数据。咱们晓得,数据表、列、索引等信息都存储在数据库内,咱们在 java 程序内无奈间接援用。但有些时候,咱们又须要用到这些货色,特地是表名、字段等。Foxnic-Web 在代码生成、以及其它业务逻辑编写时都有可能用到这些元数据。

  所以,咱们要通过一种形式将数据库元数据转换成 java 构造,这种构造是通过代码生成的。Java 生成的元数据它是动态的,不会随着变构造的扭转而扭转,Foxnic-Web 要求表构造变动后,须要从新生成元数据类。

  示例我的项目的 webfull 我的项目下的 WebFullDBMetaGenerator 类用于生成数据库元数据类:

package org.github.foxnic.web.generator.constants;

import com.github.foxnic.dao.spec.DAO;
import com.github.foxnic.generator.builder.constants.DBMetaClassFile;
import org.github.foxnic.web.generator.config.WebFullConfigs;

public class WebFullDBMetaGenerator {
    /**
    * 运行 main 函数生成代码
    * */
    public static void main(String[] args) throws Exception {WebFullDBMetaGenerator g = new WebFullDBMetaGenerator();
        g.buildDBMeta();}
    /**
    * 生成 DBMeta 数据
    * */
    private void buildDBMeta() {WebFullConfigs configs=new WebFullConfigs("webfull-service-example");
        DAO dao=configs.getDAO();
        DBMetaClassFile dbMetaBuilder=new DBMetaClassFile(dao,configs.getDomainProject(),configs.getProjectConfigs().getDomainConstantsPackage(),"WebFullTables");
        dbMetaBuilder.setTableFilter(table->{table=table.toLowerCase();
            // 仅生成以 example_ 结尾的表
            if(table.startsWith("webfull_")) return true;
            return false;
        });
        dbMetaBuilder.save(true);
    }
}

  执行 main 函数后,在 domain 模块内生成 WebFullTables 类,前面生成其它代码,咱们会用到这个类中数据库表构造定义的常量。

非 Web 环境的代码生成

  事实上,非 Web 环境的开发是很少的,然而咱们在解说 Foxnic-SQL 局部的时候,也用到了非 Web 环境的代码生成,大家参考 Foxnic-SQL 相干的文档即可。

  在 https://gitee.com/LeeFJ/foxni… 我的项目的 com/leefj/foxnic/sql/demo/generator 目录的 ExampleCodeGenerator.java 中有示例,大家看代码联合咱们的文档,很容易了解。前面的篇幅咱们着重介绍 Web 环境下的代码生成,所有 Web 环境下代码生成的原理一样实用于非 Web 环境。

  为了不便了解,咱们还是贴一下代码:

package com.leefj.foxnic.sql.demo.generator;

import com.github.foxnic.commons.project.maven.MavenProject;
import com.github.foxnic.dao.spec.DAO;
import com.github.foxnic.generator.builder.model.PoClassFile;
import com.github.foxnic.generator.config.ModuleContext;
import com.github.foxnic.sql.meta.DBTable;
import com.leefj.foxnic.sql.demo.app.domain.example.Address;
import com.leefj.foxnic.sql.demo.app.domain.example.Goods;
import com.leefj.foxnic.sql.demo.app.domain.example.Order;
import com.leefj.foxnic.sql.demo.app.domain.example.OrderItem;
import com.leefj.foxnic.sql.demo.config.DBInstance;
import com.leefj.foxnic.sql.demo.config.db.ExampleTables;

/**
* 代码生成器
* */
public class ExampleCodeGenerator {
    public static interface  Config  {void config(PoClassFile poType);
    }

    private static final String BASE_PACKAGE = "com.leefj.foxnic.sql.demo.app";

    /**
    * 须要首先运行 ExampleDBMetaGenerator 生成 ExampleTables 类
    * */
    public static void main(String[] args) {ExampleCodeGenerator generator = new ExampleCodeGenerator();
        // 生成商品实体类
        generator.generate(ExampleTables.EXAMPLE_GOODS.$TABLE, poType -> {
            // Goods 对象 通过 orderList 属性持有 Order
            poType.addListProperty(Goods.class,"orderList","订单明细商品","订单明细商品");
            // Goods 对象 通过 addressList 属性持有 Address
            poType.addListProperty(Address.class,"addressList","收件地址","收件地址,包含收件人以及手机号码");
            // Goods 对象 通过 itemList 属性持有 OrderItem
            poType.addListProperty(OrderItem.class,"itemList","订单明细","订单明细");
        });
        // 生成订单实体类
        generator.generate(ExampleTables.EXAMPLE_ORDER.$TABLE , poType -> {
            // Order 对象 通过 goodsList 属性持有 Goods
            poType.addListProperty(Goods.class,"goodsList","订单明细商品","订单明细商品");
            // Order 对象 通过 address 属性持有 Address
            poType.addSimpleProperty(Address.class,"address","收件地址","收件地址,包含收件人以及手机号码");
            // Order 对象 通过 itemList 属性持有 OrderItem
            poType.addListProperty(OrderItem.class,"itemList","订单明细","订单明细");
        });
        // 生成订单明细实体类
        generator.generate(ExampleTables.EXAMPLE_ORDER_ITEM.$TABLE, poType -> {
            // OrderItem 对象 通过 goodsList 属性持有 Goods
            poType.addSimpleProperty(Goods.class,"goods","订单明细商品","订单明细商品");
            // OrderItem 对象 通过 address 属性持有 Address
            poType.addSimpleProperty(Address.class,"address","收件地址","收件地址,包含收件人以及手机号码");
            // OrderItem 对象 通过 order 属性持有 Order
            poType.addListProperty(Order.class,"order","订单","订单");
        });
        // 生成地址实体类
        generator.generate(ExampleTables.EXAMPLE_ADDRESS.$TABLE, poType -> {
            // Address 对象 通过 goodsList 属性 持有 Goods
            poType.addListProperty(Goods.class,"goodsList","订单明细商品","订单明细商品");
            // Address 对象 通过 orderList 持有 Order
            poType.addListProperty(Address.class,"orderList","收件地址","收件地址,包含收件人以及手机号码");
            // Address 对象 通过 itemList 持有 OrderItem
            poType.addListProperty(OrderItem.class,"itemList","订单明细","订单明细");
        });
    }
    /**
    * 按表生成
    * */
    public void generate(DBTable table) {generate(table,null);
    }
    /**
    * 按表生成
    * */
    public void generate(DBTable table,Config config) {DAO dao = DBInstance.DEFAULT.dao();
        MavenProject project = GeneratorUtil.getProject();
        String pkg = table.name().split("_")[0];
        String prefix = pkg + "_";
        ModuleContext context = new ModuleContext(GeneratorUtil.initGlobalSettings(),table,prefix,BASE_PACKAGE + "." + pkg);
        context.setDomainProject(project);
        context.setServiceProject(project);
        context.setDAO(dao);
        if(config!=null) {config.config(context.getPoClassFile());
        }
        context.buildPo();
        context.buildVo();
        context.buildService();}                    
}

Web 环境的代码生成

  Web 环境的代码生成本文以 webfull 我的项目为示例,它以 WebFullCodeStarter 开始,初始化代码生成器,各模块配置,最初按生成用户指定的模块代码。代码生成的模块配置是按表配置的,一个表对应一套代码。咱们先来看一下 WebFullCodeStarter 的代码:

package org.github.foxnic.web.generator.module;

import com.github.foxnic.generator.util.ModuleCodeGenerator;
import org.github.foxnic.web.generator.module.bpm.ExampleReimbursementConfig;
import org.github.foxnic.web.generator.module.mall.ExampleAddressConfig;
import org.github.foxnic.web.generator.module.mall.ExampleGoodsConfig;
import org.github.foxnic.web.generator.module.mall.ExampleOrderConfig;
import org.github.foxnic.web.generator.module.mall.ExampleOrderItemConfig;
/**
* 代码生成启动类
* */
public class WebFullCodeStarter extends ModuleCodeGenerator {public static void main(String[] args) {
        // 新建启动类对象
        WebFullCodeStarter g=new WebFullCodeStarter();
        // 初始化本次须要生成代码的模块
        g.initModules();
        // 启动
        g.start();}
    /**
    * 初始化本次须要生成代码的模块
    * */
    public void initModules() {initExampleModules();
        initBPMModules();}
    /**
    * 初始化 BPM 示例模块
    * */
    private void initBPMModules() {this.addConfig(new ExampleReimbursementConfig());
    }
    /**
    * 初始化订单示例模块
    * */
    private void initExampleModules() {this.addConfig(new ExampleGoodsConfig());
        this.addConfig(new ExampleAddressConfig());
        this.addConfig(new ExampleOrderConfig());
        this.addConfig(new ExampleOrderItemConfig());
    }
}

  启动 WebFullCodeStarter 的 main 函数,输入如下:

输出 ALL 生成全副

或输出需模块序号: (1) webfull_example_goods (2) webfull_example_address (3) webfull_example_order (4) webfull_example_order_item (5) webfull_example_reimbursement

|

  此时,输出 all 或 a 生成列表中全副模块的代码,如果输出指定模块的序号,则社能成指定模块的代码。

  从这个动图中,咱们不难发现,代码生成器不用重启能够重复生成。针对一些界面的生成,能够边批改代码生成的配置,边生成边测试,咱们把它叫做迭代式的代码生成。

  为了可能重复进行代码生成,咱们针对模块代码的构造做了一些非凡的设计,尽量把业务逻辑的代码剥离到某个独自的文件,其它文件则能够重复生成,这种代码生成的形式极大的进步了开发效率。

代码生成的后果

  某个模块的代码生成后,在我的项目的各个 Maven 子模块下生成相应的 Java 类、Html 文件、js 文件。上面对各个文件阐明如下:

文件类型 示例 地位 阐明
PO Order.java domain 与数据表对应的实体类。
POMeta OrderMeta.java domain 针对 PO 类的元数据形容,蕴含一个 PO Proxy 外部类。
VO OrderVO.java domain 用于 API 接口传参、返回等。
VOMeta OrderVOMeta.java domain 针对 VO 类的元数据形容,蕴含一个 VO Proxy 外部类。
自定义模型 CustomModel domain 代码生成时自定义的模型类。
Proxy OrderServiceProxy.java proxy 接口代理、Feign 代理接口、接口门路定义。
服务接口 IOrderService.java service 服务接口
服务实现 OrderServiceImpl.java service 服务接口实现
流程反对 OrderBpmEventAdaptor.java service 可选;开启流程审批时会生成,解决流程逻辑。
API 控制器 OrderController service Rest API 接口控制器
页面控制器 OrderPageController view 页面控制器
列表页 order_list.html view 列表页,表格展现数据。
列表页 JS order_list.js view 列表页对应的 JS 文件
表单页 order_form.html view 表单页,表单形式展现、编辑数据。
表单页 JS order_form.js view 表单页 JS
逻辑扩大 JS order_ext.js view 剥离表单、表格业务逻辑,使页面代码可重复生成。

  从下面的表格咱们能够看到,一个数据表对用的简略模块,就蕴含可诸多文件。其中,彩色加粗的几项不倡议手动批改,如要批改能够通过代码生成的形式从新生成。

  页面如果有业务逻辑,尽量到 xxx_ext.js 文件批改,因为一旦批改也列表页或表单也的代码就无奈再次从新生成代码。

我的项目依赖

  Foxnic-Web 代码生成的形式是迭代式的,所以被生成的代码须要依赖到代码生成的我的项目中。以 webfull 我的项目的 generator 我的项目为例,在它的 pom 文件中须要退出 domain、proxy、service 和 view 的依赖。

<dependencies>
  <!-- 通用根底模块 -->
  <dependency>
    <groupId>com.github.foxnic.web</groupId>
    <artifactId>framework-boot</artifactId>
    <version>${foxnic.web.version}</version>
  </dependency>
  <dependency>
    <groupId>com.github.foxnic.web</groupId>
    <artifactId>framework-cloud</artifactId>
    <version>${foxnic.web.version}</version>
  </dependency>
  <dependency>
    <groupId>com.github.foxnic</groupId>
    <artifactId>foxnic-generator</artifactId>
    <version>${foxnic.version}</version>
  </dependency>
  <!-- 以后我的项目根底模块 -->
  <dependency>
    <groupId>com.github.foxnic.example.webfull</groupId>
    <artifactId>webfull-proxy</artifactId>
    <version>${project.version}</version>
  </dependency>
  <dependency>
    <groupId>com.github.foxnic.example.webfull</groupId>
    <artifactId>webfull-domain</artifactId>
    <version>${project.version}</version>
  </dependency>
  <dependency>
    <groupId>com.github.foxnic.example.webfull</groupId>
    <artifactId>webfull-framework</artifactId>
    <version>${project.version}</version>
  </dependency>
  <!-- 以后我的项目业务模块 -->
  <dependency>
    <groupId>com.github.foxnic.example.webfull</groupId>
    <artifactId>webfull-service-example</artifactId>
    <version>${project.version}</version>
  </dependency>
  <dependency>
    <groupId>com.github.foxnic.example.webfull</groupId>
    <artifactId>webfull-view-example</artifactId>
    <version>${project.version}</version>
  </dependency>
</dependencies>

小结

  本节次要介绍了在 Foxnic-SQL 和 oxnic-Web 代码生成的根本步骤,以及代码生成的文件散布,具体作用等。尤其要留神是代码生成我的项目的依赖问题,可能导致异样而无奈正确生成代码。

  前面的章节中,咱们将进一步介绍代码生成的细节。

相干我的项目

  https://gitee.com/LeeFJ/foxnic

  https://gitee.com/LeeFJ/foxni…

  https://gitee.com/lank/eam

  https://gitee.com/LeeFJ/foxni…

官网文档

  http://foxnicweb.com/docs/doc…

正文完
 0