使⽤mybatis-plus通过⾃定义模版来⾃动⽣成相关模版代码 在现在的开发中,对我们开发⼈员⽽⾔,最重要的就是开发效率,本次讲解的就是使⽤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", Map());
List<FileOutConfig> focList = FileOutConfigList();
if (CollectionUtils.isNotEmpty(focList)) {
for (FileOutConfig foc : focList) {
if (isCreate(FileType.OTHER, foc.outputFile(tableInfo))) {
writer(objectMap, TemplatePath(), foc.outputFile(tableInfo));
}
}
}
}
/
/ ⽣成entity实体类
String entityName = EntityName();
if (null != entityName && null != (ConstVal.ENTITY_PATH)) {
String entityFile = String.format(((ConstVal.ENTITY_PATH) + File.separator + "%s" + suffixJavaOrKt()), entityName);
if (isCreate(FileType.ENTITY, entityFile)) {
// writer⽅法交由具体引擎类实现(writer⽅法为抽象⽅法)
writer(objectMap, Entity(getConfigBuilder().getGlobalConfig().isKotlin())), entityFile);
免费模板生成器}
}
// ⽣成mapper接⼝类
if (null != MapperName() && null != (ConstVal.MAPPER_PATH)) {
String mapperFile = String.format(((ConstVal.MAPPER_PATH) + File.separator + MapperName() + suffixJavaOrKt()), entityN if (isCreate(FileType.MAPPER, mapperFile)) {
// writer⽅法交由具体引擎类实现(writer⽅法为抽象⽅法)
writer(objectMap, Mapper()), mapperFile);
}
}
// ⽣成l⽂件
if (null != XmlName() && null != (ConstVal.XML_PATH)) {
String xmlFile = String.format(((ConstVal.XML_PATH) + File.separator + XmlName() + ConstVal.XML_SUFFIX), entityName) if (isCreate(FileType.XML, xmlFile)) {
// writer⽅法交由具体引擎类实现(writer⽅法为抽象⽅法)
writer(objectMap, Xml()), xmlFile);
}
}
// ⽣成service接⼝类
if (null != ServiceName() && null != (ConstVal.SERVICE_PATH)) {
String serviceFile = String.format(((ConstVal.SERVICE_PATH) + File.separator + ServiceName() + suffixJavaOrKt()), entityN if (isCreate(FileType.SERVICE, serviceFile)) {
// writer⽅法交由具体引擎类实现(writer⽅法为抽象⽅法)
writer(objectMap, Service()), serviceFile);
}
}
// ⽣成service接⼝实现类
if (null != ServiceImplName() && null != (ConstVal.SERVICE_IMPL_PATH)) {
if (null != ServiceImplName() && null != (ConstVal.SERVICE_IMPL_PATH)) {
String implFile = String.format(((ConstVal.SERVICE_IMPL_PATH) + File.separator + ServiceImplName() + suffixJavaOrKt()), if (isCreate(FileType.SERVICE_IMPL, implFile)) {
// writer⽅法交由具体引擎类实现(writer⽅法为抽象⽅法)
writer(objectMap, ServiceImpl()), implFile);
}
}
// ⽣成controller类
if (null != ControllerName() && null != (ConstVal.CONTROLLER_PATH)) {
String controllerFile = String.format(((ConstVal.CONTROLLER_PATH) + File.separator + ControllerName() + suffixJavaOrKt( if (isCreate(FileType.CONTROLLER, controllerFile)) {
// writer⽅法交由具体引擎类实现(writer⽅法为抽象⽅法)
writer(objectMap, Controller()), controllerFile);
}
}
}
} catch (Exception e) {
<("⽆法创建⽂件,请检查配置信息!", 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("source.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 = Template(templatePath, ConstVal.UTF8);
try (FileOutputStream fos = new FileOutputStream(outputFile);
OutputStreamWriter ow = new OutputStreamWriter(fos, ConstVal.UTF8);
BufferedWriter writer = new BufferedWriter(ow)) {
<(new VelocityContext(objectMap), writer);
}
logger.debug("模板:" + templatePath + "; ⽂件:" + outputFile);
}
/**
* 获取⽂件路径 + .vm后缀,⽐如filePath: TestController.java => TestController.java.vm
*/
@Override
public String templateFilePath(String filePath) {
if (null == filePath || ains(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);
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论