一、前言
在编写代码时我们会编写大量与业务无关的代码,比如Contoller,Service,Entity以及一些增删改查接口的定义,这些代码基本都是固定的模板,手动编写浪费大量时间,今天介绍一下Mybatis-Plus代码生成器来简化代码的开发,减少重复代码的编写。
该代码生成器地址:https://gitee.com/a1091758887/AutoGenerateCode
二、引入Jar包
<dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
三、代码
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
/**
* @Author fanQie
* @Date 2022/08/29 12:00
*/
public class AutoGenerator {
//数据库配置
private static final String url = "jdbc:mysql://127.0.0.1:3306/mybatis-plus";
private static final String username = "root";
private static final String password = "123456";
//表名
private static final String tables = "alarm_record,car_member_info,car_moving_code";
//生成路径
private static final String generatePath = "D://template";
public static void main(String[] args) {
FastAutoGenerator.create(url, username, password)
.globalConfig(builder -> {
builder.author("fanQie") // 设置作者
.fileOverride() // 覆盖已生成文件
.outputDir(generatePath); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent(""); // 设置父包名(我这边为空,因为我的项目目录结构不统一,所以在代码生成模板中自己定义了包名,如果你的目录结构比较清晰可以在这里设置父目录)
})
.strategyConfig(builder -> {
builder. addInclude(tables) // 设置需要生成的表名
//Entity 策略配置
.entityBuilder()
.enableLombok() //开启lombok
.enableTableFieldAnnotation();//开启生成实体时生成字段注解 默认值:false(加上这个配置生成的实体字段会有 @TableField()注解)
})
.templateEngine(new EnhanceFreemarkerTemplateEngine()) //自定义模板
.execute();
}
/**
* 代码生成器支持自定义模版
*/
public final static class EnhanceFreemarkerTemplateEngine extends FreemarkerTemplateEngine {
@Override
protected void outputCustomFile(@NotNull Map<String, String> customFile, @NotNull TableInfo tableInfo, @NotNull Map<String, Object> objectMap) {
String entityName = tableInfo.getEntityName();
String otherPath = this.getPathInfo(OutputFile.other);
//自定义模板参数(定义的这些参数可以在我们的Freemark模板中使用&{}语法取到该值,比如 &{requestMapping})
objectMap.put("requestMapping", StringUtils.firstToLowerCase(entityName));
objectMap.put("entityPackage", "com.ly.smallscene.database.entity.ticketsmallscene");
objectMap.put("controllerPackage", "com.ly.smallscene.resourceadmin.modules." + tableInfo.getEntityName().toLowerCase());
objectMap.put("facadePackage", "com.ly.smallscene.common.modules." + tableInfo.getEntityName().toLowerCase() + ".facade");
objectMap.put("facadeImplPackage", "com.ly.smallscene.common.modules." + tableInfo.getEntityName().toLowerCase() + ".facade.impl");
objectMap.put("servicePackage", "com.ly.smallscene.common.modules." + tableInfo.getEntityName().toLowerCase() + ".sevice");
objectMap.put("servicePackageImpl", "com.ly.smallscene.common.modules." + tableInfo.getEntityName().toLowerCase() + ".sevice.impl");
objectMap.put("mapperPackage", "com.ly.smallscene.database.mapper.ticketsmallscene");
objectMap.put("requestPackage", "com.ly.smallscene.common.modules." + tableInfo.getEntityName().toLowerCase() + ".request");
objectMap.put("responsePackage", "com.ly.smallscene.common.modules." + tableInfo.getEntityName().toLowerCase() + ".response");
//设置要生成的文件名以及FreeMark模板文件路径
customFile = new HashMap<>();
customFile.put(entityName + StringPool.DOT_JAVA, "/template/entity.java.ftl");
customFile.put(entityName + "Controller" + StringPool.DOT_JAVA, "/template/controller.java.ftl");
customFile.put(entityName + "Facade" + StringPool.DOT_JAVA, "/template/facade.java.ftl");
customFile.put(entityName + "FacadeImpl" + StringPool.DOT_JAVA, "/template/facadeImpl.java.ftl");
customFile.put(entityName + "Service" + StringPool.DOT_JAVA, "/template/service.java.ftl");
customFile.put(entityName + "ServiceImpl" + StringPool.DOT_JAVA, "/template/serviceImpl.java.ftl");
customFile.put(entityName + "Mapper" + StringPool.DOT_JAVA, "/template/mapper.java.ftl");
customFile.put(entityName + "Mapper" + StringPool.DOT_XML, "/template/mapper.xml.ftl");
customFile.put(entityName + "SaveRequest" + StringPool.DOT_JAVA, "/template/saveRequest.java.ftl");
customFile.put(entityName + "DeleteRequest" + StringPool.DOT_JAVA, "/template/deleteRequest.java.ftl");
customFile.put(entityName + "UpdateRequest" + StringPool.DOT_JAVA, "/template/updateRequest.java.ftl");
customFile.put(entityName + "DetailRequest" + StringPool.DOT_JAVA, "/template/detailRequest.java.ftl");
customFile.put(entityName + "PageListRequest" + StringPool.DOT_JAVA, "/template/pageListRequest.java.ftl");
customFile.put(entityName + "DetailResponse" + StringPool.DOT_JAVA, "/template/detailResponse.java.ftl");
customFile.put(entityName + "PageListResponse" + StringPool.DOT_JAVA, "/template/pageListResponse.java.ftl");
customFile.forEach((key, value) -> {
//拼接生成文件的目录
String fileName = otherPath + "/" + entityName + "/" +key;
//核心方法来生成模板
this.outputFile(new File(fileName), objectMap, value, this.getConfigBuilder().getInjectionConfig().isFileOverride());
});
}
}
}
FreeMark模板
1.模板目录
2.controller.java.ftl代码
package ${controllerPackage};
import ${entityPackage}.${entity};
import ${servicePackage}.${table.serviceName};
import com.ly.smallscene.common.base.entity.BaseResponseEntity;
import com.ly.smallscene.common.base.tool.PageInfo;
import ${requestPackage}.${entity}SaveRequest;
import ${requestPackage}.${entity}DeleteRequest;
import ${requestPackage}.${entity}UpdateRequest;
import ${requestPackage}.${entity}DetailRequest;
import ${requestPackage}.${entity}PageListRequest;
import ${responsePackage}.${entity}DetailResponse;
import ${responsePackage}.${entity}PageListResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
/**
* @author ${author}
* @since ${date}
*/
@Tag(name = "${(table.comment!?html?replace('\r\n','') )!}")
@RestController
@RequestMapping("${requestMapping}")
public class ${table.controllerName} {
@Autowired
private ${entity}Facade ${entity?uncap_first}Facade;
@Operation(summary = "新增")
@PostMapping(value = "/save")
public BaseResponseEntity save(@RequestBody @Valid ${entity}SaveRequest request) {
${entity?uncap_first}Facade.save(request);
return new BaseResponseEntity();
}
@Operation(summary = "删除")
@PostMapping(value = "/delete")
public BaseResponseEntity delete(@RequestBody @Valid ${entity}DeleteRequest request) {
${entity?uncap_first}Facade.delete(request);
return new BaseResponseEntity();
}
@Operation(summary = "更新")
@PostMapping(value = "/update")
public BaseResponseEntity update(@RequestBody @Valid ${entity}UpdateRequest request) {
${entity?uncap_first}Facade.update(request);
return new BaseResponseEntity();
}
@Operation(summary = "详情")
@PostMapping(value = "/detail")
public BaseResponseEntity detail(@RequestBody @Valid ${entity}DetailRequest request) {
${entity}DetailResponse response = ${entity?uncap_first}Facade.detail(request);
return new BaseResponseEntity(response);
}
@Operation(summary = "分页列表")
@PostMapping(value = "/pageList")
public BaseResponseEntity pageList(@RequestBody ${entity}PageListRequest request) {
PageInfo<${entity}PageListResponse> response = ${entity?uncap_first}Facade.pageList(request);
return new BaseResponseEntity(response);
}
}
3.entity.java.ftl代码
package ${entityPackage};
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* ${table.comment!}
* @author ${author}
* @since ${date}
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("${table.name}")
public class ${entity} implements Serializable {
private static final long serialVersionUID = 1L;
<#-- ---------- BEGIN 字段循环遍历 ---------->
<#list table.fields as field>
<#if field.keyFlag>
<#assign keyPropertyName="${field.propertyName}"/>
</#if>
<#if field.comment!?length gt 0>
/**
* ${field.comment}
*/
</#if>
<#if field.keyFlag>
<#-- 主键 -->
<#if field.keyIdentityFlag>
@TableId(value = "${field.name}", type = IdType.AUTO)
<#elseif idType??>
@TableId(value = "${field.name}", type = IdType.${idType})
<#elseif field.convert>
@TableId("${field.name}")
</#if>
<#-- 普通字段 -->
<#elseif field.fill??>
<#-- ----- 存在字段填充设置 ----->
<#if field.convert>
@TableField(value = "${field.name}", fill = FieldFill.${field.fill})
<#else>
@TableField(fill = FieldFill.${field.fill})
</#if>
<#elseif field.convert>
@TableField("${field.name}")
</#if>
private ${field.propertyType} ${field.propertyName};
</#list>
}
总结
- MyBatis-Plus代码生成有很多配置可以参考官网说明 Mybait-Plus官网。
- 我自己定义了许多模板,大家可以根据自己的项目实际场景定义属于自己的模板,我的代码生成器地址:https://gitee.com/a1091758887/AutoGenerateCode,大家可以参考。
- 想要在模板中定义自己的参数可以在outputCustomFile()方法objectMap中定义,然后在模板中使用${}获取。