基于ry-vue-plus的代码生成工具整合自定义模版

news2024/9/27 19:24:49

前言

         鉴于自己最近参加一个比赛,整区块链应用,因此部分核心数据需要往区块链网络的数据库中存储。用的区块链框架为FISCO-BCOS。FISCO-BCOS官方提供一一个预编译合约,名叫Table.sol (CRUD合约),能让我们通过CRUD合约像使用一般关系型数据库中的增删改查操作,从而对数据进行增删改查。

        但,问题是,这个合约虽然提供了数据库一样的操作,并没有像Java一样的映射框架,就算用Table.sol来操作数据上链,这个代码量也非常大。

        所以啊,我就想到之前我研究到的一个项目ry-vue-plus,有个代码生成工具,通过数据库连接->进而生成一般的crud代码、以及vue文件、domain、service、mapper之类的。在此基础上,对合约也设置一个模版,对数据库表 —— 合约的映射。

ry-vue-plus采用的模版引擎为velocity。

以下,只是记录如何整合自定义模版配置。以及设计对模版引擎的介绍。

1.什么是模版引擎?

 模板引擎是构建动态内容的重要工具,特别适用于生成HTML、邮件内容、报告和其他文本文档。

简单来讲,能够让我们通过定义模板来生成动态内容。模板通常包含静态内容以及特殊语法或占位符,这些占位符可以在运行时被动态数据替换

2.Velocity 简介 

Velocity是一个强大的模板引擎,它具有简单易用的语法和灵活性。 
Velocity是一个用于生成文本输出的模板引擎。它是一种轻量级的、开源的工具,最初由Apache开发。

Velocity的主要特点包括:

简单的语法: Velocity使用简单的模板语法,易于学习和使用。

  • 灵活性: Velocity允许在模板中嵌套、迭代和使用条件语句,以便生成复杂的输出。
  • 模板重用: 模板可以被多次重用,从而减少了重复代码。
  • 可扩展性: Velocity可以与Java代码集成,允许在模板中调用Java方法。
  • 广泛支持: Velocity可以用于生成HTML、XML、JSON等多种文本格式。

 开发

吆西,知道他是个啥东西了,直接在ry-vue-plus原有的配置上进行代码开发。

找到代码生成核心

废话少说,他的代码生成在GenTableServiceImpl.java类中。核心代码在这里。

  ......

 /**
     * 查询表信息并生成代码
     */
    private void generatorCode(Long tableId, ZipOutputStream zip) {
        // 查询表信息
        GenTable table = baseMapper.selectGenTableById(tableId);
        List<Long> menuIds = new ArrayList<>();
        for (int i = 0; i < 6; i++) {
            menuIds.add(identifierGenerator.nextId(null).longValue());
        }
        table.setMenuIds(menuIds);
        // 设置主键列信息
        setPkColumn(table);
        VelocityInitializer.initVelocity();

        VelocityContext context = VelocityUtils.prepareContext(table);

        // 获取模板列表
        List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory());
        for (String template : templates) {
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, Constants.UTF8);
            tpl.merge(context, sw);
            // TODO 将模版的内容替换成实际渲染的内容
            try {
                // 添加到zip
                zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
                IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
                IoUtil.close(sw);
                zip.flush();
                zip.closeEntry();
            } catch (IOException e) {
                log.error("渲染模板失败,表名:" + table.getTableName(), e);
            }
        }
    }

......

第二个框中定义代码,将变量和那个模版渲染成那个实际的文件。

我们在模版文件中占位符使用的变量,就是在VelocityContext context = VelocityUtils.prepareContext(table);这行代码得出来的。

我们调试context变量里面的数据,发现就是这些字段吧,可以在模版文件中通过占位符的形式访问。

现在,我们知道这个模版中的占位符的数据是如何来的,然就是把我们自定义的模版添加到他的代码里面。

添加我们自己的模版

如下图位置。

在VelocityUtils.java 文件中,修改如下代码。定义如下,我们获取模版列表才能获取到。

在这个VelocityUtils.java的getFileName方法内。定义文件打包的路径。

定制我们自己的模版

仿写​

在GenTableServiceImpl.java的generatorCode方法内。

我们在上述知道context存储定义模版要使用的变量,调试到这里。以及参考项目已经定义好的模版使用,写在我们自己的模版中。

使用自定义方法

