前言
什么情况下需要生成代码呢?
一般,重复操作次数比较多的代码,javaweb技术中数据库表所对应的实体,这些代码有个特点,就是都是根据数据库来进行写get、set方法,还有一种就是mybatis中的这些dao文件,文件内容基本结构一模一样。这种文件一般我们都会选择去生成,而不是手动去写。但是生成代码的方式有很多,但是大多数都是基于模板来生成的,使用的技术也是模板技术,比如:freemarker,jsp这种模板引擎。
使用模板引擎生成代码的优缺点:
优点:
1、不需要写很多代码去实现
2、模板样式可提前定义,使用方便
缺点:
1、模板需要提前定义,使用时需要读取。比如笔者之前使用jetty部署代码生成工具,jetty会默认把资源文件放置在Linux的tmp文件夹下,Linux系统会定时清空tmp文件,这样导致后续使用的时候模板被删除,生成代码失败。
2、定义的模板不能根据业务去动态变更,比如同样是生成实体代码,可能有些涉及日期类型的我需要在字段上添加@xxx注解来格式化时间。如果使用模板需要提前定义占位符,还要根据模板引擎的语法去写条件语句,学习成本高。
3、每生成一类代码,都要新增一套模板,模板复用率低。
jef-code-generator代码生成引擎的优缺点:
优点:
1、纯代码操作,不需要任何第三方依赖。
2、可根据数据库配置自动生成数据库表对应实体
3、可高度定制化。
4、针对生成的代码,可以自定义编译规则。支持动态编译
5、可与任意java项目集成,可根据业务代码的对象去生成代码。
缺点:
1、目前只支持java代码生成
使用示例
基于数据库生成实体
jef-code-generator自带了EntityCodeGenerator,使用EntityCodeGenerator来生成实体代码:
1、配置数据库信息
在jef.properties中配置如下内容:
# 数据库配置
db.type=mysql
db.url=jdbc:mysql://127.0.0.1:3306/ad
db.username=test
db.password=test
# 注释信息
code.style.author=cz
code.style.describe=test
2、执行代码生成
/**
* @author Chengzhi
* @date 2023-05-11
* @测试目的:根据数据库配置自动生成代码
* @预期结果:
*/
@Test
public void test2() throws Exception {
CodeGenerator codeGenerator = new EntityCodeGenerator();
codeGenerator.setFileFolder("target");
codeGenerator.setIpackage("pers.cz.test");
codeGenerator.generateCode();
}
3、查看效果:
自定义代码生成模板
1、编写代码模板
package pers.cz.codegen.template;
import pers.cz.codegen.codegen.CodeGenerator;
import pers.cz.codegen.describe.*;
import pers.cz.codegen.enums.CodeGenerateConfigItem;
import pers.cz.codegen.enums.MethodAnnotationEnum;
import pers.cz.jefconfig.config.JefConfiguration;
import pers.cz.jefconfig.io.Charsets;
import pers.cz.jefconfig.tools.StringUtils;
import java.io.File;
import java.lang.reflect.Modifier;
import java.sql.SQLException;
/**
* @program: jef-code-generator
* @description: 信管代码生成
* @author: Cheng Zhi
* @create: 2022-08-09 18:32
**/
public class ImsBeanCodeGenerator extends CodeGenerator {
@Override
public void generateCode() throws SQLException {
// 从配置文件中获取要生成的类模块名
String s = JefConfiguration.get(CodeGenerateConfigItem.CODE_GEN_CLASSNAME);
for (String className : StringUtils.split(s,";")) {
JavaUnit javaUnit = new JavaUnit(className + "Bean");
javaUnit.setComment(CommentTemplate.classComment);
javaUnit.setIpackage(getIpackage());
//IClass iClassParent = new SimpleClass("BaseBusiBean");
IClass iClassParent = new SimpleClass(this.getClass());
javaUnit.setParent(iClassParent.getSimpleName());
javaUnit.addImport("java.util.List");
javaUnit.addImport("com.ailk.easyframe.web.common.exception.BaseException");
javaUnit.addImport("com.ailk.ims.common.BaseBusiBean");
javaUnit.addImport("com.ailk.ims.ims3h.IMS3hBean");
javaUnit.addImport("com.ailk.openbilling.persistence.imsintf.entity.BaseResponse");
javaUnit.addAnnotation("@LogParamter");
JavaField javaField = new JavaField("req");
javaField.setModifer(Modifier.PRIVATE);
String fieldName = className + "Req";
IClass iClassField = new SimpleClass(fieldName);
javaField.addReturnType(iClassField);
JavaMethodParamter paramter = new JavaMethodParamter();
IClass iClass = new SimpleClass("Object...");
paramter.setParamterType(iClass);
JavaMethod javaMethodInit = new JavaMethod("init");
javaMethodInit.addParamter("input", paramter);
javaMethodInit.addAnnotation(MethodAnnotationEnum.OVERRIDE);
javaMethodInit.addContent("req = (" + fieldName + ") input[0];");
JavaMethod javaMethodValidate = new JavaMethod("validate");
javaMethodValidate.addParamter("input", paramter);
javaMethodValidate.addAnnotation("@Override");
javaMethodValidate.addContent("if (req == null) {");
javaMethodValidate.addContent("throw IMSUtil.throwBusiException(ErrorCodeDefine.COMMON_PARAM_ISNULL, "CollectionFeeMgntDoCheckRequest");");
javaMethodValidate.addContent("}");
JavaMethod javaMethodCreateMain3hBeans = new JavaMethod("createMain3hBeans");
javaMethodCreateMain3hBeans.addParamter("input", paramter);
javaMethodCreateMain3hBeans.addAnnotation("@Override");
javaMethodCreateMain3hBeans.setReturnType("List<IMS3hBean>");
javaMethodCreateMain3hBeans.addContent("return null;");
JavaMethod javaMethodDoBusiness = new JavaMethod("doBusiness");
javaMethodDoBusiness.addParamter("result", paramter);
javaMethodDoBusiness.addAnnotation("@Override");
javaMethodDoBusiness.setReturnType("Object[]");
javaMethodDoBusiness.addContent("return null;");
JavaMethod javaMethodCreateResponse = new JavaMethod("createResponse");
JavaMethodParamter paramterdoBusiness = new JavaMethodParamter();
IClass iClassdoBusiness = new SimpleClass("Object[]");
paramterdoBusiness.setParamterType(iClassdoBusiness);
javaMethodCreateResponse.addParamter("result", paramterdoBusiness);
javaMethodCreateResponse.addAnnotation("@Override");
javaMethodCreateResponse.setReturnType("BaseResponse");
javaMethodCreateResponse.addContent("return null;");
JavaMethod javaMethodDestroy = new JavaMethod("destroy");
javaMethodDestroy.addAnnotation("@Override");
javaUnit.addField(javaField);
javaUnit.addMethod(javaMethodInit);
javaUnit.addMethod(javaMethodValidate);
javaUnit.addMethod(javaMethodCreateMain3hBeans);
javaUnit.addMethod(javaMethodDoBusiness);
javaUnit.addMethod(javaMethodCreateResponse);
javaUnit.addMethod(javaMethodDestroy);
javaUnit.saveToSrcFolder(new File(getFileFolder()), Charsets.UTF8);
}
}
@Override
public void enhanceCode() throws Exception {
}
}
2、自定义配置文件(可根据实际情况来确定是否需要使用配置)
jef.properties配置如下:
code.gen.classname=Test1;Test2;Test3;Test4;Test5;Test6
code.gen.fieldname=Test1Req;Test2Req;Test3Req;Test4Req;Test5Req;Test6Req
3、执行代码生成:
/**
* @author Chengzhi
* @date 2023-05-11
* @测试目的:使用自定义模板自动生成代码
* @预期结果:
*/
@Test
public void test1() throws Exception {
CodeGenerator codeGenerator = new ImsBeanCodeGenerator();
codeGenerator.setFileFolder("target");
codeGenerator.setIpackage("com.ailk.ims.business.acctinterface.aiH5.collectionFeeMgnt");
codeGenerator.generateCode();
}
4、查看结果:
项目地址
https://gitee.com/chengzhi2/jef-code-generator