java web 版代码生成器
系统功能概述及使用技术(稍后上传demo=maven+spring+jdk1.7):
- 系统主要使用采用主流springmvc框架
- 生成springmvc+mybatis+mysql框架为基础代码
- 主要针对【单】表数据模型的增,删,改,查自动生成(demo项目且公司不允许连表)
- *提供数据库导出生成
- 提供数据库建模工具【pdm文件】上传生成
- 主要使用freemark模板技术生成代码
- 提供生成打包zip下载
- 生成代码层次自由可配置
- 第一次博客文笔不好请见谅,可以作为学习参考
配置文件
config.properties —项目核心配置文件:
#数据库连接
jdbc_driver=com.mysql.jdbc.Driver
jdbc_url=jdbc:mysql://localhost:3306/test?useUnicode\=true&characterEncoding\=UTF-8&zeroDateTimeBehavior\=convertToNull
jdbc_username=root
jdbc_password=admin
databaseName=test
#模板引擎配置
zip_path=E:/autoCodezip/builder.zip
temp_path=E:/autoCode/
basePackage=com.scrt.demo.builder
#代码模块配置方案#实体层次配第一位,其他层随便(表需要有主键)
package=entity,dao,service,service.impl,web.controller,/mybatis
endStr=Entity,Dao,Service,ServiceImpl,Controller,Mapper
ftlName=entityTemplate.ftl,daoTemplate.ftl,serviceTemplate.ftl,serviceImplTemplate.ftl,controllerTemplate.ftl,mapperTemplate.ftl
fileSuffix=java,java,java,java,java,xml
dataTypeConvert.properties —sql数据类型对应java数据类型配置文件:
#################数据库类型对应java类型#######################
VARCHAR=java.lang.String
CHAR=java.lang.String
BLOB=java.lang.byte[]
TEXT=java.lang.String
INTEGER=java.lang.Long
TINYINT=java.lang.Integer
SMALLINT=java.lang.Integer
MEDIUMINT=java.lang.Integer
BIT=java.lang.Boolean
BIGINT=java.math.BigInteger
FLOAT=java.lang.Float
DOUBLE=java.lang.Double
DECIMAL=java.math.BigDecimal
BOOLEAN=java.lang.Integer
DATE=java.util.Data
TIME=java.util.Data
DATETIME=java.util.Data
TIMESTAMP=java.sql.Timestamp
YEAR=java.sql.Date
int=java.lang.Integer
核心代码
pdm读取表格 PdmReadUtil.java:
package com.scrt.demo.builder.util;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.scrt.demo.builder.entity.ColumnEntity;
import com.scrt.demo.builder.entity.TableEntity;
/**
* @ClassName: PdmReadUtil
* @Description: pdm文件读取工具类,主要用于解析pdm文件
* @company
* @author yixiang.deng
* @Email
* @date 2015年6月30日
*
*/
public class PdmReadUtil {
private static Logger logger=Logger.getLogger(PdmReadUtil.class);
private static final String TABLEXMLPATH = "/Model/o:RootObject/c:Children/o:Model/c:Tables/o:Table";
/**
*
* @Title: getDoc
* @Description: 获取Document对象
* @param filePath
* @return
*/
public static Document getDoc(String filePath){
File f = new File(filePath);
SAXReader sr = new SAXReader();
Document doc = null;
try {
doc = sr.read(f);
} catch (DocumentException e) {
e.printStackTrace();
}
return doc;
}
/**
*
* @Title: getDoc
* @Description: 通过inputStream
* @param inputStream
* @return Document
*/
public static Document getDoc(InputStream inputStream){
SAXReader sr = new SAXReader();
Document doc = null;
try {
doc = sr.read(inputStream);
} catch (DocumentException e) {
e.printStackTrace();
}
return doc;
}
/**
*
* @Title: parsePDM_VO
* @Description: 解析pdm文件,对应实体
* @param doc 文档对象
* @return List<TableEntity>
*/
public static List<TableEntity> parsePDM_VO(Document doc) {
List<TableEntity> voS = new ArrayList<TableEntity>();
TableEntity vo = null;
if(StringUtil.isEmpty(doc)){
return null;
}
@SuppressWarnings("unchecked")
Iterator<Element> itr= doc.selectNodes(TABLEXMLPATH).iterator();
while (itr.hasNext()) {
vo = new TableEntity();
Element e_table = (Element) itr.next();
vo.setTableName(e_table.elementTextTrim("Name"));
vo.setColumns( getCols(e_table));
voS.add(vo);
}
return voS;
}
//获取所有列
private static List<ColumnEntity> getCols(Element e_table) {
List<ColumnEntity> cols = new ArrayList<ColumnEntity>();
@SuppressWarnings("unchecked")
Iterator<Element> itr1 = e_table.element("Columns").elements("Column").iterator();
while (itr1.hasNext()) {
cols.add(mapperCol(e_table, itr1));
}
return cols;
}
//映射列属性值
private static ColumnEntity mapperCol(Element e_table, Iterator<Element> itr1) {
ColumnEntity col=null;
try {
col = new ColumnEntity();
Element e_col = (Element) itr1.next();
String pkID = e_col.attributeValue("Id");
//col.setDefaultValue(e_col.elementTextTrim("DefaultValue"));
col.setColumnName(e_col.elementTextTrim("Name"));
if(e_col.elementTextTrim("DataType").indexOf("(") >0){
col.setColumnType(e_col.elementTextTrim("DataType").substring(0, e_col.elementTextTrim("DataType").indexOf("(")));
}else {
col.setColumnType(e_col.elementTextTrim("DataType"));
}
//col.setCode(e_col.elementTextTrim("Code"));
col.setDatasize(e_col.elementTextTrim("Length") == null ? null : Integer.parseInt(e_col.elementTextTrim("Length")));
if(e_table.element("Keys")!=null){
String keys_key_id = e_table.element("Keys").element("Key").attributeValue("Id");
String keys_column_ref = e_table.element("Keys").element("Key").element("Key.Columns")
.element("Column").attributeValue("Ref");
String keys_primarykey_ref_id = e_table.element("PrimaryKey").element("Key").attributeValue("Ref");
if (keys_primarykey_ref_id.equals(keys_key_id) && keys_column_ref.equals(pkID)) {
col.setIsPrimaryKey(ColumnEntity.YES);
//vo.setPkField(col.getCode());
}
}
} catch (Exception ex) {
logger.error(ex);
ex.printStackTrace();
}
return col;
}
}
ZipUtil压缩文件夹 ZipUtil.java:
package com.scrt.demo.builder.util;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.Deflater;
import org.apache.log4j.Logger;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.apache.tools.zip.ZipOutputStream;
public class ZipUtil {
private static Logger logger=Logger.getLogger(ZipUtil.class);
/*public static void main(String[] args){
// new Zip().doZip("d:/str","e:/zip.rar");
new ZipUtil().unZip("e:/zip.rar","d:/str");
}*/
private ZipFile zipFile;
private ZipOutputStream zipOut;//压缩Zip
private int bufSize=1024*4; //size of bytes
private byte[] buf= new byte[this.bufSize];
public ZipUtil(){
//要构造函数中去初始化我们的缓冲区
System.out.println("init...ZipUtil....");
}
/**
* 对传入的目录或者是文件进行压缩
* @param srcFile 需要 压缩的目录或者文件
* @param destFile 压缩文件的路径
*/
public void doZip(String srcFile, String destFile) {// zipDirectoryPath:需要压缩的文件夹名
File zipFile = new File(srcFile);
String destFilePathTemp=destFile.substring(0, destFile.lastIndexOf("/"));
File destFileTemp = new File(destFilePathTemp);
if(!destFileTemp.exists()){
destFileTemp.mkdirs();
}
try {
//生成ZipOutputStream,会把压缩的内容全都通过这个输出流输出,最后写到压缩文件中去
this.zipOut = new ZipOutputStream(new BufferedOutputStream(
new FileOutputStream(destFile)));
//设置压缩的注释
zipOut.setComment("comment");
//设置压缩的编码,如果要压缩的路径中有中文,就用下面的编码
zipOut.setEncoding("UTF-8");
//启用压缩
zipOut.setMethod(ZipOutputStream.DEFLATED);
//压缩级别为最强压缩,但时间要花得多一点
zipOut.setLevel(Deflater.BEST_COMPRESSION);
handleFile(zipFile, this.zipOut,"");
//处理完成后关闭我们的输出流
this.zipOut.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
/**
* 由doZip调用,递归完成目录文件读取
* @param zipFile
* @param zipOut
* @param dirName 这个主要是用来记录压缩文件的一个目录层次结构的
* @throws IOException
*/
private void handleFile(File zipFile, ZipOutputStream zipOut,String dirName) throws IOException {
System.out.println("遍历文件:"+zipFile.getName());
//如果是一个目录,则遍历
if(zipFile.isDirectory()){
File[] files = zipFile.listFiles();
if (files.length == 0) {// 如果目录为空,则单独创建之.
//只是放入了空目录的名字
this.zipOut.putNextEntry(new ZipEntry(dirName+zipFile.getName()+File.separator));
this.zipOut.closeEntry();
} else {// 如果目录不为空,则进入递归,处理下一级文件
for (File file : files) {
// 进入递归,处理下一级的文件
handleFile(file, zipOut, dirName+zipFile.getName()+File.separator);
}
}
}else{//如果是文件,则直接压缩
FileInputStream fileIn = new FileInputStream(zipFile);
//放入一个ZipEntry
this.zipOut.putNextEntry(new ZipEntry(dirName+zipFile.getName()));
int length = 0;
//放入压缩文件的流
while ((length = fileIn.read(this.buf)) > 0) {
this.zipOut.write(this.buf, 0, length);
}
//关闭ZipEntry,完成一个文件的压缩
fileIn.close();
this.zipOut.closeEntry();
}
}
/**
* 解压指定zip文件
* @param unZipfile 压缩文件的路径
* @param destFile 解压到的目录
*/
public void unZip(String unZipfile, String destFile) {// unZipfileName需要解压的zip文件名
FileOutputStream fileOut;
File file;
InputStream inputStream;
try {
//生成一个zip的文件
this.zipFile = new ZipFile(unZipfile);
//遍历zipFile中所有的实体,并把他们解压出来
for (@SuppressWarnings("unchecked")
Enumeration<ZipEntry> entries = this.zipFile.getEntries(); entries
.hasMoreElements();) {
ZipEntry entry = entries.nextElement();
//生成他们解压后的一个文件
file = new File(destFile+File.separator+entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
} else {
// 如果指定文件的目录不存在,则创建之.
File parent = file.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
//获取出该压缩实体的输入流
inputStream = zipFile.getInputStream(entry);
fileOut = new FileOutputStream(file);
int length = 0;
//将实体写到本地文件中去
while ((length = inputStream.read(this.buf)) > 0) {
fileOut.write(this.buf, 0, length);
}
fileOut.close();
inputStream.close();
}
}
this.zipFile.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
ftl实体类模板:
package ${tableEntity.packageName};
import java.io.Serializable;
/**
*
* @ClassName: ${tableEntity.className}
* @Description: ${tableEntity.className}实体类,此代码是代码生成器自动化生成。
* @company
* @author auto code builder
* @Email auto code builder
* @date ${nowDate}
*
*/
public class ${tableEntity.className} implements Serializable{
/**
*
*/
private static final long serialVersionUID = ${serialVersionUID?c}L;
<#list tableEntity.columns as col>
private ${col.classAttrType} ${col.classAttr};//${col.columnAnnotations!}!
</#list>
<#list tableEntity.columns as col>
/**${col.columnAnnotations!}!*/
public ${col.classAttrType} get${col.endStr}() {
return ${col.classAttr};
}
/**${col.columnAnnotations!}!*/
public void set${col.endStr}(${col.classAttrType} ${col.classAttr}) {
this.${col.classAttr} = ${col.classAttr};
}
</#list>
}
感兴趣的我售后上传demo,该配置可以直接生成,因为demo逻辑和页面写的不怎么滴!勿喷。
demo下载:http://download.csdn.net/detail/u013210551/8880987
浏览器兼容
目前,本编辑器对Chrome浏览器支持最为完整。建议大家使用较新版本的Chrome。
tomcat 启动后访问 http://127.0.0.1:8080/builder