Mybatis-plus-Generator 3.5.5 自定义模板支持 (DTO/VO 等) 配置

随着项目节奏越来越快,为了减少把时间浪费在新建DTO 、VO 等地方,直接直接基于Mybatis-plus 这颗大树稍微扩展一下,在原来生成PO、 DAO、Service、ServiceImpl、Controller 基础新增。为了解决这个问题,网上找了一堆资料,发现都是老版本的,都是基于老的AutoGenerator ,里面配置非常臃肿,基于FastAutoGenerator 链式实现没有,通过Mybatis-Plus官方文档发现两个核心配置注入配置 (InjectionConfig),下面是官方文档解释

上面是官方文档的案例,存在两个问题,一个并没有other这个属性,第二个框生成的DTO实体会在系统parent目录下。本着要弄就要完美的执着,通过一下午翻阅mybatis-plus-generator 的源码,终于找到定位输出目录类配置CustomFile。下面直接上代码

POM依赖:

java 复制代码
  <!--gen code start-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.5</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.33</version>
        </dependency>
        <!--gen code ebd-->

构建代码:

java 复制代码
 FastAutoGenerator.create("jdbc:mysql://xxxx:63306/diboot",
                        "diboot", "xxx")
                //全局配置
                .globalConfig(builder -> {
                    builder.outputDir(Paths.get(System.getProperty("user.dir")) + "/src/main/java")
                            .author("xxx")
                            .build();
                })
                //包配置
                .packageConfig(builder -> {
                    builder.parent("com.example.demo")
                            .entity("model.po")
                            .service("biz")
                            .serviceImpl("biz")
                            .mapper("dao")
                           // .xml("dao.xml")
                            .controller("api.back")
                            .build();
                })
                //表策略配置
                .strategyConfig(builder -> {
                    builder.enableSkipView()
                            .disableSqlFilter()
                            .addTablePrefix("biz_", "sys_")
                            .addInclude("biz_article")
                            .build();
                })
                //entity策略
                .strategyConfig(builder -> {
                    builder.entityBuilder().idType(IdType.ASSIGN_ID)
                            .superClass(BaseModel.class)
                            .disableSerialVersionUID()
                            .enableRemoveIsPrefix()
                            .enableLombok()
                            .addIgnoreColumns("is_deleted", "create_time", "update_time")
                            .build();
                })
                //controller 策略
                .strategyConfig(builder -> {
                    builder.controllerBuilder()
                            .enableHyphenStyle()
                            .enableRestStyle()
                            .formatFileName("%sController")
                            .build();
                })
                //Service 策略
                .strategyConfig(builder -> {
                    builder.serviceBuilder()
                            .superServiceClass(IService.class)
                            .superServiceImplClass(ServiceImpl.class)
                            .formatServiceFileName("%sService")
                            .formatServiceImplFileName("%sServiceImpl")
                            .build();
                })
                //mapper 策略
                .strategyConfig(builder -> {
                    builder.mapperBuilder()
                            .superClass(BaseMapper.class)
                            .mapperAnnotation(Repository.class)
                            .enableBaseResultMap()
                            .enableBaseColumnList()
                            .formatMapperFileName("%sMapper")
                            .build();
                })
                //注入自定义配置
                .injectionConfig(builder -> {
                    /**自定义生成模板参数,在ftl模版里取值使用**/
                    Map<String,Object> data = new HashMap<>();
                    data.put("entityBuilderModel", true);
                    data.put("chainModel", true);
                    data.put("swagger",true);
                    data.put("entitySerialVersionUID",true);
                    data.put("entityLombokModel", true);
                    builder.customMap(data);
                    List<CustomFile> customFiles = new ArrayList();
                    /**DTO实体**/
                    CustomFile updateInputFile = new CustomFile.Builder()
                            .fileName("UpdateInput.java")//生成java文件名称,要和ftl模版里的文件名保持一致
                            .templatePath("/templates/UpdateInput.java.ftl")//实体模板位置
                            .packageName("model.dto")//生成文件包名
                            .build();
                    customFiles.add(updateInputFile);
                    CustomFile addInputFile = new CustomFile.Builder()
                            .fileName("AddInput.java")
                            .templatePath("/templates/AddInput.java.ftl")
                            .packageName("model.dto").build();
                    /**Vo实体**/
                    CustomFile customFileVO = new CustomFile.Builder()
                            .fileName("VO.java")
                            .templatePath("/templates/VO.java.ftl")
                            .packageName("model.vo").build();
                    customFiles.add(customFileVO);

                    customFiles.add(addInputFile);
                    builder.customFile(customFiles);
                })
                .templateEngine(new FreemarkerTemplateEngine())
                .execute();

DTO ftl模版,为了测地解决不需要修改生成实体,根据数据库字段注释生成实体字段注释,根据数据库字段是否允许为空 加上NotBlank 或者 NotNull 以及 @ApiModelProperty 的required 的条件

新增DTO模版代码,已经调试过输出美化内容,有需要的可以直接复制

java 复制代码
package ${package.Parent}.model.dto;
<#if swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
    <#if chainModel>
import lombok.experimental.Accessors;
    </#if>
