文章目录
代码生成效果:
说明:
本文均以velocity
模板演示,其余模板只是语法不同
参考博客 Mybatis-plus最新代码生成器(3.5.1+)的使用时你需要改为使用velocity
模板
1.准备工作和目标效果
如果你了解过velocity
模板引擎(不了解也没关系),这篇博文不错 Velocity模板引擎
请先阅读此博客(2分钟): Mybatis-plus最新代码生成器(3.5.1+)的使用
构建好操作环境
1.1 首先找到plus的模板在哪
外部包-----找到plus的generator包-----templates下vm后缀的模板就是velocity
的模板了
##1.2 以controller.java.vm为例
首先复制一份到你的resource/templates
目录下,打开如下:
1.2.1先看下它现在这个controller模板生成的controller大致是啥样的
这是我生成的用户controller
/**
* <p>
* 前端控制器
* </p>
*
* @author 向培
* @since 2022-04-05
*/
@Controller
@RequestMapping("/sysUser")
public class SysUserController {
}
很简陋对吧,我们肯定是想要把增删改查接口都写上对吧。
先拿我想要的结果来看:
/**
* <p>
* 前端控制器
* </p>
*
* @author 向培
* @since 2022-04-07
*/
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/sys-menu")
@Api(value = "菜单", tags = "菜单")
public class SysMenuController {
private final SysMenuService menuService;
@PostMapping("/")
@ApiOperation(value = "添加菜单", notes = "添加菜单")
public ResponseData addMenu(@RequestBody @Validated SysMenuForm form) {
return menuService.addMenu(form);
}
@PutMapping("/")
@ApiOperation(value = "修改菜单", notes = "修改菜单")
public ResponseData editMenu(@RequestBody @Validated SysMenuForm form) {
return menuService.editMenu(form);
}
@DeleteMapping("/{menu_id}")
@ApiOperation(value = "删除菜单", notes = "删除菜单")
public ResponseData deleteMenu(@PathVariable("menu_id") String menuId) {
return menuService.deleteMenu(menuId);
}
@GetMapping("/page")
@ApiOperation(value = "菜单分页", notes = "菜单分页")
public ResponseData menuPage(SysMenuForm form) {
return menuService.selectMenuByPage(form);
}
@GetMapping("/{menu_id}")
@ApiOperation(value = "id查找", notes = "id查找")
public ResponseData menuPage(@PathVariable("menu_id") String menuId) {
return menuService.selectMenuById(menuId);
}
}
下面我们就把plus默认的模板改造成我们想要的吧!不了解velocity
的语法也是没关系的!
2.入手点
如果你点进我前面推荐的关于velocity
的文章,那么你应该知道了最后生成的代码是通过模板与数据合并实现的。
ok,原理就是这个,那么plus肯定也只能这样做。
所以,一定有一个类的某个方法会执行这个合并操作。
2.1查看引入的包
经过我的查看,一个叫VelocityTemplateEngine
的类就是搞这个的。
包目录----plus的generator包-----engine下面的VelocityTemplateEngine
其中的write方法为关键:
@Override
public void writer(@NotNull Map<String, Object> objectMap, @NotNull String templatePath, @NotNull File outputFile) throws Exception {
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);
}
}
参数objectMap
即为数据模型
参数templatePath
即为模板所在路径
怎么样?恍然大悟吧,它两执行merge
操作就可以生成代码文件了
2.2了解objectMap
为了能更好的帮助我们修改模板,我们需要知道objectMap
里面都有哪些数据可供我们使用。
打个断点,
debug
运行代码生成工具,如果你没有代码生成工具类,可以看看我的这篇文章,代码在最后,复制即用(表和数据库需要自己弄):
Mybatis-plus最新代码生成器(3.5.1+)的使用
进入断点:可以看到东西还是很多的
这里我们不必太关心true
和false
这些键值对,它们大都用于模板中的if
判断。
你需要的时候看看就知道了,这不是我们关注的重点。
哪些是重点?
比如table、package这些value为对象的key:
了解了这些东西之后,我们才能知道通过哪些对象可以点出哪些属性供我们使用!!!
objectMap中的所有键值对都能在模板中使用!!!
3.修改模板
3.1梳理一下需求
3.2打开你复制的模板做修改
这里作者有一个小建议,那就是断点不要放行,以便于修改模板的同时能查看objectMap有哪些可用数据
之前生成的代码需要删除掉,不然不会进入断点
首先把效果图中的代码复制到模板中,然后再根据需求改动:
减少篇幅,展示部分代码
public class ${table.controllerName} {
#end
private final SysMenuService menuService;
@PostMapping("/")
@ApiOperation(value = "添加菜单", notes = "添加菜单")
public ResponseData addMenu(@RequestBody @Validated SysMenuForm form) {
return menuService.addMenu(form);
}
@PutMapping("/")
@ApiOperation(value = "修改菜单", notes = "修改菜单")
public ResponseData editMenu(@RequestBody @Validated SysMenuForm form) {
return menuService.editMenu(form);
}
@DeleteMapping("/{menu_id}")
@ApiOperation(value = "删除菜单", notes = "删除菜单")
public ResponseData deleteMenu(@PathVariable("menu_id") String menuId) {
return menuService.deleteMenu(menuId);
}
@GetMapping("/page")
@ApiOperation(value = "菜单分页", notes = "菜单分页")
public ResponseData menuPage(SysMenuForm form) {
return menuService.selectMenuByPage(form);
}
@GetMapping("/{menu_id}")
@ApiOperation(value = "id查找", notes = "id查找")
public ResponseData menuPage(@PathVariable("menu_id") String menuId) {
return menuService.selectMenuById(menuId);
}
}
#end
3.2.1添加注解
1.@Validated 数据校验
2.@RequiredArgsConstructor 构造器
3.@Api(value = “菜单”, tags = “菜单”) 、 @ApiOperation(value = “修改菜单”, notes = “修改菜单”) swagger
这些是死代码,直接把import语句复制进来,注解加上就行了
需要注意的是,因为是死代码,添加的时候不要放到if
语句中,不然可能失效。
需要处理的地方就是@Api(value = "菜单")
这个菜单是动态内容,需要改
看看,objectMap的数据呢:这个我们可以直接定位到在table里面
好像没有这样的中文,但是我们可以使用这个comment
属性,就是数据库表的注释,现在没有,那就去加一个
放行断点、删除生成的文件,重新debug
可以了,修改模板:
@Api(value = "${table.comment}", tags = "${table.comment}")
ok,生成代码看看效果:
没有问题!
下面就该修改service注入了:
private final SysMenuService menuService;
很明显啊,我们看controller的名字:
那么Service的名字也肯定在table里面:都在这里面了
private final ${table.serviceName} menuService;
那么问题来了,这个小写开头的menuService
我们改怎么处理呢?
在模板中是无法调用String这些api的,所以我们需要写一个类继承VelocityTemplateEngine
,重写write
方法,然后做自定义操作:
public class MyVelocityTemplateEngine extends VelocityTemplateEngine {
@Override
public void writer(Map<String, Object> objectMap, String templatePath, File outputFile) throws Exception {
// 取出Service接口的名字,进行首字母小写处理
TableInfo tableInfo = (TableInfo) objectMap.get("table");
String first = tableInfo.getServiceName().substring(0,1).toLowerCase();
String firstToLower = first + tableInfo.getServiceName().substring(1);
objectMap.put("firstToLowerService", firstToLower);
super.writer(objectMap, templatePath, outputFile);
}
}
需要注意的是这个TableInfo是来自这个包下:
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
然后将代码生成工具类的最后位置改一下:改成自定义的类
再次debug运行,看看:
没问题了,再改改模板:
import ${package.Service}.${table.ServiceName};
private final ${table.serviceName} ${firstToLowerService};
顺势而为,把@ApiOperation
和方法名改了:
@PostMapping("/")
@ApiOperation(value = "添加${table.comment}", notes = "添加${table.comment}")
public ResponseData add${table.entityName}(@RequestBody @Validated SysMenuForm form) {
return menuService.add${table.entityName}(form);
}
@PutMapping("/")
@ApiOperation(value = "修改${table.comment}", notes = "修改${table.comment}")
public ResponseData edit${table.entityName}(@RequestBody @Validated SysMenuForm form) {
return menuService.edit${table.entityName}(form);
}
@DeleteMapping("/{menu_id}")
@ApiOperation(value = "删除${table.comment}", notes = "删除${table.comment}")
public ResponseData delete${table.entityName}(@PathVariable("menu_id") String menuId) {
return menuService.delete${table.entityName}(menuId);
}
@GetMapping("/page")
@ApiOperation(value = "${table.comment}分页", notes = "${table.comment}分页")
public ResponseData ${table.entityName}Page(SysMenuForm form) {
return menuService.select${table.entityName}ByPage(form);
}
@GetMapping("/{menu_id}")
@ApiOperation(value = "id查找", notes = "id查找")
public ResponseData ${table.entityName}Page(@PathVariable("menu_id") String menuId) {
return menuService.select${table.entityName}ById(menuId);
}
生成效果:
@PostMapping("/")
@ApiOperation(value = "添加系统菜单", notes = "添加系统菜单")
public ResponseData addSysMenu(@RequestBody @Validated SysMenuForm form) {
return menuService.addSysMenu(form);
}
@PutMapping("/")
@ApiOperation(value = "修改系统菜单", notes = "修改系统菜单")
public ResponseData editSysMenu(@RequestBody @Validated SysMenuForm form) {
return menuService.editSysMenu(form);
}
@DeleteMapping("/{menu_id}")
@ApiOperation(value = "删除系统菜单", notes = "删除系统菜单")
public ResponseData deleteSysMenu(@PathVariable("menu_id") String menuId) {
return menuService.deleteSysMenu(menuId);
}
@GetMapping("/page")
@ApiOperation(value = "系统菜单分页", notes = "系统菜单分页")
public ResponseData SysMenuPage(SysMenuForm form) {
return menuService.selectSysMenuByPage(form);
}
@GetMapping("/{menu_id}")
@ApiOperation(value = "id查找", notes = "id查找")
public ResponseData SysMenuPage(@PathVariable("menu_id") String menuId) {
return menuService.selectSysMenuById(menuId);
}
小结
由于篇幅原因,打算分开来说。
以上演示还有较多的”小毛病“,比如分页的方法名是大写开头(当然,你完全可以通过修改${table.entityName}Page
来避免,比如改为page${table.entityName}
)
还有@DeleteMapping("/{menu_id}")
这个menu_id你完全可以使用id替换,直接写死,省事。我就先不改了
还有,@RequestBody @Validated SysMenuForm form
这个对象SysMenuForm
你也需要写一个模板生成它,然后在controller中引用它,(在自定义MyVelocityTemplateEngine
可以办到)
总结经验
1.你想在模板中使用的属性,先去objectMap中找找(推荐方式:打个断点不放行,可以边修改模板边看objectMap的内容有哪些)
2.objectMap中没有的、你想自己加一些东西的,可以通过继承VelocityTemplateEngine
,重写write方法。往objectMap中put数据
虽然本文只讲述了如何生成controller,但是其思路是通用的!
我也会持续更新至controller、service、mapper等模板修改。前端vue可能也会哦~~