一个java代码生成器的简单实现

Posted qiyongkang520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个java代码生成器的简单实现相关的知识,希望对你有一定的参考价值。

最近,一直跟着公司技术牛人在搞大数据相关的东西,主要涉及的是环境搭建,同时也了解下整个hadoop生态系统相关的东西,真是让我大开眼界,这个在之后的博文中再来与大家分享。
今天,笔者给大家介绍一个代码生成器,这个是笔者的主管写的,写的确实不错,主要是基于公司的jquery easyUI + springMVC + myBatis这套框架写的,可以根据一个数据库表生成model、mapper.xml、dao接口以及service、controller、jsp页面等相关的东西,包含增删改查等操作,节省开发时间。然后,笔者在此代码生成器上修改了几个bug,同时兼容了一下mysql
这个代码生成器工具使用的核心是freemarker,一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。
下面,笔者开始进行核心代码的介绍。
首先,我们必须指定哪张表,然后通过jdbc获取这个表的信息以及表字段相关的信息。
这里,将所有的配置写入config.properties:

###数据库表与model的映射
taskhistory=TaskHistory

###数据源配
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://172.31.26.156:3306/test
username=root
password=root
db=mysql

###每个用户对应一个同名的schema,注意配置,不然会搜索每个schema
schemaPattern=root
tableNamePattern=%taskhistory
sEQNamePattern=%TM0101_SE

###model包名
modelPackage=com.qiyongkang.sys.model
###model保存文件路径
modelSavePath=D:\\\\develop\\\\model\\\\

###mapper接口包名
mapperPackage=com.qiyongkang.sys.dao
###mapper接口保存文件路径
mapperSavePath=D:\\\\develop\\\\dao\\\\

###mapper.xml的文件路径
mapperXmlSavePath=D:\\\\develop\\\\mapping\\\\oracle\\\\

###service的包名
servicePackage=com.qiyongkang.sys.service.impl

###service的保存文件路径
serviceSavePath=D:\\\\develop\\\\service\\\\impl\\\\

###service interface的包名
serviceInterfacePackage=com.qiyongkang.sys.service
###service interface的保存文件路径
serviceInterfaceSavePath=D:\\\\develop\\\\service\\\\

###control包名
controllerPackage=com.qiyongkang.sys.ctrl

###control文件路径
controllerSavePath=D:\\\\develop\\\\ctrl\\\\

###junit包名
junitPackage=com.qiyongkang.test.system.service

###junit文件路径
junitSavePath=D:\\\\develop\\\\test\\\\java\\\\com\\\\qiyongkang\\\\test\\\\system\\\\service\\\\

###js文件路径
jsHomeSavePath=D:\\\\develop\\\\WebContent\\\\js\\\\modules\\\\system\\\\

###jsp文件路径
jspHomeSavePath=D:\\\\develop\\\\WebContent\\\\WEB-INF\\\\views\\\\system\\\\

###是否生成model
modelFlag=true

###是否生成mapper
mapperFlag=true

###是否生成mapper.xml
mapperXmlFlag=true

###是否生成service
serviceFlag=true

###是否生成service接口
serviceImplFlag=true

###是否生成control
controlFlag=true

###是否生成junit
junitFlag=false

###是否生成easyUIJs
easyUIJsFlag=false

###是否生成easyUIJsp
easyUIJspFlag=false

###是否生成extJs
extJsFlag=false

###备份文件路径
fileBakPath=D:\\\\develop\\\\bakFile\\\\

##项目名称
projectName=qyk_testSpringMVC

然后,再来看看获取数据库信息相关的代码:

package com.codegenerator.framework.service.impl;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import com.codegenerator.core.utils.ConfigUtil;
import com.codegenerator.framework.model.ColumnInfo;
import com.codegenerator.framework.model.ConnectConfig;
import com.codegenerator.framework.model.ModelInfo;
import com.codegenerator.framework.model.TableInfo;
import com.codegenerator.framework.service.DataBaseService;

