代码自动生成,避免重复性劳动,程序猿解放时间陪家人

版权声明:本文为博主原创文章,未经博主允许不得转载。安卓五千源码下载--https://blog.csdn.net/wuqilianga/article/details/89185887 https://blog.csdn.net/wuqilianga/article/details/82698371

前序

你有没有觉得自己常常写重复的代码,面试造轮船,上班拧螺丝?
你有没有常觉得,自己明明可以更快地写好功能模块,却要不断地 Ctrl + C 、Ctrl + V ?



一、java代码自动生成系统开发

1.1 开发环境
  • java JDK 8或更新
  • Tomcat 6及以上,tomcat8以上更佳,或者jetty7以上
  • intellij idea 或者 eclipse
  • maven
  • mysql 5.7及以上(非必须)
  • idea 需要安装lombok插件,一块缩减代码的getter setter log等的插件
1.2 已实现目标
  • 通过配置实体模板自动生成MVC层,及mysql的脚本
  • 通过配置现有系统的开发模板(或者开发流程),进行全自动生成各层的代码
1.3 系统推介

系统模块结构图,如下图所示,图中展示了,模板层基础层代码自动生成层,以及各层的必备工具utils层。
系统模块结构图

生成的系统模块逻辑代码如下图所示,这些代码完全是根据模板,通过IO流,配置规则,自动读取包名进行切割完成IO输出,注释和配置分层都会自动生成,代码可以随意更改,完全符合你需要更改成自己的模块生成的自由度。
这里写图片描述



二、系统亮点展示

2.1 亮点一、自动读取实体,根据注释生成js table所需的代码

如下图,是js table节选代码块,如果是做管理后台的页面,bootstrap 里头有js table控件 这是标配了。
这里写图片描述

这里写图片描述

而这一部分,代码的相似性,可以不夸张地说,所有的模块,所有目录下的页面都会包含,如果,每次都要去开发,都要去复制粘贴修改,这是多么痛苦的领悟!

举例说明: 下面有这么一个实体,实现的是机构信息这么个实体。

package com.xxx.cum.vo;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

/**
* 机构信息
* @author XXX
* @version Id; OrgInfo, 2018/8/9 16:17 XXX Exp $$
*/
@Data
public class OrgInfo implements Serializable {

private static final long serialVersionUID = ${gETSerialVersionUID };

        /**
        * ID
        */
        private Long id;


        /**
        * 机构编号
        */
        private String orgCode;

        /**
        * 机构名称
        */
        private String orgName;

        /**
        * 机构全称
        */
        private String orgFullName;

        /**
        * 收款开户行银行编码
        */
        private String bankCode;

        /**
        * 收款开户行名称
        */
        private String bankName;

        /**
        * 收款银行卡账号'
        */
        private String bankCardNo;

        /**
        * 银联分润比例
        */
        private BigDecimal unionpayBenefitRate;

        /**
        * 品牌服务费率
        */
        private BigDecimal brandRate;

        /**
        * 转接清算费率
        */
        private BigDecimal  transferRate;


        /**
        * 付款摘要
        */
        private String payoutSummary;

        /**
        * 是否集团结算 0否 1是
        */
        private String groupSettle;

        /**
        * 是否再付 0否 1是
        */
        private String payAgain;

        /**
        * 公私标识 0对公,1对私
        */
        private String perEntFlag;

        /**
        * 清结算模式 1自主清算 2代理清算 3自主清算+代理清算
        */
        private String settleType;


        /**
        * 协议有效期
        */
        private Date expiredAt;


        /**
        * 机构是否停用状态码(默认0,0未停用、1停用、其他待定)
        */
        private String  state;

        /**
        * 创建时间
        */
        private Date createdAt;

        /**
        * 创建人
        */
        private String createdBy;

        /**
        * 更新时间
        */
        private Date updatedAt;

        /**
        * 更新人
        */
        private String updatedBy;



}

实现步骤:
1)、先读取文件

