原文链接:http://localhost:4001/2018/07/30/Mybatis-Plus-%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E6%9D%BF/
介绍
在现今的软件开发过程中,软件开发人员将更多的精力投入在了重复的相似劳动中。特别是在如今特别流行的 MVC 架构模式中,软件各个层次的功能更加独立,同时代码的相似度也更加高。所以我们需要寻找一种来减少软件开发人员重复劳动的方法,让程序员将更多的精力放在业务逻辑以及其他更加具有创造力的工作上。Mybatis Plus 可能加快开发速度。 但是更多时候,我们需要自定一些模板出来。
需求分析
在使用 Mybatis Plus 代码生成器中, 会自动生成 Mapper 、 Model 、 Service 、 Controller层的代码, 那么如何生成一些有自定义、有规律的代码? 带着这个疑问,查看了一下Mybatis Plus 的代码生成器的代码。
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("==========================文件生成完成!!!==========================");
}
可以看到,在一堆的配置后。会执行这个方法。
/**
* <p>
* 输出 java xml 文件
* </p>
*/
public AbstractTemplateEngine batchOutput() {
try {
List<TableInfo> tableInfoList = this.getConfigBuilder().getTableInfoList();
for (TableInfo tableInfo : tableInfoList) {
Map<String, Object> objectMap = this.getObjectMap(tableInfo);
Map<String, String> pathInfo = this.getConfigBuilder().getPathInfo();
TemplateConfig template = this.getConfigBuilder().getTemplate();
// 自定义内容
InjectionConfig injectionConfig = this.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 (this.isCreate(foc.outputFile(tableInfo))) {
this.writer(objectMap, foc.getTemplatePath(), foc.outputFile(tableInfo));
}
}
}
}
// 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" + this.suffixJavaOrKt()), entityName);
if (this.isCreate(entityFile)) {
this.writer(objectMap, this.templateFilePath(template.getEntity(this.getConfigBuilder().getGlobalConfig().isKotlin())), entityFile);
}
}
// MpMapper.java
if (null != tableInfo.getMapperName() && null != pathInfo.get(ConstVal.MAPPER_PATH)) {
String mapperFile = String.format((pathInfo.get(ConstVal.MAPPER_PATH) + File.separator + tableInfo.getMapperName() + this.suffixJavaOrKt()), entityName);
if (this.isCreate(mapperFile)) {
this.writer(objectMap, this.templateFilePath(template.getMapper()), mapperFile);
}
}
// MpMapper.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 (this.isCreate(xmlFile)) {
this.writer(objectMap, this.templateFilePath(template.getXml()), xmlFile);
}
}
// IMpService.java
if (null != tableInfo.getServiceName() && null != pathInfo.get(ConstVal.SERIVCE_PATH)) {
String serviceFile = String.format((pathInfo.get(ConstVal.SERIVCE_PATH) + File.separator + tableInfo.getServiceName() + this.suffixJavaOrKt()), entityName);
if (this.isCreate(serviceFile)) {
this.writer(objectMap, this.templateFilePath(template.getService()), serviceFile);
}
}
// MpServiceImpl.java
if (null != tableInfo.getServiceImplName() && null != pathInfo.get(ConstVal.SERVICEIMPL_PATH)) {
String implFile = String.format((pathInfo.get(ConstVal.SERVICEIMPL_PATH) + File.separator + tableInfo.getServiceImplName() + this.suffixJavaOrKt()), entityName);
if (this.isCreate(implFile)) {
this.writer(objectMap, this.templateFilePath(template.getServiceImpl()), implFile);
}
}
// MpController.java
if (null != tableInfo.getControllerName() && null != pathInfo.get(ConstVal.CONTROLLER_PATH)) {
String controllerFile = String.format((pathInfo.get(ConstVal.CONTROLLER_PATH) + File.separator + tableInfo.getControllerName() + this.suffixJavaOrKt()), entityName);
if (this.isCreate(controllerFile)) {
this.writer(objectMap, this.templateFilePath(template.getController()), controllerFile);
}
}
}
} catch (Exception e) {
logger.error("无法创建文件,请检查配置信息!", e);
}
return this;
}
在 batchOutput 方法中,会有生成 Mapper 、 Model 、 Service 、 Controller 层的代码,也可以在这个自定义自己的模板代码。如果在配置中配置了 fileOutConfigList 的属性,就可以自定自己的模板代码。
编写模板
经过上述的分析,我们可以知道。 如果想要自定义自己的模板代码。就需要配置 fileOutConfigList 这个属性。 试着对 fileOutConfigList 进行一些简单的配置
AutoGenerator autoGenerator = new AutoGenerator();
autoGenerator.setCfg(customerConfig());
autoGenerator.setGlobalConfig(configGlobalConfig());
autoGenerator.setDataSource(configDataSource());
autoGenerator.setStrategy(configStrategyConfig());
autoGenerator.setPackageInfo(configPackageConfig());
autoGenerator.execute();
/**
* 自定义生成文件
*/
private static InjectionConfig customerConfig() {
InjectionConfig config = new InjectionConfig() {
@Override
public void initMap() {
}
};
List<FileOutConfig> files = new ArrayList<FileOutConfig>();
files.add(new FileOutConfig("/template.java.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
String expand = CODE_FACTORY_OUT_PATH + "/" + "expand";
String entityFile = String.format((expand + File.separator + "%s" + ".java"), tableInfo.getControllerName());
return entityFile;
}
});
config.setFileOutConfigList(files);
return config;
}
这个是 Java 层面上的配置, 我们指定了一个模板文件 template.java.vm ,按照 Mybatis Plus 里面所提供的模板文件来创建一个自定义的模板文件。 而这里,我只是生成一个简单的增删改查的 Controller 。
package ${package.Controller};
import org.springframework.web.bind.annotation.RequestMapping;
#if(${restControllerStyle})
import org.springframework.web.bind.annotation.RestController;
#else
import org.springframework.stereotype.Controller;
#end
#if(${superControllerClassPackage})
import ${superControllerClassPackage};
#end
import ${package.Service}.${table.serviceName};
import ${package.Entity}.${entity};
import com.baomidou.mybatisplus.plugins.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.message.common.BaseResponse;
import java.util.List;
/**
* <p>
* $!{table.comment} 前端控制器
* </p>
*
* @author ${author}
* @since ${date}
*/
#if(${restControllerStyle})
@RestController
#else
@Controller
#end
@RequestMapping("#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
public class ${table.controllerName} {
#end
private ${table.serviceName} targetService;
@Autowired
public ${table.controllerName}(${table.serviceName} targetService){
this.targetService = targetService;
}
/**
* 获取数据列表
*/
@RequestMapping("/list")
@ResponseBody
public BaseResponse findListByPage(@RequestParam(name = "page", defaultValue = "1") int pageIndex,@RequestParam(name = "rows", defaultValue = "20") int step){
Page page = new Page(pageIndex,step);
targetService.selectPage(page);
return BaseResponse.onSuccess(page);
}
/**
* 获取全部数据
*/
@RequestMapping("/all")
@ResponseBody
public BaseResponse findAll(){
List<${entity}> models = targetService.selectList(null);
return BaseResponse.onSuccess(models);
}
/**
* 根据ID查找数据
*/
@RequestMapping("/find")
@ResponseBody
public BaseResponse find(@RequestParam("id") Long id){
${entity} ${entity} = targetService.selectById(id);
if(${entity}==null){
return BaseResponse.onFail("尚未查询到此ID");
}
return BaseResponse.onSuccess(${entity});
}
/**
* 添加数据
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
@ResponseBody
public BaseResponse addItem(@RequestBody ${entity} ${entity}){
boolean isOk = targetService.insert(${entity});
if(isOk){
return BaseResponse.onSuccess("数据添加成功!");
}
return BaseResponse.onFail("数据添加失败");
}
/**
* 更新数据
*/
@RequestMapping(value = "/update", method = RequestMethod.POST)
@ResponseBody
public BaseResponse updateItem(@RequestBody ${entity} ${entity}){
boolean isOk = targetService.updateAllColumnById(${entity});
if(isOk){
return BaseResponse.onSuccess("数据更改成功!");
}
return BaseResponse.onFail("数据更改失败");
}
/**
* 删除数据
*/
@RequestMapping("/del")
@ResponseBody
public BaseResponse deleteItems(@RequestParam("ids") List<Long> ids){
boolean isOk = targetService.deleteBatchIds(ids);
if(isOk){
return BaseResponse.onSuccess("数据删除成功!");
}
return BaseResponse.onFail("数据删除失败");
}
}
#end
完成测试
运行代码生成器,就可以生成自己想要生成的模板代码了。 这里仅仅是展示了一个增删改成的模板代码。 你也可能生成前端通用的模板代码、还有一些有规律的模板代码,来解放你的双手。很多时候,封装是个好东西。 慢慢的你会发现,过渡的设计也是一种致命的错误。 只有你自己知道。你适合什么。
网友评论