public class DataBaseServiceImpl implements DataBaseService 
    private static Logger logger = LogManager.getLogger(DataBaseServiceImpl.class);

    @Override
    public List<ModelInfo> loadModelInfo(ConnectConfig connectConfig) 
        ModelInfo.tableNamePex = connectConfig.getTableNamePattern();
        logger.info("表前缀:", ModelInfo.tableNamePex);

        ModelInfo.sEQNamePex = connectConfig.getsEQNamePattern();
        logger.info("序列前缀:", ModelInfo.sEQNamePex);

        List<ModelInfo> mList = new ArrayList<ModelInfo>();
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        logger.info("驱动类:", connectConfig.getDriverClassName());
        dataSource.setDriverClassName(connectConfig.getDriverClassName());

        logger.info("url:", connectConfig.getUrl());
        dataSource.setUrl(connectConfig.getUrl());

        logger.info("userName:", connectConfig.getUsername());
        dataSource.setUsername(connectConfig.getUsername());

        logger.info("password:", connectConfig.getPassword());
        dataSource.setPassword(connectConfig.getPassword());

        Properties pro = connectConfig.getConnectionPros();

        logger.info("设置连接属性:", pro.stringPropertyNames());
        dataSource.setConnectionProperties(pro);

        Connection conn = null;
        //表查询结果集
        ResultSet tableRS = null;

        try 
            conn = dataSource.getConnection();
            DatabaseMetaData dbMetaData = conn.getMetaData();

            logger.info("Catalog:", connectConfig.getCatalog());
            logger.info("SchemaPattern:", connectConfig.getSchemaPattern());
            logger.info("TableNamePattern:", connectConfig.getTableNamePattern());
            logger.info("Types:", Arrays.toString(connectConfig.getTypes()));

            //获取表的结果集
            tableRS = dbMetaData.getTables(connectConfig.getCatalog(), connectConfig.getSchemaPattern(), connectConfig.getTableNamePattern(),
                    connectConfig.getTypes());

            while (tableRS.next()) 
                String tableName = tableRS.getString("TABLE_NAME");
                logger.info("tableName:", tableName);
                if (tableName.indexOf("$") == -1 && !connectConfig.getExclusionMap().containsKey(tableName)) 
                    if (ConfigUtil.getConfig(tableName) == null) 
                        continue;
                    
                    ModelInfo modelInfo = new ModelInfo();
                    TableInfo tableInfo = new TableInfo();
                    tableInfo.setName(tableName);

                    logger.info("表的注释:", tableName, tableRS.getString("REMARKS"));
                    tableInfo.setRemark(tableRS.getString("REMARKS"));

                    logger.info("表的类型:", tableName, tableRS.getString("TABLE_TYPE"));
                    tableInfo.setType(tableRS.getString("TABLE_TYPE"));

                    //获取列的结果集
                    ResultSet columnRS = dbMetaData.getColumns(null, connectConfig.getSchemaPattern(), tableName, "%");

                    List<ColumnInfo> ciList = new ArrayList<ColumnInfo>();
                    while (columnRS.next()) 
                        String columnName = columnRS.getString("COLUMN_NAME");
                        logger.info("字段名称:", columnName);

                        String columnType = columnRS.getString("TYPE_NAME").toUpperCase();
                        logger.info("字段类型:", columnType);

                        String columnRemark = columnRS.getString("REMARKS");
                        logger.info("字段注释:", columnRemark);

                        int len = columnRS.getInt("COLUMN_SIZE");
                        logger.info("字段长度:", len);

                        int precision = columnRS.getInt("DECIMAL_DIGITS");
                        logger.info("字段类型精度:", precision);

                        if (columnName == null || "".equals(columnName)) 
                            continue;
                        

                        ColumnInfo ci = new ColumnInfo();
                        ci.setName(columnName);
                        ci.setType(columnType);
                        ci.setRemark(columnRemark);
                        ci.setLen(len);
                        ci.setPrecision(precision);

                        ciList.add(ci);
                    
                    tableInfo.setColumnList(ciList);
                    modelInfo.setmTable(tableInfo, connectConfig.getIdMap());
                    mList.add(modelInfo);
                    columnRS.close();
                
            
            tableRS.close();
         catch (Exception e) 
            e.printStackTrace();
            logger.error("获取表、字段相关信息异常。。", e);
         finally 
            try 
                conn.close();
             catch (SQLException e) 
                e.printStackTrace();
            
        
        return mList;
    


