首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

SpringBoot代码生成器,让你释放双手,从此不用手撸代码

前言

通常在开始开发项目的时候,首先会建立好数据库相关表,然后根据表结构生成 Controller、Service、DAO、Model以及一些前端页面。

如果开发前没有强制的约束,而每个程序员都有自己的编码习惯,最终会导致一个项目呈现出多种编码风格。再有就是一些CRUD的列表功能,基本是没啥挑战性的,纯粹苦力活,浪费时间。

所以,根据公司现有框架,开发一款统一风格的代码生成器还是很有必要的。

技术选型

开发框架:SpringBoot+JPA,考虑到会生成各种前后端代码文件,这里我们选用freemarker模板引擎来制作相应的模板。

实现思路

获取表结构信息

首先我们定义一个实体类,为了使用方便,把表和字段信息放到了一个类中:

代码语言:javascript
复制
/**?*?表以及相关字段信息?*/?@Data?public?class?AppGen?extends?PageBean?implements?Serializable?{??/**?*?表名?*/?private?String?tableName;?/**?*?实体类名?*/?private?String?entityName;?/**?*?实体类名?首字母小写?*/?private?String?lowerEntityName;?/**?*?表备注?*/?private?String?tableComment;?/**?*?表前缀?*/?private?String?prefix;?/**?*?功能描述?*/?private?String?function;??/**?*?列名?*/?private?String?columnName;?/**?*?实体列名?*/?private?String?entityColumnName;?/**?*?列描述?*/?private?String?columnComment;??/**?*?类型?*/?private?String?dataType;??/**?*?自增?*/?private?Object?columnExtra;?/**?*?长度?*/?private?Object?columnLength;??private?List<AppGen>?list;??}?

获取表列表:

代码语言:javascript
复制
@Override?@Transactional(readOnly?=?true)?public?Result?list(AppGen?gen){?String?countSql?=?"SELECT?COUNT(*)?FROM?information_schema.tables?";?countSql?+="WHERE?table_schema='tools'";?Long?totalCount?=?dynamicQuery.nativeQueryCount(countSql);?PageBean<AppGen>?data?=?new?PageBean<>();?if(totalCount>0){?String?nativeSql?=?"SELECT?table_name?as?tableName,table_comment?as?tableComment?";?nativeSql+="FROM?information_schema.tables?WHERE?table_schema='tools'";?Pageable?pageable?=?PageRequest.of(gen.getPageNo(),gen.getPageSize());?List<AppGen>?list?=?dynamicQuery.nativeQueryPagingListModel(AppGen.class,pageable,?nativeSql);?data?=?new?PageBean<>(list,?totalCount);?}?return?Result.ok(data);?}?

制作模板

模板太多了,这里只以Controller模板为例,贴一下实现代码,更多模板见源码:

代码语言:javascript
复制
package?com.tools.module.${prefix}.web;??import?com.tools.common.config.AbstractController;?import?com.tools.common.model.Result;?import?com.tools.module.${prefix}.entity.${entityName};?import?com.tools.module.${prefix}.service.${entityName}Service;?import?org.springframework.beans.factory.annotation.Autowired;?import?org.springframework.web.bind.annotation.PostMapping;?import?org.springframework.web.bind.annotation.RequestBody;?import?org.springframework.web.bind.annotation.RequestMapping;?import?org.springframework.web.bind.annotation.RestController;???@RestController?@RequestMapping("/${prefix}/${function}")?public?class?${entityName}Controller?extends?AbstractController?{??@Autowired?private?${entityName}Service?${function}Service;??/**?*?列表?*/?@PostMapping("/list")?public?Result?list(${entityName}?${function}){?return?${function}Service.list(${function});?}?/**?*?查询?*/?@PostMapping("/get")?public?Result?get(Long?id){?return?${function}Service.get(id);?}?/**?*?保存?*/?@PostMapping("/save")?public?Result?save(@RequestBody?${entityName}?${function}){?return?${function}Service.save(${function});?}??/**?*?删除?*/?@PostMapping("/delete")?public?Result?delete(Long?id){?return?${function}Service.delete(id);?}?}?

说白了其实就是传递参数,把一些可变的代码片段使用${name}形式编写。

代码生成

有点长,慢慢看,其实就是渲染各种前后端模板:

代码语言:javascript
复制
/**?*?生成代码?*?@param?gen?*?@return?*?@throws?IOException?*?@throws?TemplateException?*/?@PostMapping("/create")?public?Result?create(@RequestBody?AppGen?gen)?throws?IOException,?TemplateException?{?/**?*?获取表字段以及注释?*/?List<AppGen>?list?=?genService.getByTable(gen);?String?name?=?gen.getTableName();?String[]?table?=?StringUtils.split(name,"_");?gen.setPrefix(table[0]);?gen.setFunction(table[1]);?gen.setEntityName(GenUtils.allInitialCapital(gen.getTableName()));?list.stream().forEach(column->?{?column.setEntityColumnName(GenUtils.secInitialCapital(column.getColumnName()));?});?gen.setList(list);?String?baseFile?=?filePath+?SystemConstant.SF_FILE_SEPARATOR+"com"+?SystemConstant.SF_FILE_SEPARATOR+?"tools"+?SystemConstant.SF_FILE_SEPARATOR+?"module"+?SystemConstant.SF_FILE_SEPARATOR+?gen.getPrefix()+SystemConstant.SF_FILE_SEPARATOR;?/**?*?后端代码?*/?File?entityFile?=?FileUtil.touch(baseFile+"entity"+?SystemConstant.SF_FILE_SEPARATOR+gen.getEntityName()+".java");?File?repositoryFile?=?FileUtil.touch(baseFile+"repository"+?SystemConstant.SF_FILE_SEPARATOR+gen.getEntityName()+"Repository.java");?File?serviceFile?=?FileUtil.touch(baseFile+"service"+?SystemConstant.SF_FILE_SEPARATOR+gen.getEntityName()+"Service.java");?File?serviceImplFile?=?FileUtil.touch(baseFile+"service"+?SystemConstant.SF_FILE_SEPARATOR+"impl"+SystemConstant.SF_FILE_SEPARATOR+?gen.getEntityName()+"ServiceImpl.java");?File?controllerFile?=?FileUtil.touch(baseFile+"web"+?SystemConstant.SF_FILE_SEPARATOR?+?gen.getEntityName()?+?"Controller.java");?/**?*?前端代码?*/?String?htmlPath?=?filePath+?SystemConstant.SF_FILE_SEPARATOR?+?"templates"+?SystemConstant.SF_FILE_SEPARATOR?+?gen.getPrefix()+?SystemConstant.SF_FILE_SEPARATOR?+?gen.getFunction()+SystemConstant.SF_FILE_SEPARATOR;?File?listFile?=?FileUtil.touch(htmlPath?+?"list.html");?File?formFile?=?FileUtil.touch(htmlPath?+?"form.html");?/**?*?生成静态页面?*/?Template?template?=?configuration.getTemplate("html/list.ftl");?String?text?=?FreeMarkerTemplateUtils.processTemplateIntoString(?template,?gen);?FileUtil.writeString(text,listFile,"UTF-8");?template?=?configuration.getTemplate("html/form.ftl");?text?=?FreeMarkerTemplateUtils.processTemplateIntoString(?template,?gen);?FileUtil.writeString(text,formFile,"UTF-8");?/**?*?生成后端代码?repository?*/?template?=?configuration.getTemplate("java/repository.ftl");?text?=?FreeMarkerTemplateUtils.processTemplateIntoString(?template,?gen);?FileUtil.writeString(text,repositoryFile,"UTF-8");?/**?*?生成后端代码?entity?*/?template?=?configuration.getTemplate("java/entity.ftl");?text?=?FreeMarkerTemplateUtils.processTemplateIntoString(?template,?gen);?FileUtil.writeString(text,entityFile,"UTF-8");?/**?*?生成后端代码?service?*/?template?=?configuration.getTemplate("java/service.ftl");?text?=?FreeMarkerTemplateUtils.processTemplateIntoString(?template,?gen);?FileUtil.writeString(text,serviceFile,"UTF-8");?/**?*?生成后端代码?service?实现?*/?template?=?configuration.getTemplate("java/serviceImpl.ftl");?text?=?FreeMarkerTemplateUtils.processTemplateIntoString(?template,?gen);?FileUtil.writeString(text,serviceImplFile,"UTF-8");?/**?*?生成后端代码?controller?实现?*/?template?=?configuration.getTemplate("java/controller.ftl");?text?=?FreeMarkerTemplateUtils.processTemplateIntoString(?template,?gen);?FileUtil.writeString(text,controllerFile,"UTF-8");?return?Result.ok();?}?

生成逻辑还是很傻瓜的,后期会慢慢优化,比如根据字段类型生成不同的表单形式,可以自定义字段是否显示等的。

小结

总的来说,还是比较容易上手的,相对于一些简单的列表功能分分钟撸出效果,开发一分钟,喝茶一整天。当然对于一些复杂的效果,还是自己一一去实现,但这并不影响生成器的实用性。

源码 https://gitee.com/52itstyle/SPTools

  • 发表于:
  • 原文链接http://news.51cto.com/art/202005/617351.htm
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com