随着项目节奏越来越快,为了减少把时间浪费在新建DTO 、VO 等地方,直接直接基于Mybatis-plus 这颗大树稍微扩展一下,在原来生成PO、 DAO、Service、ServiceImpl、Controller 基础新增。为了解决这个问题,网上找了一堆资料,发现都是老版本的,都是基于老的AutoGenerator ,里面配置非常臃肿,基于FastAutoGenerator 链式实现没有,通过Mybatis-Plus官方文档发现两个核心配置注入配置 (InjectionConfig),下面是官方文档解释
上面是官方文档的案例,存在两个问题,一个并没有other这个属性,第二个框生成的DTO实体会在系统parent目录下。本着要弄就要完美的执着,通过一下午翻阅mybatis-plus-generator 的源码,终于找到定位输出目录类配置CustomFile。下面直接上代码
POM依赖:
<!--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-->
构建代码:
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模版代码,已经调试过输出美化内容,有需要的可以直接复制
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>@Serialprivate 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模版代码
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>@Serialprivate 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模版:
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>@Serialprivate 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的模版也出一个教程。