这里,是将获取到的信息用ModelInfo.java这个实体封装:

package com.codegenerator.framework.model;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

import com.codegenerator.core.utils.ConfigUtil;
import com.codegenerator.core.utils.StringUtil;
import com.codegenerator.framework.flt.service.ModelFtlService;
import com.codegenerator.framework.service.TypeHandler;

public class ModelInfo implements ModelFtlService 
    private String className;
    private String packageName;
    private String savePath;
    private TableInfo mTable;
    private String fileName;
    private String remark;
    public static String tableNamePex;
    public static String sEQNamePex;
    private String idCol;
    private String idPro;
    private String idColType;
    private String idProType;
    private String[] cols;
    private String[] pros;
    private String[] jdbcTypes;
    private String[] javaTypes;
    private Map<String, TypeHandler> dtoProMap = new HashMap<String, TypeHandler>();
    private Map<String, TypeHandler> modelProMap = new HashMap<String, TypeHandler>();
    private String name;
    private String sEQName;
    private String dtoFileName;

    public Map<String, TypeHandler> getDtoProMap() 
        return dtoProMap;
    

    public void setDtoProMap(Map<String, TypeHandler> dtoProMap) 
        this.dtoProMap = dtoProMap;
    

    public String getDtoFileName() 
        return dtoFileName;
    

    public void setDtoFileName(String dtoFileName) 
        this.dtoFileName = dtoFileName;
    

    public String[] getJdbcTypes() 
        return jdbcTypes;
    

    public void setJdbcTypes(String[] jdbcTypes) 
        this.jdbcTypes = jdbcTypes;
    

    public String[] getJavaTypes() 
        return javaTypes;
    

    public void setJavaTypes(String[] javaTypes) 
        this.javaTypes = javaTypes;
    

    public static String getsEQNamePex() 
        return sEQNamePex;
    

    public static void setsEQNamePex(String sEQNamePex) 
        ModelInfo.sEQNamePex = sEQNamePex;
    

    public String getsEQName() 
        return sEQName;
    

    public void setsEQName(String sEQName) 
        this.sEQName = sEQName;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String[] getCols() 
        return cols;
    

    public void setCols(String[] cols) 
        this.cols = cols;
    

    public String[] getPros() 
        return pros;
    

    public void setPros(String[] pros) 
        this.pros = pros;
    

    public void setmTable(TableInfo mTable) 
        this.mTable = mTable;
    

    public static String getTableNamePex() 
        return tableNamePex;
    

    public static void setTableNamePex(String tableNamePex) 
        ModelInfo.tableNamePex = tableNamePex;
    

    public String getIdColType() 
        return idColType;
    

    public void setIdColType(String idColType) 
        this.idColType = idColType;
    

    public String getIdProType() 
        return idProType;
    

    public void setIdProType(String idProType) 
        this.idProType = idProType;
    

    public void setIdCol(String idCol) 
        this.idCol = idCol;
    

    public void setIdPro(String idPro) 
        this.idPro = idPro;
    

    public String getRemark() 
        return remark;
    

    public void setRemark(String remark) 
        this.remark = remark;
    

    public String getFileName() 
        return fileName;
    

    public void setFileName(String fileName) 
        this.fileName = fileName;
    

    public String getPackageName() 
        return packageName;
    

    public void setPackageName(String packageName) 
        this.packageName = packageName;
    

    public String getSavePath() 
        return savePath;
    

    public void setSavePath(String savePath) 
        this.savePath = savePath;
    

    public TableInfo getmTable() 
        return mTable;
    

    public void setmTable(TableInfo mTable, Map<String, String> idMap) 

        String tableName = ConfigUtil.getConfig(mTable.getName());
        if (tableName == null || "".equals(tableName)) 
            return;
        
        this.mTable = mTable;
        if (this.className == null) 
            setClassName(StringUtil.getClassName(mTable.getName(), tableNamePex));
        
        if (this.sEQName == null) 
            setsEQName(StringUtil.getSEQName(mTable.getName(), tableNamePex, sEQNamePex));
        
        if (this.fileName == null) 
            setFileName(getClassName() + ".java");
        
        if (this.dtoFileName == null) 
            setDtoFileName(getClassName() + "Dto.java");
        
        if (this.remark == null) 
            setRemark(mTable.getRemark());
        
        if (this.name == null) 
            setName(StringUtil.getClassAlias(mTable.getName(), tableNamePex));
        
        ColumnInfo col = null;
        boolean hasConfig = idMap.containsKey(mTable.getName());
        List<ColumnInfo> colList = mTable.getColumnList();
        int len = colList.size() - 1;
        cols = new String[len];
        pros = new String[len];
        jdbcTypes = new String[len];
        javaTypes = new String[len];
        len = 0;
        for (ColumnInfo ci : colList) 
            if ((hasConfig && idMap.get(mTable.getName()).equalsIgnoreCase(ci.getName()))
                    || ci.getName().equalsIgnoreCase("id")) 
                //主键
                col = ci;
             else 
                if (ci.getName() != null) 
                    cols[len] = ci.getName();
                    pros[len] = ci.getPropertyInfo().getName();
