CrudBoy快乐水-编写代码生成器

没有理由不根据自己的项目编写一套适合自己项目的代码生成工具,不是吗?

思路: 首先根据自己的项目情况,定义好代码模板与占位参数,生成的时候只需要将参数填进去,再在指定的位置生成相应的.java/.xml等文件即可

使用freemarker模板引擎 compile 'org.freemarker:freemarker:2.3.23'

# 核心源源码

package com.futao.springbootdemo.utils.generator;

import com.futao.springbootdemo.foundation.ApplicationException;
import com.futao.springbootdemo.utils.DateTools;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 代码生成器
 *
 * @author futao
 * Created on 2019-03-08.
 */
public class CodeGeneratorManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(CodeGeneratorManager.class);
    /**
     * 项目基础路径
     */
    private static final String PROJECT_BASE_PATH = System.getProperty("user.dir") + "/src/main/java/com/futao/springbootdemo";
    /**
     * 模板文件路径
     */
    private static final String TEMPLATE_FILE_PATH = PROJECT_BASE_PATH + "/utils/generator/template";
    /**
     * Entity生成路径
     */
    private static final String ENTITY_PATH = PROJECT_BASE_PATH + "/model/entity";
    /**
     * Controller路径
     */
    private static final String CONTROLLER_PATH = PROJECT_BASE_PATH + "/controller/business";
    /**
     * Service实现类生成路径
     */
    private static final String SERVICE_IMPL_PATH = PROJECT_BASE_PATH + "/service/impl";
    /**
     * Service接口生成路径
     */
    private static final String SERVICE_FACE_PATH = PROJECT_BASE_PATH + "/service";
    /**
     * Dao Mapper路径
     */
    private static final String DAO_PATH = PROJECT_BASE_PATH + "/dao";
    /**
     * Mybatis mapper xml文件路径
     */
    private static final String MYBATIS_MAPPER_XML_PATH = System.getProperty("user.dir") + "/src/main/resources/mybatis/mapper";


    private static Configuration configuration = null;

    private CodeGeneratorManager() {
    }

    /**
     * Freemarker 模板环境配置
     *
     * @return
     * @throws IOException
     */
    private Configuration initFreemarkerConfiguration() {
        Configuration cfg;
        try {
            cfg = new Configuration(Configuration.VERSION_2_3_23);
            cfg.setDirectoryForTemplateLoading(new File(TEMPLATE_FILE_PATH));
            cfg.setDefaultEncoding("UTF-8");
            cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        } catch (IOException e) {
            throw new RuntimeException("Freemarker 模板环境初始化异常!", e);
        }
        return cfg;
    }

    /**
     * 获取模板文件
     *
     * @return
     */
    private Template getTemplate(String templateName) {
        if (configuration == null) {
            configuration = initFreemarkerConfiguration();
        }
        try {
            return configuration.getTemplate(templateName);
        } catch (IOException e) {
            e.printStackTrace();
            throw ApplicationException.ae(e.getMessage());
        }
    }

    /**
     * 生成代码
     *
     * @param args
     */
    public static void main(String[] args) {
        CodeGeneratorManager codeGeneratorManager = new CodeGeneratorManager();

        Map<String, Object> dataMap = new HashMap<>(6);
        dataMap.put("className", "Address");
        dataMap.put("classDesc", "地址");
        dataMap.put("createDate", DateTools.dateToString(new Date(), DateTools.yyyyMMdd));
        dataMap.put("controllerPackagePath", getPackagePath(CONTROLLER_PATH));
        dataMap.put("entityPackagePath", getPackagePath(ENTITY_PATH));
        dataMap.put("serviceFacePackagePath", getPackagePath(SERVICE_FACE_PATH));
        dataMap.put("serviceImplPackagePath", getPackagePath(SERVICE_IMPL_PATH));
        dataMap.put("daoPackagePath", getPackagePath(DAO_PATH));

        Template entityTemplate = codeGeneratorManager.getTemplate("EntityTemplate.ftl");
        Template controllerTemplate = codeGeneratorManager.getTemplate("ControllerTemplate.ftl");
        Template serviceFaceTemplate = codeGeneratorManager.getTemplate("ServiceFaceTemplate.ftl");
        Template serviceImplTemplate = codeGeneratorManager.getTemplate("ServiceImplTemplate.ftl");
        Template daoTemplate = codeGeneratorManager.getTemplate("DaoTemplate.ftl");
        Template mapperTemplate = codeGeneratorManager.getTemplate("MapperTemplate.ftl");

        File entityFile = new File(ENTITY_PATH + "/" + dataMap.get("className") + ".java");
        File controllerFile = new File(CONTROLLER_PATH + "/" + dataMap.get("className") + "Controller.java");
        File serviceFaceFile = new File(SERVICE_FACE_PATH + "/" + dataMap.get("className") + "Service.java");
        File serviceImplFile = new File(SERVICE_IMPL_PATH + "/" + dataMap.get("className") + "ServiceImpl.java");
        File daoFile = new File(DAO_PATH + "/" + dataMap.get("className") + "Dao.java");
        File mapperFile = new File(MYBATIS_MAPPER_XML_PATH + "/" + dataMap.get("className") + "Mapper.xml");


        try {
            entityTemplate.process(dataMap, new FileWriter(entityFile));
            System.out.println(">>>> 实体类【" + dataMap.get("className") + "】生成成功");
            controllerTemplate.process(dataMap, new FileWriter(controllerFile));
            System.out.println(">>>> 控制器类【" + dataMap.get("className") + "Controller】生成成功");
            serviceFaceTemplate.process(dataMap, new FileWriter(serviceFaceFile));
            System.out.println(">>>> Service接口【" + dataMap.get("className") + "Service】生成成功");

            serviceImplTemplate.process(dataMap, new FileWriter(serviceImplFile));
            System.out.println(">>>> Service实现类【" + dataMap.get("className") + "ServiceImpl】生成成功");

            daoTemplate.process(dataMap, new FileWriter(daoFile));
            System.out.println(">>>> Dao接口【" + dataMap.get("className") + "Dao】生成成功");

            mapperTemplate.process(dataMap, new FileWriter(mapperFile));
            System.out.println(">>>> Mapper文件【" + dataMap.get("className") + "Mapper】生成成功");

            System.out.println(StringUtils.repeat("=", 20) + "执行完毕" + StringUtils.repeat("=", 20));
        } catch (TemplateException | IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 根据文件系统路径获取包路径
     *
     * @param fileSysPath 文件系统路径
     * @return
     */
    private static String getPackagePath(String fileSysPath) {
        return fileSysPath.substring(fileSysPath.indexOf("com")).replace("/", ".");
    }

}

# 代码模板(只贴出两个示例)

  • Controller.java
package ${controllerPackagePath};

import ${entityPackagePath}.${className};
import ${serviceFacePackagePath}.${className}Service;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
* ${classDesc}操作接口
*
* @author futao
* Created on ${createDate}.
*/
@Api("${classDesc}")
@RestController
@RequestMapping(path = "${className?lower_case}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class ${className}Controller {
    @Resource
    private ${className}Service ${className?lower_case}Service;

    /**
    * 新增${classDesc}
    *
    * @return
    */
    @ApiOperation("新增${classDesc}")
    @PostMapping(path = "add")
    public ${className} add(
    ) {
    return ${className?lower_case}Service.add();
    }

    /**
    * 删除${classDesc}
    *
    * @param id 要删除的${classDesc}的id
    * @return
    */
    @DeleteMapping("{id}")
    public ${className} delete(
        @PathVariable("id") String id
    ) {
    return ${className?lower_case}Service.delete(id);
    }

    /**
    * 更新${classDesc}
    *
    * @param id 要更新的${classDesc}的id
    * @return
    */
    @PutMapping("{id}")
    public ${className} update(
        @PathVariable("id") String id
    ) {
        return ${className?lower_case}Service.update(id);
    }


    /**
    * 查询${classDesc}列表
    *
    * @return
    */
    @GetMapping("list")
    public List<${className}> list() {
        return ${className?lower_case}Service.list();
    }

    /**
    * 获取${classDesc}详情
    *
    * @param id ${classDesc}id
    * @return
    */
    @GetMapping("{id}")
    public ${className} byId(@PathVariable("id") String id) {
        return ${className?lower_case}Service.byId(id);
    }
}

  • Mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="${daoPackagePath}.${className}Dao">

    <!--配置一个LRU缓存(二级缓存),每隔60秒进行刷新,存储512个对象-->
    <!--
        LRU     最近最少使用策略,移除最长时间不被使用的对象
        FIFO    先进先出策略
        SOFT    软引用策略,移除基于垃圾回收器状态和软引用规则的对象
        WEAK    弱引用策略,更积极地移除基于垃圾回收器状态和软引用规则的对象
    -->
    <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>

    <insert id="add" parameterType="${className?lower_case}">
        insert
        into springmvcdemo.futao_${className?lower_case} ()
        values ();
    </insert>

    <delete id="delete" parameterType="string">
        delete
        from springmvcdemo.futao_${className?lower_case}
        where id = ${r"#{id}"}
    </delete>

    <update id="update" parameterType="${className?lower_case}">
        update springmvcdemo.futao_${className?lower_case}
        set
        where id = ${r"#{id}"}
    </update>

    <select id="list">
        select *
        from springmvcdemo.futao_${className?lower_case}
    </select>

    <select id="byId" parameterType="string">
        select *
        from springmvcdemo.futao_${className?lower_case}
        where id = ${r"#{id}"}
    </select>
</mapper>

根据自己的项目情况创建模板即可,比如我就创建了6个

image.png

# 使用

直接执行 CodeGeneratorManager#main 方法即可


image.png
  • 效果


    image.png

    image.png

无解~
快乐~

源代码: https://github.com/FutaoSmile/springbootFramework

image.png

我在这里等你:


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容

  • 加入群聊 SpringBoot 核心技术①:373229384 (满)SpringBoot 核心技术②:58835...
    恒宇少年阅读 4,605评论 2 50
  • 一. Java基础部分.................................................
    wy_sure阅读 3,805评论 0 11
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • 1.abstract class 和interface 有什么区别? 抽象类可以有构造方法 接口不行 抽象类可以有...
    sunnysans阅读 846评论 0 1
  • 下午去了沃尔玛,遇到伊莎贝丝。她帮我找化妆品时,我偷拍了一张像,她工作时,又偷拍了一张。 最后呢,我们自拍。 哈哈...
    鲁长安阅读 123评论 0 0