/**
     * 通过类实体获取DataTable
     * @return
     * @throws IOException
     */
    public static String doSomeThing() throws IOException {
        StringBuilder outputSb = new StringBuilder();

        //读文件
        File directory = new File("F:\\study\\project\\noUsage\\codeGenerator\\dedd\\com.william\\src\\main\\java\\com\\william\\auto\\temp_help\\template_oss_web");
        for (File tempFile : directory.listFiles()) {
            if (tempFile.getName().indexOf(".xml") != -1) {
                FileReader fileReader = new FileReader(tempFile);
                BufferedReader bufferedReader = new BufferedReader(fileReader);
                String s = null;
                StringBuilder sb = new StringBuilder();
                while(( s = bufferedReader.readLine() ) != null ) {
                    //System.out.println(s);
                    sb.append(s);
                }

                List<String> annoList = getRegexAnnotationExp("\\/\\*([^\\*^\\/]*|[\\*^\\/*]*|[^\\**\\/]*)*\\*\\/",sb);
                List<String> fieldList = getRegexFieldExp("private\\s+([a-zA-Z]*)*\\s+([a-zA-Z]*)*",sb);

                for (int i=0;i<fieldList.size();i++) {
                    if (fieldList.size() > i) {
                        if (fieldList.get(i).equalsIgnoreCase("final")) {
                            continue;
                        }

                        //{'title': '选择', 'column': 'id'},
                        String item = "{'title':'"+annoList.get(i)+",'column':'"+fieldList.get(i)+"'},";
                        outputSb.append(item+"\n");
                        //System.out.println(item);
                    }
                }

                //输出结果
                System.out.println(outputSb.toString());
            }
        }
        return outputSb.toString();
    }

2)、读取实体,以注释作为js table的title,属性作为值

/**
     * 读取注释文字
     * @param regexExp
     * @param sb
     */
    private static List<String> getRegexAnnotationExp(String regexExp, StringBuilder sb) {
        List<String> resultList = new ArrayList<String>();

        Pattern pattern = Pattern.compile(regexExp);
        String searchPlainText = sb.toString();
        Matcher matcher = pattern.matcher(searchPlainText);
        while (matcher.find()) {
            String groupExp = matcher.group(0).replaceAll("/\\*+\\s+\\*","").replaceAll("\\s+\\*/","");
            resultList.add(groupExp);
            //System.out.println("匹配到:"+groupExp+"  位置:(" + matcher.start()+","+matcher.end()+")");
        }
        return resultList;
    }

    /**
     * 读取属性field
     * @param regexExp
     * @param sb
     */
    private static List<String> getRegexFieldExp(String regexExp,StringBuilder sb) {
        List<String> resultList = new ArrayList<String>();

        Pattern pattern = Pattern.compile(regexExp);
        String searchPlainText = sb.toString();
        Matcher matcher = pattern.matcher(searchPlainText);
        while (matcher.find()) {
            String groupExp = matcher.group(0).replaceAll("private\\s+([a-zA-Z]*)*\\s+","");
            resultList.add(groupExp);
            //System.out.println("匹配到:"+groupExp+"  位置:(" + matcher.start()+","+matcher.end()+")");
        }
        return resultList;
    }

生成的结果如下:

{'title':' 机构编号,'column':'orgCode'},
{'title':' 机构名称,'column':'orgName'},
{'title':' 机构全称,'column':'orgFullName'},
{'title':' 收款开户行银行编码,'column':'bankCode'},
{'title':' 收款开户行名称,'column':'bankName'},
{'title':' 收款银行卡账号','column':'bankCardNo'},
{'title':' 银联分润比例,'column':'unionpayBenefitRate'},
{'title':' 品牌服务费率,'column':'brandRate'},
{'title':' 转接清算费率,'column':'transferRate'},
{'title':' 付款摘要,'column':'payoutSummary'},
{'title':' 是否集团结算 01是,'column':'groupSettle'},
{'title':' 是否再付 0否 1是,'column':'payAgain'},
{'title':' 公私标识 0对公,1对私,'column':'perEntFlag'},
{'title':' 清结算模式 1自主清算 2代理清算 3自主清算+代理清算,'column':'settleType'},
{'title':' 协议有效期,'column':'expiredAt'},
{'title':' 机构是否停用状态码(默认0,0未停用、1停用、其他待定),'column':'state'},
{'title':' 创建时间,'column':'createdAt'},
{'title':' 创建人,'column':'createdBy'},
{'title':' 更新时间,'column':'updatedAt'},
{'title':' 更新人,'column':'updatedBy'},


2.2 自动替换代码模板的内容(代码为节选块)
File templateDirectory = new File(mybatisPath);
            if (templateDirectory.isDirectory()) {
                File[] templateFiles = templateDirectory.listFiles();
                for (File templateFileItem : templateFiles) {
                    String suffixGenerate = ".xml";
                    String template = "";
                    FileReader fr = new FileReader(templateFileItem);

                    BufferedReader br = new BufferedReader(fr);
                    String s,packagePath = "";

                    while ((s = br.readLine()) != null) {
                        if(s.trim().startsWith("package ")){
                            suffixGenerate = ".java";
                            packagePath = s;
                            packagePath = packagePath.replaceAll("package","").trim().toLowerCase().replaceAll(";","");
                            logger.info("package  path: " + packagePath + "\n");
                        }
                        template += s + "\n";
                    }
                    fr.close();

                    // 替换内容
                    template = StringUtils.toReplaceTemplateKey(template, new String[]{
                                    "Template",
                                    "template",
                                    "author",
                                    "TemplateCN",
                                    "DateTime",
                                    "TemplateUpdateReturn",
                                    "TemplateDeleteReturn",
                                    "TemplateAddReturn",
                                    "TemplateReturnUpdateType",
                                    "TemplateReturnDeleteType",
                                    "TemplateReturnAddType"
                            },
                            new String[]{
                                    className,
                                    StringUtils.toLower(className),
                                    author,
                                    classCNName,
                                    new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()),
                                    TemplateUpdateReturn,
                                    TemplateDeleteReturn,
                                    TemplateAddReturn,
                                    TemplateReturnUpdateType,
                                    TemplateReturnDeleteType,
                                    TemplateReturnAddType
                            });

                    String realProjectFilePath = "";
                    for (String tempPath:packagePath.split("\\.")) {
                        logger.info("tempPath:" + tempPath + "\tpackagePath:"+packagePath);
                        if (StringUtils.isNull(realProjectFilePath)) {
                            realProjectFilePath = realProjectFilePath + tempPath ;
                        } else {
                            realProjectFilePath = realProjectFilePath +File.separator+ tempPath ;
                        }
                        logger.info("切割后生成的目录为:==> packagePath:"+realProjectFilePath);
                    }

                    String path = PROJECT_PATH + File.separator + PropertiesHelper.getValueByKey("rootPackage").replaceAll("\\.","\\\\") + File.separator + yyyyMMddHHmmss + File.separator+ realProjectFilePath + File.separator;
                    File file = new File(path);
                    if(!file.exists()){
                        file.mkdirs();
                    }

                    //File fileBiz = new File(path + "\\" + fileNameTemplate + suffixTemplate);

                    String fileItemName = templateFileItem.getName().replaceAll("_","").replaceAll("CustInfoConfig",className).replaceAll("Template",className).split("\\.")[0];


                    FileWriter fw = new FileWriter(path + File.separator + fileItemName + suffixGenerate);
                    BufferedWriter bw = new BufferedWriter(fw);
                    bw.write(template);
                    bw.close();
                    logger.info("生成测试类文件:[" + fileItemName + suffixGenerate + "]成功" );
                    logger.info("文件根目录点击打开:[" + "file:" + File.separator + File.separator+ File.separator + path + "]成功" );
                }

如你所有的模板中,有个类注解

/**
 * ${TemplateCN}查询请求
 * @author ${author}
 * @version Id: ${Template}QueryRequest.java , ${DateTime}  ${author} Exp $
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class ${Template}QueryRequest extends CumRequest {

模板中的${TemplateCN} ,${author} ,${Template},${DateTime}
可以通过全局文件的替换功能,实现替换
替换后的效果:

/**
 * 商户查询请求
 * @author zs
 * @version Id: OssCustInstRateQueryRequest.java , 2018-09-03 17:08  zs Exp $
 */
2.3 自动生成各层的MVC代码,及数据库
/**
     * 开始执行自动生成代码
     * @param className
     */
    private static void autoGenerator(String className) {
        try{
            //生成实体对象
            Class.forName(entityPackage + "." + className);

            //生成实体文件
            writeEntity(className);

            //生成dao
            writeDao(className);

            //生成service
            writeService(className);

            //生成service的实现类
            writeServiceImpl(className);

            //生成controller类
            writeController(className);

            //生成xml文件
            writeXml(className);

            //生成ServiceTest的实现类
            writeFileBeforeReplace(className,"TemplateManageServiceTest",className + "ManageServiceTest",".xml",".java");

            //生成dubbo-service-provider.xml配置文件
            writeDubboProviderXml(className);

            System.out.println("\n======生成的建表语句如下:======");
            System.out.println(SqlGenerator.generateSql(entityPackage + "." + className,"id"));
        }catch (Exception e){
            logger.error(e.getStackTrace(),e);
        }
    }

如dao层、sql脚本生成的代码节选:

/**
     * 生成dao代码
     * @param className
     */
    private static void writeDao(String className) {
        String daoPath = StringUtils.getJavaPath() + templatePackage;
        try {
            String targetDao = PROJECT_PATH + File.separator + PropertiesHelper.getValueByKey("rootPackage").replaceAll("\\.","/") + File.separator + "dao//";
            File file = new File(targetDao);
            if(!file.exists()){
                file.mkdirs();
            }
            File fileAction = new File(targetDao + className + "Dao.java");
            if (!fileAction.exists()) {
                String template = "";
                FileReader fr = new FileReader(daoPath + "TemplateDao.java");

                BufferedReader br = new BufferedReader(fr);
                String s;
                boolean started = false;
                while ((s = br.readLine()) != null) {
                    if(s.startsWith("package")){
                        //重新赋值
                        s = "package " + PropertiesHelper.getValueByKey("rootPackage") + ".dao;";
                    }
                    if(!started){
                        if(s.startsWith("import")){
                            String entityClass = PropertiesHelper.getValueByKey("rootPackage") + ".entity." + className + ";";
                            template += "import " + entityClass + "\n";
                            started = true;
                        }
                    }
                    template += s + "\n";
                }
                fr.close();

                // 替换内容
                template = template.replaceAll("Template", className).replaceAll("template", className);

                FileWriter fw = new FileWriter(targetDao + className + "Dao.java");
                BufferedWriter bw = new BufferedWriter(fw);
                bw.write(template);
                bw.close();
            }
            logger.info("生成dao类:[" + className + "Dao]成功" );
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



sql脚本根据配置的实体生成:


public class SqlGenerator {

    static Logger logger = Logger.getLogger(SqlGenerator.class);

    public static void main(String[] args) {
        String className = "User";
        System.out.println(generateSql(className,"id"));
    }

    /**
     * 根据实体类生成建表语句
     * @author
     * @param className 全类名
     */
    public static String generateSql(String className,String indexKey){
        try {
            Class<?> clz = Class.forName(className);
            className = clz.getSimpleName();
            Field[] fields = clz.getDeclaredFields();
            StringBuffer column = new StringBuffer();
            String varchar = " varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,";
            for (Field f : fields) {
                boolean isStatic = Modifier.isStatic(f.getModifiers());
                if(!isStatic) {
                    if (indexKey.equals(f.getName())) {
                        column.append("\n\t`" + f.getName() + "` int(11) NOT NULL AUTO_INCREMENT,");
                    } else {
                        Class type = f.getType();
                        if (type == String.class) {
                            column.append("\n\t`" + f.getName() + "`" + varchar);
                        }
                    }
                }
            }
            StringBuffer sql = new StringBuffer();
            sql.append("DROP TABLE IF EXISTS `"+ RuleUtils.getTableNameByBean(className) + "`; ")
                    .append("\nCREATE TABLE `"+ RuleUtils.getTableNameByBean(className) + "`(")
                    .append(column)
                    .append(" \n\t PRIMARY KEY (`" + indexKey + "`) USING BTREE")
                    .append("\n) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci;");
            return sql.toString();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            logger.debug("该类未找到!");
            return null;
        }
    }
}


代码下载

代码目录


对本代码感兴趣的同学,可以下载下来使用,下载地址
对本代码感兴趣的同学,可以下载下来使用,下载地址
对本代码感兴趣的同学,可以下载下来使用,下载地址



猜你喜欢

转载自blog.csdn.net/wuqilianga/article/details/82698371