在现在的开发中,对我们开发人员而言,最重要的就是开发效率,本次讲解的就是使用mybatis-plus来完成自定义代码生成的教程。
我们在对一个框架进行自定义拓展的话,第一种方式就是阅读官方文档,如果官方文档没有给出相关的解决方案,我们可能还需要通过查看源码来完成我们想要实现的功能,我们都知道mybatis-plus实现了代码自动生成器,我们通过官方文档就可以查看,我们知道通过mybatis-plus自带生成的代码中可能不满足我们的需求,比如说我们希望生成的controller, service中包含最基本的crud方法。此时,我们就需要自己来自定义模版来完成了。
首先,我们在阅读mybatis-plus源码时,我们需要了解这个框架的整体架构,通过查看其目录架构如下:
我们找到mybatis-plus-generator包,通过名字我们知道这就是我们要找的自动代码生成的jar包;查看其文件目录如下:
我们首先查看其有一个templates文件夹,这个文件夹所放置的便是相关模块代码自动生成的模版,我们通过engine文件夹发现,其有4个engine引擎类,初步猜测其为加载templates文件夹符合自己资深引擎的模版文件,然后生成相关的类。
通过templates下的文件后缀我们发现:
1. .btl为后缀的文件对应的是BeetlTemplateEngine引擎类;
2. .ftl为后缀的文件对应的是FreemarkerTemplateEngine引擎类;
3. .vm为后缀的文件为VelocityTemplateEngine引擎类;
其中还有一个AbstractTemplateEngine类,为一个抽象类,上面的类都继承该抽象类;AbstractTemplateEngine类实现了大部分的代码生成处理流操作方法,核心源码如下:
/**
* 输出 java xml 文件
*/
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))) {
writer(objectMap, foc.getTemplatePath(), foc.outputFile(tableInfo));
}
}
}
}
// 生成entity实体类
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方法交由具体引擎类实现(writer方法为抽象方法)
writer(objectMap, templateFilePath(template.getEntity(getConfigBuilder().getGlobalConfig().isKotlin())), entityFile);
}
}
// 生成mapper接口类
if (null != tableInfo.getMapperName() && null != pathInfo.get(ConstVal.MAPPER_PATH)) {
String mapperFile = String.format((pathInfo.get(ConstVal.MAPPER_PATH) + File.separator + tableInfo.getMapperName() + suffixJavaOrKt()), entityName);
if (isCreate(FileType.MAPPER, mapperFile)) {
// writer方法交由具体引擎类实现(writer方法为抽象方法)
writer(objectMap, templateFilePath(template.getMapper()), mapperFile);
}
}
// 生成mapper.xml文件
if (null != tableInfo.getXmlName() && null != pathInfo.get(ConstVal.XML_PATH)) {
String xmlFile = String.format((pathInfo.get(ConstVal.XML_PATH) + File.separator + tableInfo.getXmlName() + ConstVal.XML_SUFFIX), entityName);
if (isCreate(FileType.XML, xmlFile)) {
// writer方法交由具体引擎类实现(writer方法为抽象方法)
writer(objectMap, templateFilePath(template.getXml()), xmlFile);
}
}
// 生成service接口类
if (null != tableInfo.getServiceName() && null != pathInfo.get(ConstVal.SERVICE_PATH)) {
String serviceFile = String.format((pathInfo.get(ConstVal.SERVICE_PATH) + File.separator + tableInfo.getServiceName() + suffixJavaOrKt()), entityName);
if (isCreate(FileType.SERVICE, serviceFile)) {
// writer方法交由具体引擎类实现(writer方法为抽象方法)
writer(objectMap, templateFilePath(template.getService()), serviceFile);
}
}
// 生成service接口实现类
if (null != tableInfo.getServiceImplName() && null != pathInfo.get(ConstVal.SERVICE_IMPL_PATH)) {
String implFile = String.format((pathInfo.get(ConstVal.SERVICE_IMPL_PATH) + File.separator + tableInfo.getServiceImplName() + suffixJavaOrKt()), entityName);
if (isCreate(FileType.SERVICE_IMPL, implFile)) {
// writer方法交由具体引擎类实现(writer方法为抽象方法)
writer(objectMap, templateFilePath(template.getServiceImpl()), implFile);
}
}
// 生成controller类
if (null != tableInfo.getControllerName() && null != pathInfo.get(ConstVal.CONTROLLER_PATH)) {
String controllerFile = String.format((pathInfo.get(ConstVal.CONTROLLER_PATH) + File.separator + tableInfo.getControllerName() + suffixJavaOrKt()), entityName);
if (isCreate(FileType.CONTROLLER, controllerFile)) {
// writer方法交由具体引擎类实现(writer方法为抽象方法)
writer(objectMap, templateFilePath(template.getController()), controllerFile);
}
}
}
} catch (Exception e) {
logger.error("无法创建文件,请检查配置信息!", e);
}
return this;
}
AbstractTemplateEngine类中包含2个抽象方法:
/**
* 将模板转化成为文件
*
* @param objectMap 渲染对象 MAP 信息
* @param templatePath 模板文件
* @param outputFile 文件生成的目录
*/
public abstract void writer(Map<String, Object> objectMap, String templatePath, String outputFile) throws Exception;
/**
* 模板真实文件路径
*
* @param filePath 文件路径
* @return ignore
*/
public abstract String templateFilePath(String filePath);
mybatis-plus采用的默认引擎为VelocityTemplateEngine类(后面会通过代码的方式告知为何为默认的模版引擎), 我们查看查看该类实现的2个抽象方法:
/**
* 初始化模版引擎,设置需要加载的模版文件位置,编码等
*/
@Override
public VelocityTemplateEngine init(ConfigBuilder configBuilder) {
super.init(configBuilder);
if (null == velocityEngine) {
Properties p = new Properties();
p.setProperty(ConstVal.VM_LOAD_PATH_KEY, ConstVal.VM_LOAD_PATH_VALUE);
p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, StringPool.EMPTY);
p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
p.setProperty("file.resource.loader.unicode", StringPool.TRUE);
velocityEngine = new VelocityEngine(p);
}
return this;
}
/**
* 写出模版文件
*/
@Override
public void writer(Map<String, Object> objectMap, String templatePath, String outputFile) throws Exception {
if (StringUtils.isEmpty(templatePath)) {
return;
}
Template template = velocityEngine.getTemplate(templatePath, ConstVal.UTF8);
try (FileOutputStream fos = new FileOutputStream(outputFile);
OutputStreamWriter ow = new OutputStreamWriter(fos, ConstVal.UTF8);
BufferedWriter writer = new BufferedWriter(ow)) {
template.merge(new VelocityContext(objectMap), writer);
}
logger.debug("模板:" + templatePath + "; 文件:" + outputFile);
}
/**
* 获取文件路径 + .vm后缀,比如filePath: TestController.java => TestController.java.vm
*/
@Override
public String templateFilePath(String filePath) {
if (null == filePath || filePath.contains(DOT_VM)) {
return filePath;
}
return filePath + DOT_VM;
}
在这里我们大致了解了模版引擎的执行流程,通过AbstractTemplateEngine类中的batchOutput()方法,我们发现了该类中的核心数据来源是tableInfoList集合,我们查看batchOutput方法的调用者为AutoGenerator类。
我们查看AutoGenerator类中的核心源码:
/**
* 配置信息
*/
protected ConfigBuilder config;
/**
* 注入配置
*/
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
protected InjectionConfig injectionConfig;
/**
* 数据源配置
*/
private DataSourceConfig dataSource;
/**
* 数据库表配置
*/
private StrategyConfig strategy;
/**
* 包 相关配置
*/
private PackageConfig packageInfo;
/**
* 模板 相关配置
*/
private TemplateConfig template;
/**
* 全局 相关配置
*/
private GlobalConfig globalConfig;
/**
* 模板引擎
*/
private AbstractTemplateEngine templateEngine;
/**
* 生成代码
*/
public void execute() {
logger.debug("==========================准备生成文件...==========================");
// 初始化配置
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();
logger.debug("==========================文件生成完成!!!==========================");
}
/**
* 开放表信息、预留子类重写
*
* @param config 配置信息
* @return ignore
*/
protected List<TableInfo> getAllTableInfoList(ConfigBuilder config) {
return config.getTableInfoList();
}
我们发现AutoGenerator中的execute()方法为带代码自动生成的核心,其中做了一系列的初始化配置,包括包信息,数据源,定义策略,指定模版,以及全局配置等,在其下我们发现它做了模版引擎是否为空的校验,如果模版引擎为空,则采用VelocityTemplateEngine作为其模版引擎,然后调用batchOutput()方法来完成相关类的实现。OK,大致的执行流程我们是知道了,我们了解到mybatis-plus默认的模版引擎为VelocityTemplateEngine, 模版引擎会读取模版文件然后写出到指定的文件目录,所以我们了解到只需让模版引擎读取我们自己自定义的模版文件来生成就达到了目的,此时,我们再次回到AbstractTemplateEngine类中的抽象方法writer():
/**
* 将模板转化成为文件
*
* @param objectMap 渲染对象 MAP 信息
* @param templatePath 模板文件
* @param outputFile 文件生成的目录
*/
public abstract void writer(Map<String, Object> objectMap, String templatePath, String outputFile) throws Exception;
我们发现,当我们调用writer方法写出模版时,需要传入模版文件的路径templatePath, 而templatePath又是被调用于batchOutput()方法中:我们查看batchOutput()方法中的部分源码:
/**
* 输出 java xml 文件
*/
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();
...
// 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)) {
// templateFilePath来自于TemplateConfig类
writer(objectMap, templateFilePath(template.getEntity(getConfigBuilder().getGlobalConfig().isKotlin())), entityFile);
}
}
...
此时我们知道了,templateFilePath来自于TemplateConfig类,而templateFilePath()方法是由我们具体的模版引擎类重写的,此时我们仅查看VelocityTemplateEngine模版引擎(其他的模版引擎暂未研究,但是原理大致相同)的templateFilePath()方法:
/**
* 给模版文件路径添加.vm后缀
*/
@Override
public String templateFilePath(String filePath) {
if (null == filePath || filePath.contains(DOT_VM)) {
return filePath;
}
return filePath + DOT_VM;
}
这里仅仅只是对模版文件的路径添加.vm后缀。
OK,我们知道了模版文件的配置类是在TemplateConfig类,我们稍微查看一下他的源码:
/**
* 模板路径配置项
*
* @author tzg hubin
* @since 2017-06-17
*/
@Data
@Accessors(chain = true)
public class TemplateConfig {
/**
* entity => "/templates/entity.java"
*/
@Getter(AccessLevel.NONE)
private String entity = ConstVal.TEMPLATE_ENTITY_JAVA;
/**
* entityKt => "/templates/entity.kt"
*/
private String entityKt = ConstVal.TEMPLATE_ENTITY_KT;
/**
* service => "/templates/service.java"
*/
private String service = ConstVal.TEMPLATE_SERVICE;
/**
* serviceImpl => "/templates/serviceImpl.java"
*/
private String serviceImpl = ConstVal.TEMPLATE_SERVICE_IMPL;
/**
* mapper => "/templates/mapper.java"
*/
private String mapper = ConstVal.TEMPLATE_MAPPER;
/**
* xml => "/templates/mapper.xml"
*/
private String xml = ConstVal.TEMPLATE_XML;
/**
* controller => "/templates/controller.java"
*/
private String controller = ConstVal.TEMPLATE_CONTROLLER;
/**
* 是否为kotlin语法模版
* @param kotlin
* @return
*/
public String getEntity(boolean kotlin) {
return kotlin ? entityKt : entity;
}
}
TemplateConfig类就是一个实体类,我们只需要调用setter()方法覆盖掉它默认的模版文件即可,还记得AutoGenerator类吗,这个类调用execute()方法来完成代码的自动生成,它其中包含了很多的属性:
/**
* 配置信息
*/
protected ConfigBuilder config;
/**
* 注入配置
*/
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
protected InjectionConfig injectionConfig;
/**
* 数据源配置
*/
private DataSourceConfig dataSource;
/**
* 数据库表配置
*/
private StrategyConfig strategy;
/**
* 包 相关配置
*/
private PackageConfig packageInfo;
/**
* 模板 相关配置
*/
private TemplateConfig template;
/**
* 全局 相关配置
*/
private GlobalConfig globalConfig;
/**
* 模板引擎
*/
private AbstractTemplateEngine templateEngine;
其中也就包含了TemplateConfig类,其他的相关配置在这里又不累述了,有兴趣的同学可以自己去看一下他们的相关源码,都蛮简单清晰的。现在我们就来实现我们自定义的代码生成吧。
首先,我们采用mybatis-plus默认的模版引擎,因此,我们要先引入velocity相关的pom:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.1</version>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
我们定义一个GeneratorCodeUtil类:
/**
* 自动生成pojo,mapper, service, controller
*/
public class GeneratorCodeUtil {
/**
* 请自定义自己的db url
*/
private static final String DB_URL = "jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&useSSL=false";
/**
* 请自定义自己的username
*/
private static final String USERNAME = "root";
/**
* 请自定义自己的password
*/
private static final String PASSWORD = "123456";
private static final String DRIVER_NAME = "com.mysql.jdbc.Driver";
/**
* 请自定义自己的包名,后续的代码生成会在这个包下
*/
private static final String PACKAGE_NAME = "com.xiaofeifei.testmybatisplus";
/**
* 请自定义自己的模块名(可以理解为项目名称)
*/
private static final String MODULE_NAME = "test-mybatis-plus";
public static void main(String[] args) throws IOException {
System.out.println("--------------------开始自动生成相关的类----------------------");
System.out.println("args = " + new File("").getAbsolutePath() + "/src/main/java/");
generateByTables(MODULE_NAME, "user");
System.out.println("--------------------------生成成功------------------------");
}
/**
* 通过表名生成相关类
* @param module
* @param tableNames
*/
private static void generateByTables(String module, String... tableNames) {
moduleGenerator(module, tableNames);
}
private static void moduleGenerator(String module, String [] tableNames){
// 全局配置
GlobalConfig globalConfig = getGlobalConfig(module);
// 数据源配置
DataSourceConfig dataSourceConfig = getDataSourceConfig();
// 包配置
PackageConfig packageConfig = getPackageConfig();
// 策略配置
StrategyConfig strategyConfig = getStrategyConfig(tableNames);
// 模板配置
TemplateConfig templateConfig = getTemplateConfig();
// 采用自定义代码生成器来完成
new MyAutoGenerator()
.setGlobalConfig(globalConfig)
.setDataSource(dataSourceConfig)
.setPackageInfo(packageConfig)
.setStrategy(strategyConfig)
.setTemplate(templateConfig)
.execute();
}
/**
* 自定义代码生成模板, 由于我的项目中完全舍弃了xml文件和service接口,因此置null,
* 在模版引擎的执行方法中会校验如果模版为空则不会执行writer()方法
* @return
*/
private static TemplateConfig getTemplateConfig() {
TemplateConfig templateConfig = new TemplateConfig();
templateConfig.setEntity("templates/entity.java.vm") // entity模板采用自定义模板
.setMapper("templates/mapper.java.vm")// mapper模板采用自定义模板
.setXml(null) // 不生成xml文件
.setService(null) // 不生成service接口
.setServiceImpl("templates/serviceImpl.java.vm") // serviceImpl模板采用自定义模板
.setController("templates/controller.java.vm"); // controller模板采用自定义模板
return templateConfig;
}
/**
* 定义策略
* @param tableNames
* @return
*/
private static StrategyConfig getStrategyConfig(String... tableNames) {
StrategyConfig strategyConfig = new StrategyConfig();
// strategyConfig.setNaming()
strategyConfig
.setCapitalMode(false)//驼峰命名
.setEntityLombokModel(true)
.setRestControllerStyle(true)
.setNaming(NamingStrategy.underline_to_camel)
.setColumnNaming(NamingStrategy.underline_to_camel)
.setInclude(tableNames);
return strategyConfig;
}
/**
* 配置生成包名
* @return
*/
private static PackageConfig getPackageConfig() {
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent(PACKAGE_NAME)
.setEntity("pojo")
.setMapper("mapper")
.setServiceImpl("service")
.setController("controller");
return packageConfig;
}
/**
* 配置数据源
* @return
*/
private static DataSourceConfig getDataSourceConfig() {
String dbUrl = DB_URL;
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL)
.setDriverName(DRIVER_NAME)
.setUsername(USERNAME)
.setPassword(PASSWORD)
.setUrl(dbUrl);
return dataSourceConfig;
}
/**
* 全局配置,配置生成文件的目录
* @return
*/
private static GlobalConfig getGlobalConfig(String module) {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOpen(false)// new File("test-mybatis-plus").getAbsolutePath()得到当前模块根目录路径
.setOutputDir(new File(module).getAbsolutePath() + "/src/main/java")//生成文件的输出目录
.setFileOverride(true)//是否覆盖已有文件
.setBaseResultMap(true)
.setBaseColumnList(true)
.setActiveRecord(false)
.setAuthor("feifei")
.setServiceName("%sService");
return globalConfig;
}
}
可能直接贴代码大家会有些不懂的地方,下方做了相关的解释:
1. 上面定义的MODULE常量为模块名称(大家可以理解为你的项目名称),我的模块名称为:
2. 定义的模版文件在:
在项目的资源文件目录下新建了一个templates文件夹,其中放置了相关的自定义模版文件(采用的模版引擎是mybatis-plus默认的模版引擎),这个模版文件可以拷贝于mybatis-plus相关jar中的模版文件(不清楚的看最开始的框架目录结构),然后在进行自己的改造(如果要采用其他的模版引擎,还请引入相对应的pom文件)。这里仅演示下我自己自定义的controller.java.vm文件:
package ${package.Controller};
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.jgw.supercodeplatform.productmanagement.common.model.RestResult;
import com.jgw.supercodeplatform.exception.SuperCodeException;
import ${package.ServiceImpl}.${table.serviceName};
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
#if(${restControllerStyle})
#else
import org.springframework.stereotype.Controller;
#end
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end
/**
* <p>
* $!{table.comment} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${restControllerStyle})
@RestController
#else
@Controller
#end
@RequestMapping("/productmanage/#if(${package.ModuleName})/${package.ModuleName}#end/#if(${controllerMappingHyphenStyle})${controllerMappingHyphen}#else${table.entityPath}#end")
#if(${kotlin})
class ${table.controllerName}#if(${superControllerClass}) : ${superControllerClass}()#end
#else
#if(${superControllerClass})
public class ${table.controllerName} extends ${superControllerClass} {
#else
@Api(value = "", tags = "")
public class ${table.controllerName} {
#end
// 可在模版中添加相应的controller通用方法,编辑模版在resources/templates/controller.java.vm文件中
@Autowired
private ${table.serviceName} service;
@PostMapping("/save")
@ApiOperation(value = "", notes = "")
public RestResult save(@RequestBody Object obj) {
// TODO obj类型自行修改
service.add(obj);
return RestResult.success();
}
@PostMapping("/update")
@ApiOperation(value = "", notes = "")
public RestResult update(@RequestBody Object obj) {
// TODO obj类型自行修改
service.update(obj);
return RestResult.success();
}
@GetMapping("/{id}")
@ApiOperation(value = "", notes = "")
public RestResult getById(@PathVariable("id") String id) {
service.getById(id);
return null;
}
@GetMapping("/list")
@ApiOperation(value = "", notes = "")
public RestResult list(Object obj){
// TODO obj类型自行修改
service.list(obj);
return null;
}
}
#end
然后,我们编写GeneratorCodeUtil类中的AutoGenerator类(代码生成器)采用的我自己自定义的代码生成器类(MyAutoGenerator):
public class MyAutoGenerator extends AutoGenerator {
@Override
protected List<TableInfo> getAllTableInfoList(ConfigBuilder config) {
List<TableInfo> allTableInfoList = super.getAllTableInfoList(config);
allTableInfoList.forEach(tableInfo -> {
List<TableField> fields = tableInfo.getFields();
Set<String> importPackages = tableInfo.getImportPackages();
fields.forEach(field -> {
String propertyName = field.getPropertyName();
// 将字段名称的首字母小写
// field.setPropertyName(StringUtils.firstCharToLower(propertyName));
// 如果存在LocalDateTime类型时,将其修改为Date类型
if (field.getPropertyType().equals("LocalDateTime")) {
field.setColumnType(DbColumnType.DATE);
importPackages.remove("java.time.LocalDateTime");
importPackages.add("java.util.Date");
}
});
/*
* 将ServiceImpl名称修改为 => Service
* ps:UserServiceImpl -> UserService
*/
tableInfo.setServiceImplName(tableInfo.getServiceName());
// TODO 后续需要对自动代码生成进行相关拓展,可在此进行操作
});
// 自定义配置模版, 如果你想添加一个新的类,可以在资源文件目录中的templates文件夹下
// 添加自定义的模版文件
config.setInjectionConfig(getInjectionConfig(config));
return allTableInfoList;
}
public InjectionConfig getInjectionConfig(ConfigBuilder config) {
InjectionConfig injectionConfig = new InjectionConfig() {
@Override
public void initMap() {
}
};
List<FileOutConfig> list = new ArrayList<>();
FileOutConfig fileOutConfig = new FileOutConfig("templates/MyCustomTemplate.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
String outputFile = String.format((config.getPathInfo().get(ConstVal.SERVICE_IMPL_PATH) + File.separator + tableInfo.getServiceImplName() + ConstVal.JAVA_SUFFIX), tableInfo.getServiceImplName());
return outputFile;
}
};
list.add(fileOutConfig);
injectionConfig.setFileOutConfigList(list);
return injectionConfig;
}
}
还记得AutoGenerator类中的getAllTableInfoList()类吗
/**
* 开放表信息、预留子类重写
*
* @param config 配置信息
* @return ignore
*/
protected List<TableInfo> getAllTableInfoList(ConfigBuilder config) {
return config.getTableInfoList();
}
getAllTableInfoList()方法是该框架给我们进行自定义拓展的方法,TableInfo类中包含了表信息,关联到当前字段信息;因为mybatis-plus对应数据库的datetime类型为LocalDateTime, 我在自己的项目中只用到了Date,所以重写该方法对LocalDateTime进行了转换。
这样,功能便可实现了,还有很多其他的小细节,需要读者自己去注意了或者查看官方文档或者博客来完成了,因为最近很忙,后续会补充完成,写的有点乱,后续会修正完善。如有任何疑问,请留言。