</#if>
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.io.Serial;
import java.time.*;
/**
* <p>
    * ${table.comment!}
    * </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if swagger>@ApiModel(description = "${table.comment!}")
</#if>
public class ${entity}AddInput implements Serializable {
<#if entitySerialVersionUID>
    @Serial
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if !field.keyFlag && field.propertyName!="tenantId"&&field.propertyName!="museumId"><#--不是主键、不是租户ID 输出-->
    <#if field.comment!?length gt 0>
        <#if field.metaInfo.nullable>

     @ApiModelProperty(value="${field.comment}")
        <#else>

     @ApiModelProperty(value="${field.comment}",required = true)
            <#if field.propertyType=="string">
     @NotBlank(message = "${field.comment}不能为空")
            <#else>
     @NotNull(message = "${field.comment}不能为空")
            </#if>
        </#if>
    </#if>
     private ${field.propertyType} ${field.propertyName};
    </#if>
</#list>
<#------------  END 字段循环遍历  ---------->
}

生成效果图:自动加上参数校验

修改DTO模版代码

java 复制代码
package ${package.Parent}.model.dto;
<#if swagger>
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
import lombok.Getter;
import lombok.Setter;
    <#if chainModel>
import lombok.experimental.Accessors;
    </#if>
</#if>
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.io.Serial;
import java.time.*;
/**
* <p>
    * ${table.comment!}
    * </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if swagger>@ApiModel(description = "${table.comment!}")
</#if>
public class ${entity}UpdateInput implements Serializable {
<#if entitySerialVersionUID>
    @Serial
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if field.propertyName!="tenantId"&&field.propertyName!="museumId"><#--不是租户ID 输出-->
    <#if field.comment!?length gt 0>
        <#if field.metaInfo.nullable>

     @ApiModelProperty(value="${field.comment}")
        <#else>

     @ApiModelProperty(value="${field.comment}",required = true)
            <#if field.propertyType=="string">
     @NotBlank(message = "${field.comment}不能为空")
            <#else>
     @NotNull(message = "${field.comment}不能为空")
            </#if>
        </#if>
    </#if>
     private ${field.propertyType} ${field.propertyName};
    </#if>
</#list>
<#------------  END 字段循环遍历  ---------->
}

生成效果图:

VO模版:

java 复制代码
package ${package.Parent}.model.vo;
<#if swagger>
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
</#if>
<#if entityLombokModel>
    import lombok.Getter;
    import lombok.Setter;
    <#if chainModel>
        import lombok.experimental.Accessors;
    </#if>
</#if>
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.io.Serializable;
import java.io.Serial;
import java.time.*;
/**
* <p>
    * ${table.comment!}
    * </p>
*
* @author ${author}
* @since ${date}
*/
<#if entityLombokModel>
@Getter
@Setter
    <#if chainModel>
@Accessors(chain = true)
    </#if>
</#if>
<#if swagger>@ApiModel(description = "${table.comment!}")
</#if>
public class ${entity}VO implements Serializable {
<#if entitySerialVersionUID>
    @Serial
    private static final long serialVersionUID = 1L;
</#if>
<#-- ----------  BEGIN 字段循环遍历  ---------->
<#list table.fields as field>
    <#if field.propertyName!="tenantId"&&field.propertyName!="museumId"><#--不是租户ID 输出-->
        <#if field.comment!?length gt 0>

        @ApiModelProperty(value="${field.comment}")
        </#if>
        private ${field.propertyType} ${field.propertyName};
    </#if>
</#list>
<#------------  END 字段循环遍历  ---------->
}

效果图:

项目结构截图:

能看到这里应该有个大概的了解了,既然能生成自定义DTO 和 VO,那我们完全也可以覆盖之前的默认Service,将生成好的 DTO 和VO 放入 Service 模版里,然后将Service模版里 放入Controller模版里,那我们一次性就可以把 PO VO DTO 以及 Service 里增删改查 全部实现,并放到 Controller接口 ,那常用的业务基本上就可以使用了,接口上加上一些权限 注解和日志注解。如果有些特殊的逻辑再生成的service调整即可。后续有时间,把Service的模版也出一个教程。

相关推荐
weixin_438335404 小时前
springboot多实例部署时,@Scheduled注释的方法重复执行
springboot
天上掉下来个程小白11 小时前
案例-14.文件上传-简介
数据库·spring boot·后端·mybatis·状态模式
sunnyday042619 小时前
MyBatis XML映射文件中的批量插入和更新
xml·java·mysql·mybatis
LUCIAZZZ2 天前
SkyWalking快速入门
java·后端·spring·spring cloud·微服务·springboot·skywalking
剑走偏锋o.O2 天前
Java四大框架深度剖析:MyBatis、Spring、SpringMVC与SpringBoot
java·spring boot·spring·mybatis
风月歌2 天前
基于springboot校园健康系统的设计与实现(源码+文档)
java·spring boot·后端·mysql·毕业设计·mybatis·源码
剑走偏锋o.O2 天前
MyBatis框架详解与核心配置解读
java·学习·mybatis
ONEPEICE-ing3 天前
快速入门Springboot+vue——MybatisPlus多表查询及分页查询
前端·vue.js·spring boot·mybatis
wolf犭良3 天前
14、《SpringBoot+MyBatis集成(2)——进阶配置XML与注解的灵活运用》
xml·spring boot·mybatis