mybatis-plus-自定义模板

自定义模板

  • 由于公司需求,好吧由于本人比较懒,不愿意写代码,估采用代码生成器的方式来解决我的痛点
  • 官方的代码生成器已经够好了但是还是不太符合我的要求,那咋能自己改吧改吧呗
  • 拥有 一键生成增、删、改、查、分页功能还有导入导出等…
  • 具体的模板参考GitHub
  • 如需特殊生成,联系我,免费给你加~~

GIT 地址

  • 自己下去吧

https://github.com/myliwenbo/Springboot/tree/master/springboot/springboot-mybatis-plus-generator

关注点

  • VelocityTemplateEngineEnhance 这个是具体的生成代码的,

生成的代码调用流程

  • MD mermaid图太难了…我直接贴图了
链接
调用
调用
调用
调用
Controller
Manager
Service
Dao
Mapper
XML
  • 具体代码的流程
    在这里插入图片描述

生成器

  • 由于官方的代码都放在了一个类中,个人强迫症都进行了规整处理
  • 我将官方的进行了拆分,看起来好学习一点,这个代码生成器,主要使用的是自定义模板比较多
/**
 * 生成器
 */
public class FinancingGenerator {

    /**
     * JDBC
     */
    private static final String URL = "";
    private static final String USER_NAME = "";
    private static final String PASSWORD = "";

    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        //这里去添加要生成的表
        FinancingGenerator.createStrategyConfig(mpg, "file_manage"); //策略
        FinancingGenerator.createDateSource(mpg); //数据源
        FinancingGenerator.createGlobalConfig(mpg); //全局配置
        FinancingGenerator.createTemplateConfig(mpg); //配置模板
        FinancingGenerator.createInjectionConfig(mpg);//自定义配置
        new TemplateConfigEnhance(mpg);//配置包信息
        mpg.execute();
    }


    /**
     * 数据源配置
     *
     * @return
     */
    public static void createDateSource(AutoGenerator mpg) {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(URL);
        dsc.setUsername(USER_NAME);
        dsc.setPassword(PASSWORD);
        dsc.setDriverName("com.mysql.jdbc.Driver");
        dsc.setDbType(DbType.MYSQL);
        dsc.setTypeConvert(new MySqlTypeConvert());
        mpg.setDataSource(dsc);
    }

    /**
     * 全局配置
     *
     * @return
     */
    public static void createGlobalConfig(AutoGenerator mpg) {
        GlobalConfig gc = new GlobalConfig();
        gc.setOutputDir(Templates.PATH); // 设置文件生成的目录
        gc.setFileOverride(true); // 是否覆盖原来的文件---- 这里需要注意
        gc.setAuthor(Templates.AUTHOR); // 设置作者~
        gc.setOpen(false); // 打开输出目录
        gc.setEnableCache(false); // XML 二级缓存
        gc.setActiveRecord(true); // 开启 activeRecord 模式
        gc.setBaseResultMap(true); // XML ResultMap
        gc.setBaseColumnList(true);// XML columList
        gc.setServiceName("I%sDao"); // 实体命名方式,就会形成 UserService ,如果使用自定义路径则该规则不会生效
        gc.setServiceImplName("%sDaoImpl"); // 实体命名方式,就会形成 UserServiceImpl ,如果使用自定义路径则该规则不会生效
        mpg.setGlobalConfig(gc);

    }

    /**
     * 策略配置,可指定需要生成哪些表或者排除哪些表,
     * 参考:https://mp.baomidou.com/config/generator-config.html#%E6%95%B0%E6%8D%AE%E5%BA%93%E8%A1%A8%E9%85%8D%E7%BD%AE
     *
     * @return
     */
    public static void createStrategyConfig(AutoGenerator mpg, String... include) { // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel); // 数据库映射到实体的命名策略
        // 公共父类
        // strategy.setSuperControllerClass("com.alijiajituan.controller.BaseController");
        strategy.setSuperEntityClass("cn....entity.BaseDo");
        strategy.setInclude(include); // 需要生成的表,和排除只能2选一
        //strategy.setExclude("bak_category_property", "user"); // 需要排除的表,除了排除的表其他的都生成
        // 自定义实体,公共字段
        strategy.setSuperEntityColumns("id", "is_valid", "op_time", "last_ver", "status", "type", "create_time", "app_id");
        strategy.setVersionFieldName("last_ver"); //乐观锁属性名称
        strategy.setLogicDeleteFieldName("is_valid");//逻辑删除属性名称
        strategy.setRestControllerStyle(true); // 生成 @RestController 控制器
        strategy.setEntityLombokModel(true); // 添加lombok模型
        strategy.setEntityColumnConstant(true); //是否生成字段常量
        strategy.setEntityBooleanColumnRemoveIsPrefix(true); // Boolean类型字段是否移除is前缀处理
        mpg.setStrategy(strategy);
    }

    /**
     * 模板配置,如果使用自定义模板和配置,需要将默认模板为NULL!!!!     *
     *
     * @return
     */
    public static void createTemplateConfig(AutoGenerator mpg) {
        TemplateConfig templateConfig = new TemplateConfig();
        // templateConfig.setService("/templates/service.java.vm"); //默认模板
        templateConfig.setEntity(null);// 模块如果设置 Null 将不生成该模块
        templateConfig.setService(null);// 模块如果设置 Null 将不生成该模块
        templateConfig.setServiceImpl(null);// 模块如果设置 Null 将不生成该模块
        templateConfig.setController(null);// 模块如果设置 Null 将不生成该模块
        templateConfig.setMapper(null);// 模块如果设置 Null 将不生成该模块
        templateConfig.setXml(null);// 模块如果设置 Null 将不生成该模块
        // 自定义模板文件,注意不要带上(.ftl)或者(.vm), 会根据使用的模板引擎自动识别
        // 自定义模板放在 src/main/resources/templates 目录下, 默认名称可以不配置,也可以自定义模板名称
        // 自定义模板配置,可以 copy 源码 mybatis-plus/src/main/resources/templates 下面内容修改
        mpg.setTemplate(templateConfig);
    }

    /**
     * 自定义配置
     */
    public static void createInjectionConfig(AutoGenerator mpg) {
        StrategyContext templatesList = StrategyContext.getTemplatesList();
        templatesList.contextMethod(new EntityTemplates());
        templatesList.contextMethod(new QueryReuqestEntityTemplates());
        templatesList.contextMethod(new SaveReuqestEntityTemplates());
        templatesList.contextMethod(new VOEntityTemplates());
        templatesList.contextMethod(new TDOEntityTemplates());
        templatesList.contextMethod(new XMLTemplates());
        templatesList.contextMethod(new MapperTemplates());
        templatesList.contextMethod(new DAOTemplates());
        templatesList.contextMethod(new DAOImplTemplates());
        templatesList.contextMethod(new ServiceTemplates());
        templatesList.contextMethod(new ManagerTemplates());
        templatesList.contextMethod(new ControllerTemplates());
        templatesList.getInjectionConfig(mpg);

    }
}