//                    jdbcTypes[len] = ci.getPropertyInfo().getJdbcType();
                    javaTypes[len] = ci.getPropertyInfo().getClassName();
//                    if ("TIMESTAMP".equalsIgnoreCase(jdbcTypes[len])) 
//                        TypeHandler mHandler = new DateHandler(ci.getPropertyInfo(), ci);
//                        dtoProMap.put(cols[len], mHandler);
//                        modelProMap.put(pros[len], mHandler);
//                    
                    len++;
                
            
        
        if (col != null) 
            setIdCol(col.getName());
            setIdPro(col.getPropertyInfo().getName());
            setIdColType(col.getType());
            setIdProType(col.getPropertyInfo().getClassName());
        

    

    public void setClassName(String className) 
        this.className = className;
    

    @Override
    public String getPackageStr() 
        return "package " + getPackageName() + ";";
    

    @Override
    public String getImportStr() 
        StringBuffer sb = new StringBuffer("\\r\\n");
        Map<String, String> imMap = new HashMap<String, String>();
        List<ColumnInfo> cifs = mTable.getColumnList();
        for (ColumnInfo cif : cifs) 
            PropertyInfo pi = cif.getPropertyInfo();
            String imStr = "import " + pi.getPackageName() + "." + pi.getClassName() + ";\\r\\n";
            if (pi.getPackageName() != null && !imMap.containsKey(imStr)) 
                sb.append(imStr);
                imMap.put(imStr, imStr);
            
        

        String imStr = "import java.util.Date;\\r\\n";
        if (modelProMap.size() > 0 && !imMap.containsKey(imStr)) 
            sb.append(imStr);
            imMap.put(imStr, imStr);
        
        return sb.length() > 0 ? sb.toString() : null;
    

    @SuppressWarnings("rawtypes")
    @Override
    public String getPropertiesStr() 
        StringBuffer sb = new StringBuffer("\\r\\n");
        List<ColumnInfo> cifs = mTable.getColumnList();
        for (ColumnInfo cif : cifs) 
            PropertyInfo pi = cif.getPropertyInfo();
            sb.append(" /**\\r\\n");
            sb.append("  *" + pi.getRemark() + "\\r\\n");
            sb.append("  */\\r\\n");
            sb.append(" private " + pi.getClassName() + " " + pi.getName() + ";\\r\\n");

        

        Set set = modelProMap.keySet();
        Iterator it = set.iterator();
        while (it.hasNext()) 
            String key = (String) it.next();
            sb.append(" /**\\r\\n");
            sb.append("  *查询起始时间\\r\\n");
            sb.append("  */\\r\\n");
            sb.append(" private Date " + key + "Before;\\r\\n");
            sb.append(" /**\\r\\n");
            sb.append("  *查询截止时间\\r\\n");
            sb.append("  */\\r\\n");
            sb.append(" private Date " + key + "After;\\r\\n");

        
        return sb.length() > 0 ? sb.toString() : null;
    

    @SuppressWarnings("rawtypes")
    @Override
    public String getMethodStr() 
        StringBuffer sb = new StringBuffer("\\r\\n");
        List<ColumnInfo> cifs = mTable.getColumnList();
        for (ColumnInfo cif : cifs) 
            PropertyInfo pi = cif.getPropertyInfo();
            sb.append("\\r\\n /**  \\r\\n    *设置 :" + pi.getRemark() + "\\r\\n     */\\r\\n");
            sb.append(" public void set" + StringUtils.capitalize(pi.getName()) + "(" + pi.getClassName() + " "
                    + pi.getName() + ") \\r\\n");
            sb.append("     this." + pi.getName() + " = " + pi.getName() + ";\\r\\n");
            sb.append(" \\r\\n");
            sb.append("\\r\\n /**  \\r\\n    *获取 :" + pi.getRemark() + "\\r\\n     */\\r\\n");
            if ("boolean".equalsIgnoreCase(pi.getClassName())) 
                sb.append(" public " + pi.getClassName() + " is" + StringUtils.capitalize(pi.getName()) + "() \\r\\n");
             else 
                sb.append(" public " + pi.getClassName() + " get" + StringUtils.capitalize(pi.getName()) + "() \\r\\n");
            
            sb.append("     return this." + pi.getName() + ";\\r\\n");
            sb.append(" \\r\\n");
        

        Set set = modelProMap.keySet();
        Iterator it = set.iterator();
        while (it.hasNext()) 
            String key = (String) it.next();
            getMetStr(key, sb);
        
        return sb.length() > 0 ? sb.toString() : null;
    

    @Override
    public String getClassName() 
        return this.className;
    

    @Override
    public String getIdCol() 
        return this.idCol;
    

    @Override
    public String getIdPro() 
        return this.idPro;
    

    @Override
    public String getDtoClassBody() 
        StringBuilder proStr = new StringBuilder();
        StringBuilder metStr = new StringBuilder();
        for (Entry<String, TypeHandler> entry : dtoProMap.entrySet()) 
            proStr.append(entry.getValue().getProStr());
            metStr.append(entry.getValue().getMetStr());
        
        return proStr.toString() + "\\r\\n" + metStr.toString();
    

    public String getDtoSavePath() 
        return getSavePath() + "Dto\\\\";
    

    public String getAuthorStr() 
        return System.getProperty("user.name");
    

    public String getMetStr(String key, StringBuffer sb) 
        sb.append("\\r\\n /**  \\r\\n    *获取 :" + key + "Before\\r\\n  */\\r\\n");
        sb.append("    public Date get" + StringUtils.capitalize(key) + "Before() \\r\\n");
        sb.append("        return this." + key + "Before;\\r\\n");
        sb.append("    \\r\\n");
        sb.append("\\r\\n /**  \\r\\n    *设置 :" + key + "Before\\r\\n  */\\r\\n");
        sb.append("    public void set" + StringUtils.capitalize(key) + "Before(Date " + key + "Before) \\r\\n");
        sb.append("        this." + key + "Before = " + key + "Before;\\r\\n");
        sb.append("    \\r\\n\\r\\n");
        sb.append("\\r\\n /**  \\r\\n    *获取 :" + key + "After\\r\\n   */\\r\\n");
        sb.append("    public Date get" + StringUtils.capitalize(key) + "After() \\r\\n");
        sb.append("        return this." + key + "After;\\r\\n");
        sb.append("    \\r\\n");
        sb.append("\\r\\n /**  \\r\\n    *设置 :" + key + "After\\r\\n   */\\r\\n");
        sb.append("    public void set" + StringUtils.capitalize(key) + "After(Date " + key + "After) \\r\\n");
        sb.append("        this." + key + "After = " + key + "After;\\r\\n");
        sb.append("    \\r\\n");
        return sb.toString();
    

    @Override
    public String toString() 
        return "ModelInfo [className=" + className + ", packageName=" + packageName + ", savePath=" + savePath
                + ", mTable=" + mTable + ", fileName=" + fileName + ", remark=" + remark + ", idCol=" + idCol
                + ", idPro=" + idPro + ", idColType=" + idColType + ", idProType=" + idProType + ", cols="
                + Arrays.toString(cols) + ", pros=" + Arrays.toString(pros) + ", jdbcTypes="
                + Arrays.toString(jdbcTypes) + ", javaTypes=" + Arrays.toString(javaTypes) + ", dtoProMap=" + dtoProMap
                + ", modelProMap=" + modelProMap + ", name=" + name + ", sEQName=" + sEQName + ", dtoFileName="
                + dtoFileName + "]";
    