嗯,怎么讲,它里面有些样式可以用他的语法做出来,但是嫌麻烦,因此直接在模版文件调用java自定义方法,来处理数据得出我们想要的。

 还是在GenTableServiceImpl.java 文件的generatorCode方法内,如下位置,可以添加我们自定义类。从而在模版文件就可以调用这个类中的方法了。

 对应的静态类方法:

模版文件中的使用:


 

storage.sol.vm

pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;
import "./TableTools.sol";

#set($primayKey = $velocityUtil.getPrimaryKey($columns))
/// @title ${functionName}Storage
/// @author ${author}
/// @notice 操作${functionName}
contract  ${ClassName}Storage is TableTools{

    string constant ${ClassName}_Table = "${businessName}_table";
    string constant ${ClassName}_Fields = "$velocityUtil.generateFiledList($columns)";


    Bean tb_${businessName};

    event InsertResult(int8);

    constructor() public {
        // 初始化表结构
        initTableStruct(tb_${businessName}, ${ClassName}_Table,NOMINAL_PRIMARYKEY,${ClassName}_Fields);
    }

    /*
    * 查询全部${functionName}列表
    *
    * @return  ${functionName}列表
    */
    function queryList() public view returns(string memory) {
        int _code;
        string memory _res;
        string[] memory _strs = new string[](0);
        (_code,_res) = selectOneRecordByCondToJson(tb_${businessName}, COMMON_VALUE, _strs);
        require(_code == 1,"query failed!");
        return _res;
    }


    /*
    * 根据主键查询${functionName}
    *
    * @return  ${functionName}列表
    */
    function queryById(string memory _id) public view returns (string memory) {
        int8 _code;
        string memory _res;
        string[] memory _conditionPair = new string[](2);
        _conditionPair[0] = "${primayKey}"; 
        _conditionPair[1] = _id;
        (_code,_res) = selectOneRecordByCondToJson(tb_${businessName}, COMMON_VALUE,_conditionPair); // : 自定义字段查询
        require(_code == 1,"query failed!");
        return _res;
    }

    /*
    * 根据查询条件、分页查询${functionName}列表
    *
    * @param _conditionPair  查询条件
    * @param _pageNum  起始页数
    * @param _pageSize  起始页数
    * @return  ${functionName}列表
    */
    function queryList(string[] _conditionPair,int _pageNum,int _pageSize) public view returns(string memory) {
        string memory _res;int8 _code;
        Page memory _page = Page(_pageNum, _pageSize);
        (_code,_res) = selectOneRecordByCondToJson(tb_${businessName}, COMMON_VALUE,_conditionPair,_page);
        require(_code == 1,"query failed!");
        return _res;
    }

    /*
    *  新增${functionName}
    *
    * @param fieldsStr  字段列表字符串
    * @return  新增结果
    */
    function insert(string fieldsStr) public returns(bool) {
        string[] memory fields = getFieldsArray(fieldsStr);
        require(fields.length == $velocityUtil.getColumnsLength($columns),"The list length is wrong!");
        require(!_isIDExist(fields[0]),"insert info primaryKey exist!");
        int8 _code = insertOneRecord(tb_${businessName},COMMON_VALUE,fieldsStr, true);
        emit InsertResult(_code);
        bool end = _code == 1;
        require(end,"insert failed!");
        return end;
    }


    /*
    *  根据主键值更新${functionName}信息
    *
    * @param fieldsStr  字段列表字符串
    * @return  新增结果
    */
    function updateById(string memory _fieldsStr) public returns(bool) {
        string[] memory fields = getFieldsArray(_fieldsStr);
        string[] memory _conditionPair = new string[](2);
        _conditionPair[0] = "${primayKey}"; 
        _conditionPair[1] = fields[0];
        return update(_fieldsStr,_conditionPair);
    }

    /*
    *  根据条件更新${functionName}信息
    *
    * @param _fieldsStr 新字段列表字符串
    * @param _conditionPair 条件
    * @return  修改结果
    */
    function update(string memory _fieldsStr,string[] memory _conditionPair) public returns(bool) {
        int8 _code =  updateOneRecordByCond(tb_${businessName}, COMMON_VALUE,_fieldsStr,_conditionPair);
        bool end = _code == 1;
        require(end,"update failed!");
        return end;
    }

    /*
    * 根据主键值列表批量删除${functionName}信息
    *
    * @param _id  主键值
    * @param _id  主键值
    * @return  删除结果
    */
    function deleteWithValidByIds(string[] memory _ids,bool isValid) public returns(bool) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        int8 _code;
        for (uint j = 0; j < _ids.length; j++) {
            require(_isIDExist(_ids[j]),"remove failed!");
        }
        for (uint i = 0; i < _ids.length; i++) {
            string[] memory _conditionPair = new string[](2);
            _conditionPair[0] = "${primayKey}";
            _conditionPair[1] = _ids[i];
            _code =  remove(COMMON_VALUE,Test_Table,_conditionPair);
        }
        return _code == 1;
    }

    function deleteByIds(string[] memory _ids)  public returns(bool) {
        return deleteWithValidByIds(_ids,false);
    }


    /*
    * 根据主键值判断信息是否存在
    *
    * @param _id  主键值
    * @return  是否存在
    */
    function _isIDExist(string memory _id) internal view returns(bool) {
        string[] memory _conditionPair = new string[](2);
        _conditionPair[0] = "${primayKey}"; 
        _conditionPair[1] = _id;
        (int _code,) = selectOneRecordByCondToJson(tb_${businessName}, COMMON_VALUE,_conditionPair);
        return _code == 1;
    }

}