我写到这里我在想要不要把所有代码都贴出来…

  • 纠结了一下还是贴吧

自定义配置

  • 利用策略模式把代码进行拆分掉

定义接口

public interface Templates {


    /**
     * package
     */
    String PACKAGE = "vip.xjdai";

    /**
     * 当前项目路径
     */
    String PATH = System.getProperty("user.dir") + "/src/main/java";
   //这里是定义的作者
    String AUTHOR = "你最棒";



    /**
     * 生成的目录
     */
    String PACKAGE_FILE = "/vip/xjdai/";


    /**
     * 模板地址
     */
    String TEMPLATES = "/templates/";

    String ENTITY = PATH + PACKAGE_FILE + "/repository/entity/";
    String ENTITY_TEMPLATES = "/templates/entity.java.vm";

    String ENTITY_TDO = PATH + PACKAGE_FILE + "/repository/entity/";
    String ENTITY_TDO_TEMPLATES = "/templates/dto_entity.java.vm";


    String QUERY_ENTITY = PATH + PACKAGE_FILE + "/repository/vo/";
    String QUERY_ENTITY_TEMPLATES = "/templates/query_entity.java.vm";


    String SAVE_ENTITY = PATH + PACKAGE_FILE + "/repository/vo/";
    String SAVE_ENTITY_TEMPLATES = "/templates/save_entity.java.vm";


