开发代码生成器

  1. 代码生成器:可以生成代码的程序
  2. 代码生成器的三要素:数据+模板+合成机制
  3. 我们使用的模板引擎是freemarker
    FreeMarker是一款模板引擎: 一种基于模板和数据,并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具
  4. 下面通过一个简单的案例来了解一下Freemarker的使用:
    首先创建一个maven的工程,在pom.xml文件中添加如下依赖:
    pom.xml

        
            org.freemarker
            freemarker
            2.3.23
        
        
            mysql
            mysql-connector-java
            5.1.34
        
    

下一步我们需要创建Configuration对象和Template对象,这两个对象的使用如下:
Configuration作用:环境初始化
常用的API:

方法名称 描述
Configuration(Version incompatibleImprovements ) 生成当前类的对象
setDirectoryForTemplateLoading(File dir) 生成当前类的对象
getTemplate(String file) 模板文件名称

Template作用:模板实例化,执行代码生成
常用API:

方法名称 描述
process(Object data, Writer out) 生成数据文件

代码如下:
Generator.java

public class Generator {
    Configuration configuration;
    //1.初始化模板配置
    public void init() throws IOException {
        configuration= new Configuration(Configuration.getVersion());
        String templatePath = this.getClass().getClassLoader().getResource("").getPath();
        //设置模板所在目录
        System.out.println("templatePath:"+templatePath);
        configuration.setDirectoryForTemplateLoading(new File(templatePath));
    }
    //2.获取模板填充数据
    public void process(String tempName,Map data,String savePath) throws TemplateException, IOException {
        Template template = configuration.getTemplate(tempName);
        OutputStream os = new FileOutputStream(savePath);
        Writer writer=new OutputStreamWriter(os);
        template.process(data,writer);
    }