测试

导入数据表,点击生成之后。

打开解压好的文件,成功。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1914408.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【漏洞复现】WordPress插件Recall CVE-2024-32709 SQL注入漏洞

0x01 产品简介 WordPress是一款免费开源的内容管理系统(CMS)&#xff0c;最初是一个博客平台&#xff0c;但后来发展成为一个功能强大的网站建设工具&#xff0c;适用于各种类型的网站&#xff0c;包括个人博客、企业网站、电子商务网站等&#xff0c;并逐步演化成一款内容管理…

bug - while parsing file included at

bug 如下 找到这个对应文件tb_top.sv的对应行&#xff0c;发现是一个 include "inc_tb_tests_xxx.sv" 问题点&#xff1a;头文件&#xff0c;重复定义&#xff0c;那么 解决方法- 在被include的文件首尾加入 ifndef MY_TRANSACTION__SV define MY_TRANSACTION__SV …

【经典链表OJ】环形链表

一、题目要求 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&…

昇思25天学习打卡营第16天|应用实践之Vision Transformer图像分类

基本介绍 今天同样是图像分类任务&#xff0c;也更换了模型&#xff0c;使用的时候计算机视觉版的Transformer&#xff0c;即Vision Transformer&#xff0c;简称ViT。Transformer本是应用于自然语言处理领域的模型&#xff0c;用于处理语言序列&#xff0c;而要将其应用于图像…

百度网盘青春版网页版上线

不知道还有多少小伙伴记得百度网盘曾经出过一个青春版&#xff0c;原因是21年相关部门发布通知《工业和信息化部关于开展信息通信服务感知提升行动的通知》其中就有一条&#xff1a; 明确指出网盘向免费用户提供的上传和下载最低速率应满足基本的下载需求 正所谓上有政策下有对…

常用的设计模式和使用案例汇总

常用的设计模式和使用案例汇总 【一】常用的设计模式介绍【1】设计模式分类【2】软件设计七大原则(OOP原则) 【二】单例模式【1】介绍【2】饿汉式单例【3】懒汉式单例【4】静态内部类单例【5】枚举&#xff08;懒汉式&#xff09; 【三】工厂方法模式【1】简单工厂模式&#xf…

AI绘画小白必备!Stable Diffusion常用插件合集,好用推荐!(附插件下载)

前言 宝子们&#xff0c;早上好啊~Stable Diffusion 常用插件&#xff0c;月月已经给大家整理好了&#xff0c;自取就好。 拥有这些SD常用插件&#xff0c;让您的图像生成和编辑过程更加强大、直观、多样化。以下插件集成了一系列增强功能&#xff0c;覆盖从自动补全提示词到…

设置DepthBufferBits和设置DepthStencilFormat的区别

1&#xff09;设置DepthBufferBits和设置DepthStencilFormat的区别 2&#xff09;Unity打包exe后&#xff0c;游戏内拉不起Steam的内购 3&#xff09;Unity 2022以上Profiler.FlushMemoryCounters耗时要怎么关掉 4&#xff09;用GoodSky资产包如何实现昼夜播发不同音乐功能 这是…

东旭蓝天被控股股东占用78亿:近七年业绩奇差,或面临退市

《港湾商业观察》施子夫 张楠 在7月5日一口气发了超过30份公告后&#xff0c;终于让投资者对于东旭蓝天2023年和今年一季度经营业绩有了更清晰的观察。 与此同时&#xff0c;东旭蓝天&#xff08;下称&#xff09;也收到了深交所的关注函。种种不利因素之下&#xff0c;上市…