    String VO_ENTITY = PATH + PACKAGE_FILE + "/repository/vo/";
    String VO_TEMPLATES = "/templates/vo_entity.java.vm";


    String XML = System.getProperty("user.dir") + "/src/main/resources/mapper/";
    String XML_TEMPLATES = "/templates/xml.xml.vm";

    String MAPPER = PATH + PACKAGE_FILE + "/repository/mapper/";
    String MAPPER_TEMPLATES = "/templates/mapper.java.vm";


    String DAO = PATH + PACKAGE_FILE + "/repository/dao/";
    String DAO_TEMPLATES = "/templates/dao.java.vm";


    String DAO_IMPL = PATH + PACKAGE_FILE + "/repository/dao/impl/";
    String DAO_IMPL_TEMPLATES = "/templates/dao_impl.java.vm";


    String SERVICE = PATH + PACKAGE_FILE + "/service/";
    String SERVICE_TEMPLATES = "/templates/service.java.vm";


    String MANAGER = PATH + PACKAGE_FILE + "/manager/";
    String MANAGER_TEMPLATES = "/templates/manager.java.vm";

    String CONTROLLER = PATH + PACKAGE_FILE + "/controller/";
    String CONTROLLER_TEMPLATES = "/templates/controller.java.vm";

    FileOutConfig contextMethod();

    String SAVE_REQUEST_SUFFIX = "SaveRequest";
    String QUERY_REQUEST_SUFFIX = "QueryRequest";
    String VO_REQUEST_SUFFIX = "Vo";
    String DTO_REQUEST_SUFFIX = "Tdo";
    String MAPPER_SUFFIX = "Mapper";
    String DAO_SUFFIX = "Dao";
    String DAO_IMPL_SUFFIX = "DaoImpl";
    String SERVICE_SUFFIX = "Service";
    String MANAGER_SUFFIX = "Manager";
    String CONTROLLER_SUFFIX = "Controller";

}

定义上下文

  • 用于操作具体的生成类
public class StrategyContext {

    private List<FileOutConfig> focList;

    public void contextMethod(Templates templates) {
        FileOutConfig fileOutConfig = templates.contextMethod();
        focList.add(fileOutConfig);
    }

    public void getInjectionConfig(AutoGenerator mpg) {
        // 注入自定义配置,可以在 VM 中使用 cfg.abc
        InjectionConfig injectionConfig = new InjectionConfig() {
            @Override
            public void initMap() {
                this.setMap(new HashMap<>());
            }
        };
        injectionConfig.setFileOutConfigList(this.focList);
        mpg.setCfg(injectionConfig);
    }

    public static class StrategyContextOne {
        static StrategyContext instance = new StrategyContext();
    }

    public static StrategyContext getTemplatesList() {
        StrategyContext strategyContext = StrategyContextOne.instance;
        strategyContext.focList = Lists.newArrayList();
        return strategyContext;
    }

    public List<FileOutConfig> getFocList() {
        return focList;
    }
}

具体的模板我就不贴了

  • 都是差不多的
public class ControllerTemplates implements Templates {
    @Override
    public FileOutConfig contextMethod() {
    	// CONTROLLER_TEMPLATES 是模板的路径
        return new FileOutConfig(CONTROLLER_TEMPLATES) {
            @Override
            public String outputFile(TableInfo tableInfo) {
            // 是代码生成到那个文件夹下
                return CONTROLLER + tableInfo.getEntityName() + Templates.CONTROLLER_SUFFIX + StringPool.DOT_JAVA;
            }
        };
    }
}

代码生成具体的类