    public static void main(String[] args) throws Exception {
        Generator generator = new Generator();
        generator.init();
        Map data=new HashMap();
        data.put("name","张三11");
        String savePath="F:\\generator-data\\hello.html";
        generator.process("hello/hello.ftl",data,savePath);

    }
}
  1. 了解了合成机制,那么我们的数据如何获取 - 使用JDBC获取数据库所有表信息
    TableHandler.java
 private static Connection connection;
    private static String DBDRIVER = PropertiesUtils.get("database.properties", "driver");

    private static String DBURL = PropertiesUtils.get("database.properties", "url");

    private static String DBUSER = PropertiesUtils.get("database.properties", "user");

    private static String DBPASS = PropertiesUtils.get("database.properties", "password");

    static {
    //1.获取数据库连接
        try {
            Class.forName(DBDRIVER);
            connection = DriverManager.getConnection(DBURL,DBUSER,DBPASS);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void getTables()  {
        try {
        	//2.创建DatabaseMetaData 
            DatabaseMetaData dbmd = connection.getMetaData();
            //3.执行查询
            ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"});
            //4.遍历结果集
            while (rs.next()){
                String tableName = rs.getString("TABLE_NAME");
                System.out.println(tableName);
            }
        }  catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public void getColumns(String tableName) {
        try {
            //2.获取DatabaseMetaData 
            DatabaseMetaData dbmd = connection.getMetaData();
            //3.执行查询
            ResultSet rs = dbmd.getColumns(null, "%", tableName, "%");
            while(rs.next()){
               //获取列名
                String columnName = rs.getString("COLUMN_NAME");
                //获取列类型
                String columnType = rs.getString("TYPE_NAME");
                //获取注释
                String comment = rs.getString("REMARKS");
                System.out.println("columnName:"+columnName+",columnType:"+columnType+",comment:"+comment);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
    public static void main(String[] args) {
        TableHandler tableHandler = new TableHandler();
        //tableHandler.getTables();

        tableHandler.getColumns("itrip_hotel_room");

    }

PropertiesUtils.java

public class PropertiesUtils {

    private static Properties props;

    /**
     * 加载配置文件
     *
     * @param fileName
     */
    private static void readProperties(String fileName) {
        try {
            props = new Properties();
            InputStreamReader inputStream = new InputStreamReader(PropertiesUtils.class.getClassLoader().getResourceAsStream(fileName), "UTF-8");

            props.load(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 根据key读取对应的value
     *
     * @param key
     * @return
     */
    public static String get(String fileName,String key) {
        readProperties(fileName);
        return props.getProperty(key);
    }

}

database.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/itripdb?useUnicode=true&characterEncoding=utf-8
user=root
password=123456
  1. 了解了如何获取数据,也知道了Freemaker的合成机制。下面我们可以通过模板生成实体类,SQL映射文件及映射接口。当然还有我们的service及器实现类。
    database.properties , PropertiesUtils.java同上。
    (1)获取数据,修改TableHandler.java
public class TableHandler {
    private static Connection connection;
    private static String DBDRIVER = PropertiesUtils.get("database.properties", "driver");

    private static String DBURL = PropertiesUtils.get("database.properties", "url");

    private static String DBUSER = PropertiesUtils.get("database.properties", "user");

    private static String DBPASS = PropertiesUtils.get("database.properties", "password");

    static {
        try {
            Class.forName(DBDRIVER);
            connection = DriverManager.getConnection(DBURL,DBUSER,DBPASS);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public List getTables()  {
        List
tableList = new ArrayList
(); try { DatabaseMetaData dbmd = connection.getMetaData(); ResultSet rs = dbmd.getTables(null, null, null, new String[]{"TABLE"}); while (rs.next()){ Table table = new Table(); String tableName = rs.getString("TABLE_NAME"); table.setTableName(tableName); table.setClassName(StringUtils.captureName(StringUtils.putOffUnderline(tableName))); table.setTableNameNonUnderline(StringUtils.removeUnderlineAndSubstr(tableName)); table.setClassNameLowerFirstWord(StringUtils.lowerName(table.getClassName())); table.setColumnList(getColumns(tableName)); tableList.add(table); } } catch (SQLException e) { e.printStackTrace(); } return tableList; } public List getColumns(String tableName) { List columnList = new ArrayList(); try { DatabaseMetaData dbmd = connection.getMetaData(); ResultSet rs = dbmd.getColumns(null, "%", tableName, "%"); while(rs.next()){ Column column =new Column(); String columnName = rs.getString("COLUMN_NAME"); String columnType = rs.getString("TYPE_NAME"); String comment = rs.getString("REMARKS"); column.setColumnName(columnName); column.setColumnType(columnType); column.setComments(comment); column.setFieldName(columnName); column.setFieldNameUpperFirstWord(StringUtils.captureName(column.getFieldName())); column.setJavaType(StringUtils.switchType(columnType)); columnList.add(column); } } catch (SQLException e) { e.printStackTrace(); } return columnList; } }

以上封装的过程可能需要用到对字符串的操作:
StringUtils.java

public class StringUtils {
    /**
     * 某位置字母大写
     *
     * @param name
     * @param indx
     * @return
     */
    public static String captureName(String name, int indx) {
        name = name.substring(0, indx) + name.substring(indx, indx + 1).toUpperCase() + name.substring(indx + 1);
        return name;
    }

    /**
     * 首字母大写
     *
     * @param name
     * @return
     */
    public static String captureName(String name) {
        name = name.substring(0, 1).toUpperCase() + name.substring(1);
        return name;
    }

    /***
     * 首字母小写
     *
     * @param name
     * @return
     */
    public static String lowerName(String name) {
        name = name.substring(0, 1).toLowerCase() + name.substring(1);
        return name;
    }

    /***
     * 去掉下划线 并用驼峰原则进行转化
     *
     * @return
     */
    public static String putOffUnderline(String columnName) {
        StringBuffer fieldNameBuffer = null;
        String tempNameArray[] = columnName.split("_");
        for (int i = 0; i < tempNameArray.length; i++) {
            if (i == 0) {
                fieldNameBuffer = new StringBuffer(tempNameArray[i]);
            } else {
                fieldNameBuffer.append(captureName(tempNameArray[i]));
            }
        }
        return fieldNameBuffer.toString();
    }

    public static String removeUnderlineAndSubstr(String tableName){
       return tableName.replaceAll("_","")
                .replaceAll("itrip","");
    }

    /**
     * 列类型转换成java类型
     * @param columnType
     */
    public static String switchType(String columnType){
        String javaType=null;
        switch (columnType){
            case "BIGINT":javaType="Long";break;
            case "INT":javaType="Integer";break;
            case "BIT":javaType="Short";break;
            case "VARCHAR":javaType="String";break;
            case "TEXT":javaType="String";break;
            case "DATETIME":javaType="Date";break;
            case "DECIMAL":javaType="Double";break;
        }
        return javaType;
    }


    public static void main(String[] args) {
        //String a = putOffUnderline("a_bccc_d");
        String a=removeUnderlineAndSubstr("itrip_area_dic");
        System.out.println(a);
    }
}

(2)我们需要将获取到的表的数据及列的信息封装成两个实体类
Table.java

public class Table {
    private String tableName;
    private String className;
    //类名首字母小写
    private String classNameLowerFirstWord;
    // 表名每个单词字母大写无下划线
    private String tableNameUpperFirstWord;
    private List columnList;
    //表名无前缀和下划线
    private String tableNameNonUnderline;

  //....省略getter setter访问器
}

Column.java

public class Column {
    private String columnName;
    private String columnType;
    private String javaType;
    private String fieldName;
    //属性名首字母大写
    private String fieldNameUpperFirstWord;
    private String comments;
	//..省略getter setter访问器
}

(3)合成,修改Generator.java

public class Generator {
    Configuration configuration;
    //1.初始化模板配置
    public void init() throws IOException {
        configuration= new Configuration(Configuration.getVersion());
        String templatePath = this.getClass().getClassLoader().getResource("").getPath();
        //设置模板所在目录
        System.out.println("templatePath:"+templatePath);
        configuration.setDirectoryForTemplateLoading(new File(templatePath));
    }
    //2.获取模板填充数据
    public void process(String tempName,Map data,String savePath) throws TemplateException, IOException {
        Template template = configuration.getTemplate(tempName);
        OutputStream os = new FileOutputStream(savePath);
        Writer writer=new OutputStreamWriter(os);
        template.process(data,writer);
    }

    //该方法用于生成实体类
    public void executeModel() throws IOException, TemplateException {
        TableHandler tableHandler = new TableHandler();
        List
tableList = tableHandler.getTables(); Generator generator = new Generator(); init(); for (Table table : tableList) { Map data=new HashMap(); data.put("table",table); File saveDir = new File("F:\\generator-data\\mymodel\\"); if(!saveDir.exists()) saveDir.mkdirs(); String savePath=saveDir+"\\"+table.getClassName()+".java"; process("itrip/model.ftl",data,savePath); } } //该方法用于生成sql映射文件 public void executeMapper() throws IOException, TemplateException { TableHandler tableHandler = new TableHandler(); List
tableList = tableHandler.getTables(); Generator generator = new Generator(); init(); for (Table table : tableList) { Map data=new HashMap(); data.put("table",table); File saveDir = new File("F:\\generator-data\\mymapper\\"); if(!saveDir.exists()) saveDir.mkdirs(); String savePath=saveDir+"\\"+table.getClassName()+"Mapper.xml"; process("itrip/mapper.ftl",data,savePath); } } //生成映射器接口 public void executeClazzMapper() throws IOException, TemplateException { TableHandler tableHandler = new TableHandler(); List
tableList = tableHandler.getTables(); Generator generator = new Generator(); init(); for (Table table : tableList) { Map data=new HashMap(); data.put("table",table); File saveDir = new File("F:\\generator-data\\myclazzMapper\\"); if(!saveDir.exists()) saveDir.mkdirs(); String savePath=saveDir+"\\"+table.getClassName()+"Mapper.java"; process("itrip/clazzMapper.ftl",data,savePath); } } //生成service接口 public void executeService() throws IOException, TemplateException { TableHandler tableHandler = new TableHandler(); List
tableList = tableHandler.getTables(); Generator generator = new Generator(); init(); for (Table table : tableList) { Map data=new HashMap(); data.put("table",table); File saveDir = new File("F:\\generator-data\\myService\\"); if(!saveDir.exists()) saveDir.mkdirs(); String savePath=saveDir+"\\"+table.getClassName()+"Service.java"; process("itrip/service.ftl",data,savePath); } } //生成接口实现类 public void executeServiceImpl() throws IOException, TemplateException { TableHandler tableHandler = new TableHandler(); List
tableList = tableHandler.getTables(); Generator generator = new Generator(); init(); for (Table table : tableList) { Map data=new HashMap(); data.put("table",table); File saveDir = new File("F:\\generator-data\\myService\\impl"); if(!saveDir.exists()) saveDir.mkdirs(); String savePath=saveDir+"\\"+table.getClassName()+"ServiceImpl.java"; process("itrip/serviceImpl.ftl",data,savePath); } } public static void main(String[] args) throws Exception { Generator generator = new Generator(); //generator.executeModel(); // generator.executeMapper(); //generator.executeClazzMapper(); generator.executeService(); } }

(4)编辑模板:
model.ftl

package cn.itrip.beans.pojo;

import java.io.Serializable;
import java.util.Date;
public class ${table.className} implements Serializable {

            <#list table.columnList as column>
                private ${column.javaType} ${column.fieldName};
            
            <#list table.columnList as column>
                public void set${column.fieldNameUpperFirstWord} (${column.javaType}  ${column.fieldName}){
                    this.${column.fieldName}=${column.fieldName};
                }

                public  ${column.javaType} get${column.fieldNameUpperFirstWord}(){
                    return this.${column.fieldName};
                }
            

}

mapper.ftl





    

    

    

    
        insert into ${table.tableName}(

        <#list table.columnList as column>
            <#if column_has_next>
                ${column.columnName} ,
            <#else >
                ${column.columnName}
            
        
        )
        values(
        <#list table.columnList as column>
            <#if column_has_next>
                ${r"#{"}${column.fieldName}},
            <#else >
                ${r"#{"}${column.fieldName}}
            
        
        )
    

    
        update ${table.tableName}
        
             <#list table.columnList as column>
                <#if column_has_next>
                    
                        ${column.columnName}=${r"#{"}${column.fieldName}},
                    
                <#else >
                    
                        ${column.columnName}=${r"#{"}${column.fieldName}}
                    
                
             
        
    

    
        delete from ${table.tableName} where id = ${r"#{"}id}
    

clazzMapper.ftl

package cn.itrip.dao.${table.tableNameNonUnderline};
import cn.itrip.beans.pojo.${table.className};
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;

public interface ${table.className}Mapper {

	public ${table.className} get${table.className}ById(@Param(value = "id") Long id)throws Exception;

	public List<${table.className}>	get${table.className}ListByMap(Map param)throws Exception;

	public Integer get${table.className}CountByMap(Map param)throws Exception;

	public Integer insert${table.className}(${table.className} ${table.classNameLowerFirstWord})throws Exception;

	public Integer update${table.className}(${table.className} ${table.classNameLowerFirstWord})throws Exception;

	public Integer delete${table.className}ById(@Param(value = "id") Long id)throws Exception;

}

service.ftl

package cn.itrip.service..${table.tableNameNonUnderline};
import cn.itrip.beans.pojo.${table.className};
import java.util.List;
import java.util.Map;
import java.util.List;
import java.util.Map;
import cn.itrip.common.Page;
/**
* Created by shang-pc on 2015/11/7.
*/
public interface ${table.className}Service {

    public ${table.className} get${table.className}ById(Long id)throws Exception;

    public List<${table.className}>	get${table.className}ListByMap(Map param)throws Exception;

    public Integer get${table.className}CountByMap(Map param)throws Exception;

    public Integer itriptxAdd${table.className}(${table.className} ${table.classNameLowerFirstWord})throws Exception;

    public Integer itriptxModify${table.className}(${table.className} ${table.classNameLowerFirstWord})throws Exception;

    public Integer itriptxDelete${table.className}ById(Long id)throws Exception;

    public Page<${table.className}> query${table.className}PageByMap(Map param,Integer pageNo,Integer pageSize)throws Exception;
}

serviceImpl.ftl

package cn.itrip.service.${table.tableNameNonUnderline};
import cn.itrip.dao.${table.tableNameNonUnderline}.${table.className}Mapper;
import cn.itrip.beans.pojo.${table.className};
import cn.itrip.common.EmptyUtils;
import cn.itrip.common.Page;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import cn.itrip.common.Constants;
@Service
public class ${table.className}ServiceImpl implements ${table.className}Service {

    @Resource
    private ${table.className}Mapper ${table.classNameLowerFirstWord}Mapper;

    public ${table.className} get${table.className}ById(Long id)throws Exception{
        return ${table.classNameLowerFirstWord}Mapper.get${table.className}ById(id);
    }

    public List<${table.className}>	get${table.className}ListByMap(Map param)throws Exception{
        return ${table.classNameLowerFirstWord}Mapper.get${table.className}ListByMap(param);
    }

    public Integer get${table.className}CountByMap(Map param)throws Exception{
        return ${table.classNameLowerFirstWord}Mapper.get${table.className}CountByMap(param);
    }

    public Integer itriptxAdd${table.className}(${table.className} ${table.classNameLowerFirstWord})throws Exception{
            ${table.classNameLowerFirstWord}.setCreationDate(new Date());
            return ${table.classNameLowerFirstWord}Mapper.insert${table.className}(${table.classNameLowerFirstWord});
    }

    public Integer itriptxModify${table.className}(${table.className} ${table.classNameLowerFirstWord})throws Exception{
        ${table.classNameLowerFirstWord}.setModifyDate(new Date());
        return ${table.classNameLowerFirstWord}Mapper.update${table.className}(${table.classNameLowerFirstWord});
    }

    public Integer itriptxDelete${table.className}ById(Long id)throws Exception{
        return ${table.classNameLowerFirstWord}Mapper.delete${table.className}ById(id);
    }

    public Page<${table.className}> query${table.className}PageByMap(Map param,Integer pageNo,Integer pageSize)throws Exception{
        Integer total = ${table.classNameLowerFirstWord}Mapper.get${table.className}CountByMap(param);
        pageNo = EmptyUtils.isEmpty(pageNo) ? Constants.DEFAULT_PAGE_NO : pageNo;
        pageSize = EmptyUtils.isEmpty(pageSize) ? Constants.DEFAULT_PAGE_SIZE : pageSize;
        Page page = new Page(pageNo, pageSize, total);
        param.put("beginPos", page.getBeginPos());
        param.put("pageSize", page.getPageSize());
        List<${table.className}> ${table.classNameLowerFirstWord}List = ${table.classNameLowerFirstWord}Mapper.get${table.className}ListByMap(param);
        page.setRows(${table.classNameLowerFirstWord}List);
        return page;
    }
}

你可能感兴趣的:(代码生成器)