【竞技宝 】欧洲杯:赛事水货盘点

本届欧洲杯接近尾声,有些球员抓住机会趁势崛起,踢出了身价。可惜还有一些球员的表现无法让球迷和媒体满意,下面我们就来盘点下本届欧洲杯的水货球员,看看哪些人因为糟糕的表现上榜? 格瓦迪奥尔(克罗地亚) 本届欧洲杯是克罗地亚黄金一代球员的谢幕之战,原本格瓦迪奥尔作为球队…

凌凯科技前五大客户依赖症加剧:研发费用率骤降,应收账款大增

《港湾商业观察》黄懿 6月13日&#xff0c;上海凌凯科技股份有限公司&#xff08;下称“凌凯科技”&#xff09;在港交所提交上市申请&#xff0c;拟于主板上市&#xff0c;华泰国际为其独家保荐人。 凌凯科技致力于提供小分子化合物技术和产品解决方案&#xff0c;专注于制药…

探索东芝 TCD1304DG 线性图像传感器的功能

主要特性 高灵敏度和低暗电流 TCD1304DG 具有高灵敏度和低暗电流&#xff0c;非常适合需要精确和可靠图像捕捉的应用。传感器包含 3648 个光敏元件&#xff0c;每个元件尺寸为 8 m x 200 m&#xff0c;确保了出色的光灵敏度和分辨率。 电子快门功能 内置的电子快门功能是 T…

【onnx】onnxruntime-gpu无法使用问题

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 onnxruntime-gpu无法使用 1. 正文 CUDA版本&#xff1a;12.1 nvcc -VCUDNN的版本 cat /usr/include/cudnn_version.h |grep CUDNN_MAJOR -A 2说明: 可…

免费的SSL证书能使用吗

SSL证书为网站提供数据安全加密&#xff0c;保护数据传输&#xff0c;提升用户信任。 现在免费的SSL证书还能使用吗&#xff1f;答案是肯定的。个人博客、个人的网站目前使用免费SSL证书的居多&#xff0c;另外一些单位在网站上线前&#xff0c;也会使用免费SSL证书对网站进行…

品牌策划学习资源全攻略:从入门到精通的推荐清单!

这里再分享一些网站书籍和杂志给大家。 TOPYS创意内容平台&#xff1a; 专注于创意内容分享&#xff0c;涵盖广告、设计、艺术等多个领域&#xff0c;是广告设计人寻找创意灵感的好去处。 Dribbble&#xff1a; 设计师社区&#xff0c;用户可以浏览到全球设计师的优秀作品&…

低代码技术革新:高效构建现代人事管理系统

引言 在快速变化的商业环境中&#xff0c;企业必须不断提升其内部管理效率&#xff0c;以保持竞争力和灵活性。人事管理系统作为企业核心业务系统之一&#xff0c;承担着招聘、培训、绩效管理等重要功能&#xff0c;直接影响着企业的人才管理和运营效率。传统的人事管理系统通常…

Vue核心 — Vue2响应式原理和核心源码解析(核心中的核心)

一、前置知识 1、Vue 核心概念 Vue 是什么? Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建&#xff0c;并提供了一套声明式的、组件化的编程模型&#xff0c;帮助你高效地开发用户界面。 Vue 核心特点是什么? 响应式数据绑定:…

Springboot助农农产品销售系统-计算机毕业设计源码16718

摘要 SpringBoot助农农产品销售系统旨在通过利用SpringBoot框架开发一个便捷高效的农产品销售平台。该系统包括用户注册登录、商品浏览、购物车管理、订单生成、支付功能等模块。通过整合支付接口、地图定位、推荐系统等技术&#xff0c;提供给用户更好的购物体验。本文介绍了…

考完软考之后,如何评职称?是否有有效期?

一、软考和职称之间的关系 软考和职称之间的关系可以这样理解&#xff1a;拿到软考证书并不意味着就能获得职称。软考证书是技术等级证书&#xff0c;而职称则是一种资格。如果单位聘用你做工程师&#xff0c;那么你的软考证书就可以发挥作用&#xff0c;相当于获得了职称证。…

私域运营从0到1冷启动

私域社群的冷启动是一个从无到有的过程&#xff0c;需要策略和耐心来吸引并维护用户。以下是一些步骤和策略&#xff0c;可以帮助你的私域社群实现从0到1的冷启动&#xff1a; 1. **明确目标和定位**&#xff1a; - 确定社群的目标用户和他们的需求。 - 明确社群的主题和…