SpringBoot怎么整合freemarker实现代码生成器
一、介绍
在实际的软件项目开发过程中,我可以很负责任的跟大家说,如果你真的实际写代码的时间超过5年,你对增删改查这类简单的功能需求开发,可以说已经完全写吐了,至少我就是这种类型的。
但是呢,不可否认,绝大多数的软件功能,向下追随到最基本的单元,也基本都是单表的增、删、改、查!
只是随着用户需求不断增多,原来可能一个张单表就可以搞定的事情,现在可能需要多张表,或者多个库才能搞定,代码层就像堆积木一样,越堆越复杂。
我记得早期做项目的时候,项目每新加一张单表,我都需要在代码层,按照MVC
框架的思想,重新编写一套CURD
的代码,写完所有的基础的增删改查,至少需要20分钟,手快的情况下,最快也要10分钟。
假如某个新开发的功能,要新增10张表,按照这个时间计算,至少要100分钟,仔细想想,其实你会发现大部分的时间都浪费在这些简单而又重复的编程圈子中去了。
那有没有一个办法,将这些简单的CURD
代码,全部都标准化、公共化呢?这样我们的可以省下很多时间来投入业务场景的开发。
答案是肯定的,有!
我记得早期我最先接触的是MybatisGenertor
工具包,通过这个工具包,我们可以省去大部分的mybaits
中xml
文件的curd
编写工作。
还有我们所熟悉的JPA
,里面有一套公共的持久层动态代理类,它可以自动根据名称生成SQL
语句,能为开发省下不少的事情。
但是我这个人比较懒,我想搞一个工具,从controller
、service
、entity
、dao
层,全部的crud
代码,包括单元测试类,通过工具自动生成好。
像这样的工具,现在网上也有不少,例如我们所熟悉的Mybatis-plus
插件,它就可以做到这一点,也是非常好用。
但是有的公司就不喜欢它,原因也很简单,里面的很多公共方法封装的过于深入,而且很多crud
的sql
全部都是动态生成,你根本看不到。
总之啊就是一句,不在自己掌控之内的,很多程序员总是带着各种疑虑~~
当然,还有一个明显的疑虑,就是对微服务的开发,不能全面支持,比如你项目采用的是SpringBoot +Dubbo
组合来开发,这个时候生成的controller
,完全没啥用处,而且还很鸡肋。
因此在这种情况下,你得基于当前的项目软件开发规则,自己开发一套代码生成器,以满足快速开发的需要。
下面我就简单的介绍一下,如何自行开发一套代码生成器,过程如下!
二、代码实践
其实开发一套代码生成器,真没大家想象中的那么复杂,其中用的最重要一项技术,就是利用模板来生成代码,例如我们经常使用的模板引擎freemarker
,它就可以帮助我们实现这一点。
2.1、首先我们添加 freemarker 依赖包
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>
2.2、然后创建一个代码模版
下面我们以动态创建实体类为例,编写一个实体类的模板entity.java.ftl
,其中${}
里面定义的是动态变量。
package ${package}; import java.io.Serializable; /** * <p> * ${tableComment} * </p> * * @author ${author} * @since ${date} */ public class ${entityClass} implements Serializable { private static final long serialVersionUID = 1L; <#--属性遍历--> <#list columns as pro> /** * ${pro.comment} */ private ${pro.propertyType} ${pro.propertyName}; </#list> <#--属性get||set方法--> <#list columns as pro> public ${pro.propertyType} get${pro.propertyName?cap_first}() { return this.${pro.propertyName}; } public ${entityClass} set${pro.propertyName?cap_first}(${pro.propertyType} ${pro.propertyName}) { this.${pro.propertyName} = ${pro.propertyName}; return this; } </#list> }
2.3、最后生成目标代码
最后我们基于freemarker
编写一个测试类!
public class CodeGeneratorDemo { public static void main(String[] args) throws IOException, TemplateException { Map<String, Object> objectMap = new HashMap<>(); //定义包路径 objectMap.put("package", "com.example.test"); //定义实体类 objectMap.put("entityClass", "Student"); //定义实体类属性 List<Map<String, Object>> columns = new ArrayList<>(); //姓名字段 Map<String, Object> column1 = new HashMap<>(); column1.put("propertyType", "String"); column1.put("propertyName", "name"); column1.put("comment", "姓名"); columns.add(column1); //年龄字段 Map<String, Object> column2 = new HashMap<>(); column2.put("propertyType", "Integer"); column2.put("propertyName", "age"); column2.put("comment", "年龄"); columns.add(column2); //定义类的属性 objectMap.put("columns", columns); //定义作者 objectMap.put("author", "张三"); //定义创建时间 objectMap.put("date", new SimpleDateFormat("yyyy-MM-dd").format(new Date())); //定义类描述 objectMap.put("tableComment", "学生信息"); //生产目标代码 Configuration configuration = new Configuration(Configuration.VERSION_2_3_23); configuration.setDefaultEncoding(Charset.forName("UTF-8").name()); configuration.setClassForTemplateLoading(CodeGeneratorDemo.class, "/"); Template template = configuration.getTemplate("/templates/entity.java.ftl"); FileOutputStream fileOutputStream = new FileOutputStream(new File("../src/main/java/com/example/generator/Student.java")); template.process(objectMap, new OutputStreamWriter(fileOutputStream, Charset.forName("UTF-8").name())); fileOutputStream.close(); System.out.println("文件创建成功"); } }
运行程序,输出的文件结果如下!
package com.example.test; import java.io.Serializable; /** * <p> * 学生信息 * </p> * * @author 张三 * @since 2021-08-22 */ public class Student implements Serializable { private static final long serialVersionUID = 1L; /** * 姓名 */ private String name; /** * 年龄 */ private Integer age; public String getName() { return this.name; } public Student setName(String name) { this.name = name; return this; } public Integer getAge() { return this.age; } public Student setAge(Integer age) { this.age = age; return this; } }
与预期的效果一致,成功生成!
例如小编我就是采用这种方式,首先把要通过工具生成的代码,全部通过模板方式定义好。
然后通过连接数据库的方式,把需要自动生成的表结构查询出来,封装成数据渲染参数,最后传入到freemarker
中去,非常简单、快速的生成与自己预期想要的代码,所有单表的crud
全部一步到位!
下面这个就是小编,基于当前项目定制开发的一款代码生成器,项目采用SpringBoot + Dubbo
框架开发,没有Controller
层,截图中所有的代码全部都是采用代码生成器生成的,直接通过单元测试就可以运行,开发的时候非常快!
以上是SpringBoot怎么整合freemarker实现代码生成器的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

Jasypt介绍Jasypt是一个java库,它允许开发员以最少的努力为他/她的项目添加基本的加密功能,并且不需要对加密工作原理有深入的了解用于单向和双向加密的高安全性、基于标准的加密技术。加密密码,文本,数字,二进制文件...适合集成到基于Spring的应用程序中,开放API,用于任何JCE提供程序...添加如下依赖:com.github.ulisesbocchiojasypt-spring-boot-starter2.1.1Jasypt好处保护我们的系统安全,即使代码泄露,也可以保证数据源的

使用场景1、下单成功,30分钟未支付。支付超时,自动取消订单2、订单签收,签收后7天未进行评价。订单超时未评价,系统默认好评3、下单成功,商家5分钟未接单,订单取消4、配送超时,推送短信提醒……对于延时比较长的场景、实时性不高的场景,我们可以采用任务调度的方式定时轮询处理。如:xxl-job今天我们采

一、Redis实现分布式锁原理为什么需要分布式锁在聊分布式锁之前,有必要先解释一下,为什么需要分布式锁。与分布式锁相对就的是单机锁,我们在写多线程程序时,避免同时操作一个共享变量产生数据问题,通常会使用一把锁来互斥以保证共享变量的正确性,其使用范围是在同一个进程中。如果换做是多个进程,需要同时操作一个共享资源,如何互斥呢?现在的业务应用通常是微服务架构,这也意味着一个应用会部署多个进程,多个进程如果需要修改MySQL中的同一行记录,为了避免操作乱序导致脏数据,此时就需要引入分布式锁了。想要实现分

springboot读取文件,打成jar包后访问不到最新开发出现一种情况,springboot打成jar包后读取不到文件,原因是打包之后,文件的虚拟路径是无效的,只能通过流去读取。文件在resources下publicvoidtest(){Listnames=newArrayList();InputStreamReaderread=null;try{ClassPathResourceresource=newClassPathResource("name.txt");Input

SpringBoot和SpringMVC都是Java开发中常用的框架,但它们之间有一些明显的差异。本文将探究这两个框架的特点和用途,并对它们的差异进行比较。首先,我们来了解一下SpringBoot。SpringBoot是由Pivotal团队开发的,它旨在简化基于Spring框架的应用程序的创建和部署。它提供了一种快速、轻量级的方式来构建独立的、可执行

在Springboot+Mybatis-plus不使用SQL语句进行多表添加操作我所遇到的问题准备工作在测试环境下模拟思维分解一下:创建出一个带有参数的BrandDTO对象模拟对后台传递参数我所遇到的问题我们都知道,在我们使用Mybatis-plus中进行多表操作是极其困难的,如果你不使用Mybatis-plus-join这一类的工具,你只能去配置对应的Mapper.xml文件,配置又臭又长的ResultMap,然后再去写对应的sql语句,这种方法虽然看上去很麻烦,但具有很高的灵活性,可以让我们

1、自定义RedisTemplate1.1、RedisAPI默认序列化机制基于API的Redis缓存实现是使用RedisTemplate模板进行数据缓存操作的,这里打开RedisTemplate类,查看该类的源码信息publicclassRedisTemplateextendsRedisAccessorimplementsRedisOperations,BeanClassLoaderAware{//声明了key、value的各种序列化方式,初始值为空@NullableprivateRedisSe

在项目中,很多时候需要用到一些配置信息,这些信息在测试环境和生产环境下可能会有不同的配置,后面根据实际业务情况有可能还需要再做修改。我们不能将这些配置在代码中写死,最好是写到配置文件中,比如可以把这些信息写到application.yml文件中。那么,怎么在代码里获取或者使用这个地址呢?有2个方法。方法一:我们可以通过@Value注解的${key}即可获取配置文件(application.yml)中和key对应的value值,这个方法适用于微服务比较少的情形方法二:在实际项目中,遇到业务繁琐,逻