*主要就是将Map开放出去好定义自己的模板,看源码得知,这个Map是具体存放模板内的一些值

public abstract class VelocityTemplateEngineEnhance extends VelocityTemplateEngine {

    private Map<String, Object> objectMap;

    @Override
    public VelocityTemplateEngine init(ConfigBuilder configBuilder) {
        super.init(configBuilder);
        return this;
    }

    public void writer(Map<String, Object> objectMap, String templatePath, String outputFile) throws Exception {
        //将objectMap开放出去
        this.objectMap = objectMap;
        //这里调用增强方法
        enhanceMap(this.objectMap);
        //增强该方法
        super.writer(objectMap, templatePath, outputFile);

    }
    public Map<String, Object> getObjectMap() {
        return objectMap;
    }

    /**
     * 添加
     */
    public abstract void enhanceMap(Map<String, Object> objectMap);

}

Pack配置

  • 主要定义了一些在模板里面使用的一些属性,
  • 本来想把就是导包也加进去了,不想写了就那么用吧
/**
 * package配置
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class PackageConfigEnhance extends PackageConfig {

    private Map<String, String> packageInfo = Maps.newHashMap();
    private String saveEntity = "";
    private String queryEntity = "";
    private String voEntity = "";
    private String tdoEntity = "";
    private String customizeService = "";
    private String manager = "";

    public PackageConfigEnhance(Map<String, String> packageInfo) {
        this.packageInfo = packageInfo;
        init();
    }


    public Map<String, String> getPackageInfo() {
        packageInfo.put("Entity", joinPackage(this.getParent(), this.getEntity()));
        packageInfo.put("SaveEntity", joinPackage(this.getParent(), this.getSaveEntity()));
        packageInfo.put("QueryEntity", joinPackage(this.getParent(), this.getQueryEntity()));
        packageInfo.put("VoEntity", joinPackage(this.getParent(), this.getVoEntity()));
        packageInfo.put("DtoEntity", joinPackage(this.getParent(), this.getVoEntity()));
        packageInfo.put(ConstVal.MAPPER, joinPackage(this.getParent(), this.getMapper()));
        packageInfo.put(ConstVal.XML, joinPackage(this.getParent(), this.getXml()));
        packageInfo.put("Dao", joinPackage(this.getParent(), this.getService()));
        packageInfo.put("DaoImpl", joinPackage(this.getParent(), this.getServiceImpl()));
        packageInfo.put("Service", joinPackage(this.getParent(), this.getCustomizeService()));
        packageInfo.put("Manager", joinPackage(this.getParent(), this.getManager()));
        packageInfo.put("Controller", joinPackage(this.getParent(), this.getController()));
        return packageInfo;
    }

//    public void setClass() {
//        packageInfo.put("EntityClass", packageInfo.get());
//        packageInfo.put("SaveEntityClass",  packageInfo.get());
//        packageInfo.put("QueryEntityClass",  packageInfo.get());
//        packageInfo.put("VoEntityClass",  packageInfo.get());
//        packageInfo.put("TdoEntityClass",  packageInfo.get());
//        packageInfo.put(ConstVal.MAPPER, packageInfo.get());
//        packageInfo.put(ConstVal.XML,  packageInfo.get());
//        packageInfo.put("DaoClass",  packageInfo.get());
//        packageInfo.put("DaoImplClass",  packageInfo.get());
//        packageInfo.put("ServiceClass",  packageInfo.get());
//        packageInfo.put("ManagerClass",  packageInfo.get());
//        packageInfo.put("ControllerClass",  packageInfo.get());
//    }


    /**
     * 包配置
     *
     * @return
     */
    public void init() {
        this.setParent(Templates.PACKAGE);     //父节点
        this.setEntity("repository.entity");
        this.setQueryEntity("repository.vo");
        this.setSaveEntity("repository.vo");
        this.setTdoEntity("repository.vo");
        this.setVoEntity("repository.vo");
        this.setMapper("repository.mapper");
        this.setService("repository.dao");
        this.setServiceImpl("repository.dao.impl");
        this.setCustomizeService("service");
        this.setManager("manager");
        this.setController("controller");
    }


    /**
     * 连接父子包名
     *
     * @param parent     父包名
     * @param subPackage 子包名
     * @return 连接后的包名
     */
    private String joinPackage(String parent, String subPackage) {
        if (StringUtils.isEmpty(parent)) {
            return subPackage;
        }
        return parent + StringPool.DOT + subPackage;
    }
}


