您当前的位置:首页 > 电脑百科 > 程序开发 > 架构

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

时间:2020-05-22 14:21:44  来源:  作者:
SpringBoot代码生成器,让你释放双手,从此不用手撸代码

 

前言

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

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

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

技术选型

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

实现思路

获取表结构信息

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

/**
 * 表以及相关字段信息
 */
@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;

}

获取表列表:

@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);
}
SpringBoot代码生成器,让你释放双手,从此不用手撸代码

 

制作模板

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

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}形式编写。

代码生成

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

/**
 * 生成代码
 * @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



Tags:SpringBoot   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
我是一名程序员关注我们吧,我们会多多分享技术和资源。进来的朋友,可以多了解下青锋的产品,已开源多个产品的架构版本。Thymeleaf版(开源)1、采用技术: springboot、layui、Thymel...【详细内容】
2021-12-14  Tags: SpringBoot  点击:(21)  评论:(0)  加入收藏
前言项目中的配置文件会有密码的存在,例如数据库的密码、邮箱的密码、FTP的密码等。配置的密码以明文的方式暴露,并不是一种安全的方式,特别是大型项目的生产环境中,因为配置文...【详细内容】
2021-11-17  Tags: SpringBoot  点击:(25)  评论:(0)  加入收藏
SpringBoot开发的物联网通信平台系统项目功能模块 功能 说明 MQTT 1.SSL支持 2.集群化部署时暂不支持retain&will类型消 UDP ...【详细内容】
2021-11-05  Tags: SpringBoot  点击:(56)  评论:(0)  加入收藏
1. 介绍1.1 介绍今天开始我们来学习Java操作MySQL数据库的技巧,Java操作MySQL是借助JdbcTemplate这个对象来实现的。JdbcTemplate是一个多数据库集中解决方案,而我们今天只讲...【详细内容】
2021-11-05  Tags: SpringBoot  点击:(30)  评论:(0)  加入收藏
SpringBoot中的Controller注册本篇将会以Servlet为切入点,通过源码来看web容器中的Controller是如何注册到HandlerMapping中。请求来了之后,web容器是如何根据请求路径找到对...【详细内容】
2021-11-04  Tags: SpringBoot  点击:(53)  评论:(0)  加入收藏
环境:Springboot2.4.11环境配置接下来的演示都是基于如下接口进行。@RestController@RequestMapping("/exceptions")public class ExceptionsController { @GetMapping(...【详细内容】
2021-10-11  Tags: SpringBoot  点击:(41)  评论:(0)  加入收藏
SpringBoot项目默认使用logback, 已经内置了 logback 的相关jar包,会从resource包下查找logback.xml, logback 文件格式范本 可直接复制使用,有控制台 info.log error.log三个...【详细内容】
2021-10-09  Tags: SpringBoot  点击:(50)  评论:(0)  加入收藏
环境:Springboot2.4.10当应用程序启动时,Spring Boot将自动从以下位置查找并加载application.properties和application.yaml文件: 从Classpath类路径classpath的根类路径classp...【详细内容】
2021-09-26  Tags: SpringBoot  点击:(78)  评论:(0)  加入收藏
搭建基础1. Intellij IDEA 2. jdk1.8 3. maven3.6.3搭建方式(1)在线创建项目Spring Boot 官方提供的一种创建方式,在浏览器中访问如下网址: https://start.spring.io/在打开的页...【详细内容】
2021-09-14  Tags: SpringBoot  点击:(78)  评论:(0)  加入收藏
最近开发项目的时候需要用到对象的属性拷贝,以前也有用过一些复制框架,比如spring的 BeanUtils.copyProperties等方式,但总是不尽如人意,最近发现使用orika进行对象拷贝挺好用的...【详细内容】
2021-08-27  Tags: SpringBoot  点击:(231)  评论:(0)  加入收藏
▌简易百科推荐
为了构建高并发、高可用的系统架构,压测、容量预估必不可少,在发现系统瓶颈后,需要有针对性地扩容、优化。结合楼主的经验和知识,本文做一个简单的总结,欢迎探讨。1、QPS保障目标...【详细内容】
2021-12-27  大数据架构师    Tags:架构   点击:(5)  评论:(0)  加入收藏
前言 单片机开发中,我们往往首先接触裸机系统,然后到RTOS,那么它们的软件架构是什么?这是我们开发人员必须认真考虑的问题。在实际项目中,首先选择软件架构是非常重要的,接下来我...【详细内容】
2021-12-23  正点原子原子哥    Tags:架构   点击:(7)  评论:(0)  加入收藏
现有数据架构难以支撑现代化应用的实现。 随着云计算产业的快速崛起,带动着各行各业开始自己的基于云的业务创新和信息架构现代化,云计算的可靠性、灵活性、按需计费的高性价...【详细内容】
2021-12-22    CSDN  Tags:数据架构   点击:(10)  评论:(0)  加入收藏
▶ 企业级项目结构封装释义 如果你刚毕业,作为Java新手程序员进入一家企业,拿到代码之后,你有什么感觉呢?如果你没有听过多模块、分布式这类的概念,那么多半会傻眼。为什么一个项...【详细内容】
2021-12-20  蜗牛学苑    Tags:微服务   点击:(9)  评论:(0)  加入收藏
我是一名程序员关注我们吧,我们会多多分享技术和资源。进来的朋友,可以多了解下青锋的产品,已开源多个产品的架构版本。Thymeleaf版(开源)1、采用技术: springboot、layui、Thymel...【详细内容】
2021-12-14  青锋爱编程    Tags:后台架构   点击:(21)  评论:(0)  加入收藏
在了解连接池之前,我们需要对长、短链接建立初步认识。我们都知道,网络通信大部分都是基于TCP/IP协议,数据传输之前,双方通过“三次握手”建立连接,当数据传输完成之后,又通过“四次挥手”释放连接,以下是“三次握手”与“四...【详细内容】
2021-12-14  架构即人生    Tags:连接池   点击:(17)  评论:(0)  加入收藏
随着移动互联网技术的快速发展,在新业务、新领域、新场景的驱动下,基于传统大型机的服务部署方式,不仅难以适应快速增长的业务需求,而且持续耗费高昂的成本,从而使得各大生产厂商...【详细内容】
2021-12-08  架构驿站    Tags:分布式系统   点击:(23)  评论:(0)  加入收藏
本系列为 Netty 学习笔记,本篇介绍总结Java NIO 网络编程。Netty 作为一个异步的、事件驱动的网络应用程序框架,也是基于NIO的客户、服务器端的编程框架。其对 Java NIO 底层...【详细内容】
2021-12-07  大数据架构师    Tags:Netty   点击:(17)  评论:(0)  加入收藏
前面谈过很多关于数字化转型,云原生,微服务方面的文章。虽然自己一直做大集团的SOA集成平台咨询规划和建设项目,但是当前传统企业数字化转型,国产化和自主可控,云原生,微服务是不...【详细内容】
2021-12-06  人月聊IT    Tags:架构   点击:(23)  评论:(0)  加入收藏
微服务看似是完美的解决方案。从理论上来说,微服务提高了开发速度,而且还可以单独扩展应用的某个部分。但实际上,微服务带有一定的隐形成本。我认为,没有亲自动手构建微服务的经历,就无法真正了解其复杂性。...【详细内容】
2021-11-26  GreekDataGuy  CSDN  Tags:单体应用   点击:(35)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条