一个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>
然后, 中的内容就是要使用freemark这个jar来为我们实现,这java实现一个简单的验证码生成器