在现在的开发中,对我们开发人员而言,最重要的就是开发效率,本次讲解的就是使用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类