最近研究mybatis generator源码,发现了通过Plugin接口可以修改生成的文件,进一步研究发现也可以自定义mapper、xml、model以外的任意java类,比如service、controller等。
现在介绍生成service接口的办法:
1、首先需要再mbg的xml配置文件中增加Plugin实现,如:ServicePlugin
<generatorConfiguration>
<context>
<plugin type="cn.test.config.ServicePlugin"/>
2、ServicePlugin继承PluginAdapter
并实现contextGenerateAdditionalJavaFiles
方法
PluginAdapter是抽象类,它默认实现了Plugin接口的大部分方法,这样我们只需要重写自己需要的方法即可,比较简单。
contextGenerateAdditionalJavaFiles方法,参数IntrospectedTable包含了从数据库读取的表信息,返回List是额外生成的java文件,这里附上一段源码,一看就明白了。
mbg生成java xml kotlin三种文件,分两次生成,第一阶段对应配置文件中的<javaModelGenerator>、<sqlMapGenerator>、<javaClientGenerator>
,第二阶段additional,对应我们自定义的部分。
for (IntrospectedTable introspectedTable : introspectedTables) {
callback.checkCancel();
introspectedTable.initialize();
introspectedTable.calculateGenerators(warnings, callback);
generatedJavaFiles.addAll(introspectedTable
.getGeneratedJavaFiles());
generatedXmlFiles.addAll(introspectedTable
.getGeneratedXmlFiles());
generatedKotlinFiles.addAll(introspectedTable
.getGeneratedKotlinFiles());
generatedJavaFiles.addAll(pluginAggregator
.contextGenerateAdditionalJavaFiles(introspectedTable));
generatedXmlFiles.addAll(pluginAggregator
.contextGenerateAdditionalXmlFiles(introspectedTable));
generatedKotlinFiles.addAll(pluginAggregator
.contextGenerateAdditionalKotlinFiles(introspectedTable));
}
3、完整的ServicePlugin实现:
import org.mybatis.generator.api.GeneratedJavaFile;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.config.PropertyRegistry;
import java.util.ArrayList;
import java.util.List;
/**
* 用于生成service
*/
public class ServicePlugin extends PluginAdapter {
FullyQualifiedJavaType baseServiceType = new FullyQualifiedJavaType("com.macro.mall.base.BaseService");
@Override
public boolean validate(List<String> warnings) {
return true;
}
@Override
public List<GeneratedJavaFile> contextGenerateAdditionalJavaFiles(IntrospectedTable introspectedTable) {
// 增加自定义Service.java文件
List<GeneratedJavaFile> list = new ArrayList<>();
// baseRecordType标识生成的java model包路径及名称,是xml中配置的
String baseRecordType = introspectedTable.getBaseRecordType();
// 实体类model的类名
String modelName = baseRecordType.replace("cn.test.model.", "");
// 我们可以用replace把包改到service包下
String servicePackage = baseRecordType.replace("model", "service");
FullyQualifiedJavaType type = new FullyQualifiedJavaType(servicePackage + "Service");
// CompilationUnit的子类,对应普通java类、接口、枚举有各自的子类,此处我们使用Interface
Interface unit = new Interface(type);
String baseService = String.format("cn.test.base.BaseService<%s, %sExample>", modelName, modelName);
// 设置public访问权限
unit.setVisibility(JavaVisibility.PUBLIC);
// 设置上级接口
unit.addSuperInterface(new FullyQualifiedJavaType(baseService));
// 设置import导入
unit.addImportedType(baseServiceType);
unit.addImportedType(new FullyQualifiedJavaType(baseRecordType));
unit.addImportedType(new FullyQualifiedJavaType(baseRecordType + "Example"));
// 第二个参数,指定生成文件所属的项目位置,这样项目位置+包名,就可以指定位置了,unit指定生成的内容。
GeneratedJavaFile gjf = new GeneratedJavaFile(unit,
"module-service/src/main/java",
context.getProperty(PropertyRegistry.CONTEXT_JAVA_FILE_ENCODING),
context.getJavaFormatter());
list.add(gjf);
return list;
}
}