然后,还有一点笔者需要说明一下,就是代码生成器 jdbc类型和数据库类型的对应。
我们可以统一起来,像什么char可以用varchar或者int代替,bool可以用int代替,浮点型可以用varchar代替
oracle:
NUMBER -> Long
LONG -> Long
VARCHAR2->String
Date->Date java.uti.Date

mysql:
bigint -> Long
int -> Long
varchar -> String
DateTime -> Date java.uti.Date

这样便统一起来了。
接下来,获取到数据库表和字段的信息后,就要生成代码了,这里笔者就介绍一下如何生成Mapper.xml这个文件的,因为这个代码生成器的东西比较多,无法一一列举,但是核心思想都是一样的。
首先,必须准备一个模板,也是就是说,你想生成啥,就得准备一个相应的模板。
mapperXml.ftl.mysql:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="$m.packageName.$m.className">

    <resultMap type="$m.resMapClsName" id="$m.resBeaNameResultMap">
        $m.resMapStr
    </resultMap>

    <insert id="addEntity" parameterType="$m.resMapClsName" useGeneratedKeys="true" keyProperty="$m.idPro">
        INSERT INTO $m.tableName
          ($m.insertColsStr)
        VALUES
          ($m.insertColsVal)
    </insert>

    <delete id="delEntity" parameterType="long">
        delete from $m.tableName
        <where>
            $m.idCol = $m.escape$m.idPro
        </where>
    </delete>

    <delete id="delBatchEntity" parameterType="String">
        delete from $m.tableName
        <where>
            <if test="ids != null">
                $m.idCol in 
                (
                    <foreach collection="ids" index="index" separator="," item="item" >
                        $m.escapeitem
                    </foreach>
                )
            </if>
        </where>
    </delete>

    <update id="editEntity" parameterType="$m.resMapClsName">
        update $m.tableName
        <set>
            $m.editSetStr
        </set>
        where $m.idCol = $m.escape$m.idPro
    </update>


    <select id="count" resultType="long" parameterType="$m.resMapClsName">
        SELECT count(1) from $m.tableName
        <where>
            $m.countWhereStr
        </where>
    </select>

    <select id="list" resultMap="$m.resBeaNameResultMap" parameterType="$m.resMapClsName">
        SELECT 
            $m.listColsStr
        FROM
            $m.tableName t
        <where> 
            $m.listWhereStr
        </where>
        <if test="sort !=null and sort !=''">
            ORDER BY $m.escapeNewsort $m.escapeNeworder
        </if>
    </select>

    <select id="getEntityById" parameterType="long" resultType="$m.resMapClsName">
        SELECT 
            $m.listColsStr
        FROM $m.tableName t
        WHERE $m.idCol = $m.escape$m.idPro
    </select>
</mapper>

然后, 使freemarkjarjava实现一个简单的验证码生成器

从0到1打造代码生成器Lambda表达式实现简单接口

Java数组实现队列

Java数组实现队列

java实现简单工作流--jeeplus vue

java根据文字旋转图片方法