mybatis-plus代码生成器加模板实践

mybatis-plus代码生成器加模板实践

MyBatis-Plus(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生!
这是官方的介绍说明,不了解的小伙伴可以点击标签去查看。
之前也有写过一版mp的代码生成器,他原本的代码生成器只是生成了一个简单的mvc架构,而且不包括前端的代码,前端的html和js还需要自己去编写,比较麻烦,这个版本集成了Velocity模板,所有的CRUD操作都可以自己定义,包过前端的js和html文件也可生成,大大简化了代码量,用户只需要关注模块的核心业务即可。
下面介绍一下开发流程,项目使用的是springboot+mybatis-plus+mysql

一、集成Velocity模板

maven项目中导入该坐标

 <dependency>
     <groupId>org.apache.velocity</groupId>
     <artifactId>velocity</artifactId>
     <version>1.7</version>
 </dependency>

(一)创建VelocityUtils工具类
该工具类会将前端的文件全部创建好

/**
 * @Author: SongTiank
 * @Description: 前端文件生成
 * @Date: 2021/6/22 10:01
 * @Version: 1.0
 */
public class VelocityUtils {
    private final static Logger log = LoggerFactory.getLogger(VelocityUtils.class);
    private static final String VM_ENTITY_PATH = "templates/js/frontEnd.js.vm";
    private static final String VM_ENTITY_ADD_PATH = "templates/js/frontEnd_add.js.vm";
    private static final String VM_ENTITY_EDIT_PATH = "templates/js/frontEnd_edit.js.vm";
    private static final String VM_HTML_PATH = "templates/html/frontEnd.html.vm";

    /**
     * 创建首页js
     * fileName 文件名称
     * tableColumn 数据库字段集合
     * CREAT_PATH 文件生成路径
     */
    public static void creatEntityJs(String fileName,List<TableColumn> tableColumn,String CREAT_PATH){
        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        velocityEngine.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
        velocityEngine.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
        velocityEngine.init();
        // 获取模板文件
        Template template = velocityEngine.getTemplate(VM_ENTITY_PATH);
        // 设置变量,velocityContext是一个类似map的结构
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("tableName",fileName);
        tableColumn.remove(0);//移除只存表名的对象;
        velocityContext.put("list", tableColumn);
        // 输出渲染后的结果
        StringWriter stringWriter = new StringWriter();
        template.merge(velocityContext, stringWriter);
        //写入文件中
        ZipUtil.writeToFile(stringWriter.toString(),CREAT_PATH+"//"+fileName+".js");
    }


    /**
     * 创建新增js
     * fileName 文件名称
     * CREAT_PATH 文件生成路径
     */
    public static void creatEntityAddJs(String fileName,String CREAT_PATH){
        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        velocityEngine.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
        velocityEngine.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
        velocityEngine.init();
        // 获取模板文件
        Template template = velocityEngine.getTemplate(VM_ENTITY_ADD_PATH);
        // 设置变量,velocityContext是一个类似map的结构
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("tableName", fileName);
        // 输出渲染后的结果
        StringWriter stringWriter = new StringWriter();
        template.merge(velocityContext, stringWriter);
        //写入文件中
        ZipUtil.writeToFile(stringWriter.toString(),CREAT_PATH+"//"+fileName+"_add.js");
    }

    /**
     * 创建修改js
     * fileName 文件名称
     * CREAT_PATH 文件生成路径
     */
    public static void creatEntityEditJs(String fileName,String CREAT_PATH){
        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        velocityEngine.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
        velocityEngine.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
        velocityEngine.init();
        // 获取模板文件
        Template template = velocityEngine.getTemplate(VM_ENTITY_EDIT_PATH);
        // 设置变量,velocityContext是一个类似map的结构
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("tableName", fileName);
        // 输出渲染后的结果
        StringWriter stringWriter = new StringWriter();
        template.merge(velocityContext, stringWriter);
        //写入文件中
        ZipUtil.writeToFile(stringWriter.toString(),CREAT_PATH+"//"+fileName+"_edit.js");
    }

    /**
     * 创建html页面
     * fileName 文件名称
     * CREAT_PATH 文件生成路径
     */
    public static void creatEntityHtml(String fileName,String CREAT_PATH){
        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        velocityEngine.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
        velocityEngine.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
        velocityEngine.init();
        // 获取模板文件
        Template template = velocityEngine.getTemplate(VM_HTML_PATH);
        // 设置变量,velocityContext是一个类似map的结构
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("tableName", fileName);
        // 输出渲染后的结果
        StringWriter stringWriter = new StringWriter();
        template.merge(velocityContext, stringWriter);
        //写入文件中
        ZipUtil.writeToFile(stringWriter.toString(),CREAT_PATH+"//"+fileName+".html");
    }
}

文件目录展示
在这里插入图片描述

创建代码工具类

/**
 * 代码生成执行类
 * @Author: SongTiank
 * @Date: 2021/6/20 13:01
 */
public class CreatTableUtil {

    /**
     * 代码执行类
     *TODO 文件存储位置部署需要更换
     * 前端页面选择数据库表传递过来的数据。
     * 我是创建到了本地D盘,模仿服务器,而后压缩下载到本地,再将downLoad里的文件删除,服务器上需要调整路径。
     * @param creatTableName 待创建的数据库表名集合、
     * @param dataSource	数据库注册、
     * @param Author   创建人
     * @param PakagePath 包路径
     * @param ModelName  模块名
     * @return
     */
    public static String creating(String[] creatTableName, DataSourceConfig dataSource,String Author,String PakagePath,
                                String ModelName,HttpServletResponse response, HttpServletRequest request) {
        AutoGenerator mpg = new AutoGenerator();
        mpg.setDataSource(dataSource);
        String projectPath = request.getSession().getServletContext().getRealPath("/");
        String creatPath = "D://text" + "/" + randomUUID().toString().replaceAll("-", "");
        String downLoadPath = "D://text//downLoad";
        File temDir = new File(creatPath);
        if (!temDir.exists()) {
            temDir.mkdirs();
        }
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(creatPath); //生成路径
        gc.setAuthor(Author);     //作者
        gc.setFileOverride(true);   //是否覆盖
        gc.setActiveRecord(true);   // 不需要ActiveRecord特性的请改为false
        gc.setEnableCache(false);   // XML 二级缓存
        gc.setBaseResultMap(true);  // XML ResultMap
        gc.setBaseColumnList(true); // XML columList
        gc.setOpen(false);
        mpg.setGlobalConfig(gc);
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
        if (creatTableName != null && creatTableName.length>0) {
            strategy.setInclude(creatTableName); // 需要生成的表
        }
        strategy.setEntityBuilderModel(true);
        mpg.setStrategy(strategy);
        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent(ModelName);
        pc.setController(PakagePath+".controller");
        pc.setEntity(PakagePath+".entity");
        pc.setMapper(PakagePath+".mapper");
        pc.setService(PakagePath+".service");
        pc.setServiceImpl(PakagePath+".serviceImpl");
        pc.setXml(PakagePath+".mapperXml");
        mpg.setPackageInfo(pc);
        mpg.setTemplate(TemplateGenerate());
        // 执行生成
        mpg.execute();
        //--------------前端代码生成------------------------
        for (String tableName : creatTableName) {
            try {
            	//获取该表的名称,和所有字段以及注释,作为前端生成的条件。
                List<TableColumn> tableColumn = getTableColumn(dataSource, tableName);
                String fileName=  tableColumn.get(0).getTableName();
                VelocityUtils.creatEntityJs(fileName,tableColumn,temDir.getPath());//首页js
                VelocityUtils.creatEntityAddJs(fileName,temDir.getPath());//新增js
                VelocityUtils.creatEntityEditJs(fileName,temDir.getPath());//编辑js
                VelocityUtils.creatEntityHtml(fileName,temDir.getPath());//创建html页面
                VelocityUtils.creatEntityHtmlAdd(fileName,tableColumn,temDir.getPath());//创建add页面
                VelocityUtils.creatEntityHtmlEdit(fileName,tableColumn,temDir.getPath());//创建edit页面
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        //--------------前端代码生成结束----------------------
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=excel.zip");
        String zipName=UUID.randomUUID().toString().replaceAll("-", "")+".zip";
        /** 4.调用工具类,下载zip压缩包 */
        try {
            FileOutputStream fos1 = new FileOutputStream(new File(downLoadPath + "//"+zipName));
            ZipUtil.toZip(temDir.getPath(), fos1, true);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            ZipUtil.delFolder(creatPath);
        }
        return zipName;
    }

    /**
     * 自定义模板配置
     */
    private static TemplateConfig TemplateGenerate() {
        TemplateConfig templateConfig = new TemplateConfig()
                .setController("templates/java/controller.java" )
                .setService("templates/java/service.java" )
                .setServiceImpl("templates/java/serviceImpl.java" )
                .setEntity("templates/java/entity.java")
                .setMapper("templates/java/mapper.java" )
                .setXml("templates/java/mapper.xml");
        return templateConfig;
    }


```java
    /**
     * 动态获取表字段
     * @return 查询到的表字段对象集合
     * @throws ClassNotFoundException
     * @throws SQLException
     */
    public static List<TableColumn> getTableColumn(DataSourceConfig dataSource,String tableName) throws ClassNotFoundException, SQLException {
        List<TableColumn> tableColumnList=new ArrayList<>();//存储字段和注释
        Class.forName(dataSource.getDriverName());
        Connection conn= DriverManager.getConnection(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword());
        TableColumn _tableName = new TableColumn();//表名改驼峰
        _tableName.setTableName(JDBCUtils.underline2Camel(tableName));
        tableColumnList.add(_tableName);//存入表名
        String sql = "select column_name,column_comment from Information_schema.columns  where table_Name='"+tableName+"'";
        Statement statement = conn.createStatement();
        ResultSet rs = statement.executeQuery(sql);
        while (rs.next()) {
            //获取表字段、表注释,underline2Camel方法:下划线取消,后面字母调整大写,小驼峰命名
            String columnName = JDBCUtils.underline2Camel(rs.getString(1), false);
            String content = JDBCUtils.underline2Camel(rs.getString(2), false);
            TableColumn tableColumn = new TableColumn(columnName,content); //字段名称,字段注释
            tableColumnList.add(tableColumn);
        }
        rs.close();
        conn.close();
        return tableColumnList;
    }
}

下划线调整工具类

  /**
     * 下划线调整工具类
     * @param line
     * @param firstIsUpperCase
     * @return
     */
    public static String underline2Camel(String line, boolean ... firstIsUpperCase) {
        String str = "";

        if (StringUtils.isBlank(line)) {
            return str;
        } else {
            StringBuilder sb = new StringBuilder();
            String[] strArr;
            // 不包含下划线,且第二个参数是空的
            if (!line.contains("_") && firstIsUpperCase.length == 0) {
                sb.append(line.substring(0, 1).toLowerCase()).append(line.substring(1));
                str = sb.toString();
            } else if (!line.contains("_") && firstIsUpperCase.length != 0) {
                if (!firstIsUpperCase[0]) {
                    sb.append(line.substring(0, 1).toLowerCase()).append(line.substring(1));
                    str = sb.toString();
                } else {
                    sb.append(line.substring(0, 1).toUpperCase()).append(line.substring(1));
                    str = sb.toString();
                }
            } else if (line.contains("_") && firstIsUpperCase.length == 0) {
                strArr = line.split("_");
                for (String s : strArr) {
                    sb.append(s.substring(0, 1).toUpperCase()).append(s.substring(1));
                }
                str = sb.toString();
                str = str.substring(0, 1).toLowerCase() + str.substring(1);
            } else if (line.contains("_") && firstIsUpperCase.length != 0) {
                strArr = line.split("_");
                for (String s : strArr) {
                    sb.append(s.substring(0, 1).toUpperCase()).append(s.substring(1));
                }
                if (!firstIsUpperCase[0]) {
                    str = sb.toString();
                    str = str.substring(0, 1).toLowerCase() + str.substring(1);
                } else {
                    str = sb.toString();
                }
            }
        }
        return str;
    }

以上就是工具类的核心方法,有疑问或者指教欢迎留言~
❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…