表的相关信息

  • 主要是一些表的相关信息以及实体类呀变量呀之类的东西
/**
 * 增强表
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class TableInfoConfigEnhance extends TableInfo {

    private String entity = "";
    private String entityHump = "";

    private String saveEntity = "";
    private String saveEntityHump = "";

    private String queryEntity = "";
    private String queryEntityHump = "";

    private String voEntity = "";
    private String voEntityHump = "";

    private String dtoEntity = "";
    private String dtoEntityHump = "";

    private String mapper= "";

    private String dao= "";
    private String daoHump= "";

    private String daoImpl = "";
    private String daoImplHump = "";

    private String service = "";
    private String serviceHump = "";

    private String manager = "";
    private String managerHump = "";

    public TableInfoConfigEnhance(TableInfo tableInfo) {
        BeanUtils.copyProperties(tableInfo, this);

        this.setEntity(tableInfo.getEntityName());
        this.setEntityHump(tableInfo.getEntityPath());

        this.setSaveEntity(tableInfo.getEntityName() + Templates.SAVE_REQUEST_SUFFIX);
        this.setSaveEntityHump(tableInfo.getEntityPath() + Templates.SAVE_REQUEST_SUFFIX);

        this.setQueryEntity(tableInfo.getEntityName() + Templates.QUERY_REQUEST_SUFFIX);
        this.setQueryEntityHump(tableInfo.getEntityPath() + Templates.QUERY_REQUEST_SUFFIX);

        this.setVoEntity(tableInfo.getEntityName() + Templates.VO_REQUEST_SUFFIX);
        this.setVoEntityHump(tableInfo.getEntityPath() + Templates.VO_REQUEST_SUFFIX);

        this.setDtoEntity(tableInfo.getEntityName() + Templates.DTO_REQUEST_SUFFIX);
        this.setDtoEntityHump(tableInfo.getEntityPath() + Templates.DTO_REQUEST_SUFFIX);

        this.setMapper(tableInfo.getEntityName() + Templates.MAPPER_SUFFIX);


        this.setDao(tableInfo.getEntityName() + Templates.DAO_SUFFIX);
        this.setDaoHump(tableInfo.getEntityPath() + Templates.DAO_SUFFIX);

        this.setDaoImpl(tableInfo.getEntityName() + Templates.DAO_IMPL_SUFFIX);
        this.setDaoImplHump(tableInfo.getEntityPath() + Templates.DAO_IMPL_SUFFIX);

        this.setService(tableInfo.getEntityName() + Templates.SERVICE_SUFFIX);
        this.setServiceHump(tableInfo.getEntityPath() + Templates.SERVICE_SUFFIX);

        this.setManager(tableInfo.getEntityName() + Templates.MANAGER_SUFFIX);
        this.setManagerHump(tableInfo.getEntityPath() + Templates.MANAGER_SUFFIX);

    }

}

将上面的两个config主要到Map中

  • 这里就是具体的将一些内容注入进去了
public class TemplateConfigEnhance {

    private AutoGenerator mpg;


    public TemplateConfigEnhance(AutoGenerator mpg) {
        this.mpg = mpg;
        createVelocityTemplateEngine();
    }

    private void createVelocityTemplateEngine() {
        TemplateConfigEnhance thiz = this;
        VelocityTemplateEngineEnhance velocityTemplateEngineEnhance = new VelocityTemplateEngineEnhance() {
            @Override
            public void enhanceMap(Map<String, Object> objectMap) {
                thiz.add(objectMap);
            }
        };
        mpg.setTemplateEngine(velocityTemplateEngineEnhance);//定义模板的自定义属性
    }

    /**
     *这里就是
     *
     * @param objectMap
     */
    @SuppressWarnings("unchecked")
    public void add(Map<String, Object> objectMap) {
        TableInfoConfigEnhance table = new TableInfoConfigEnhance((TableInfo) objectMap.get("table"));
        objectMap.put("package", new PackageConfigEnhance((Map<String, String>) objectMap.get("package")).getPackageInfo()); //替换package信息
        objectMap.put("table", table); //替换package信息

    }
}

源码查看

  • 先从源头开始看
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
		//从这里开始看
        mpg.execute();
    }

生成代码

  • 可以看到的是 templateEngine==null的时候才去采用模板那摸我们给他一个值就好了,也就是我们自定义的VelocityTemplateEngineEnhance对象
    /**
     * 生成代码
     */
    public void execute() {
        // 初始化配置
        if (null == config) {
            config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig);
            if (null != injectionConfig) {
                injectionConfig.setConfig(config);
            }
        }
        if (null == templateEngine) {
            // 为了兼容之前逻辑,采用 Velocity 引擎 【 默认 】
            templateEngine = new VelocityTemplateEngine();
        }
        // 模板引擎初始化执行文件输出
        templateEngine.init(this.pretreatmentConfigBuilder(config)).mkdirs().batchOutput().open();
    }

继续看

  • pretreatmentConfigBuilder()方法
//这段代码就是去装载模板的可以在${}里面所使用的一些属性
templateEngine.init(this.pretreatmentConfigBuilder(config));
  • batchOutput 这个方法就是具体的去输出
  • 主要关注writer() 这个抽象方法,是有子类去实现的
    public AbstractTemplateEngine batchOutput() {
        try {
            List<TableInfo> tableInfoList = getConfigBuilder().getTableInfoList();
            for (TableInfo tableInfo : tableInfoList) {
                Map<String, Object> objectMap = getObjectMap(tableInfo);
                Map<String, String> pathInfo = getConfigBuilder().getPathInfo();
                TemplateConfig template = getConfigBuilder().getTemplate();
                // 自定义内容
                InjectionConfig injectionConfig = getConfigBuilder().getInjectionConfig();
                if (null != injectionConfig) {
                    injectionConfig.initMap();
                    objectMap.put("cfg", injectionConfig.getMap());
                    List<FileOutConfig> focList = injectionConfig.getFileOutConfigList();
                    if (CollectionUtils.isNotEmpty(focList)) {
                        for (FileOutConfig foc : focList) {
                            if (isCreate(FileType.OTHER, foc.outputFile(tableInfo))) {
                            //主要就是这段代码,这段代码是抽象方法,由子类去实现,将ObjectMap和一些其他参数交给具体的实现类去处理
                                writer(objectMap, foc.getTemplatePath(), foc.outputFile(tableInfo));
                            }
                        }
                    }
                }
                // Mp.java
                String entityName = tableInfo.getEntityName();
                if (null != entityName && null != pathInfo.get(ConstVal.ENTITY_PATH)) {
                    String entityFile = String.format((pathInfo.get(ConstVal.ENTITY_PATH) + File.separator + "%s" + suffixJavaOrKt()), entityName);
                    if (isCreate(FileType.ENTITY, entityFile)) {
                        writer(objectMap, templateFilePath(template.getEntity(getConfigBuilder().getGlobalConfig().isKotlin())), entityFile);
                    }
                }
     			//... 还有很多自己看源码吧
            }
        } catch (Exception e) {
            logger.error("无法创建文件,请检查配置信息!", e);
        }
        return this;
    }
    
    public abstract void writer(Map<String, Object> objectMap, String templatePath, String outputFile) throws Exception;

  • 那就简单了那就找子类就可以了,发现有三个子类,其实就是对应的三个模板…
    在这里插入图片描述
  • 既然知道writer() 由子类实现,那就好办了直接实现 这个抽象类,然后替换掉就好了.
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值