Spring boot 代码生成器,基于Freemarker编写,代码粗劣,大神勿喷

此代码生成器依赖JAR包比较少,除了必用Freemarker 和JDBC之外基本上完全个人编写,代码结构以及生成借鉴过zhangyao 大神的逻辑思路,望大神体谅,ta的码云 https://gitee.com/beany/mySpringBoot
代码生成器我也是第一次编写,编写前查询过大量的资料,感觉mybatis 的逆向工程总会有各种各样不尽人意的地方
也许是我小白不会用吧,勿喷!所以思前想后还是自己写了个代码生成器,初次编写,有些地方感觉还是比较青涩。
废话不多说,代码生成器支持model、Mapper、Dao、Service、ServiceImpl、Controller 一次性的生成,支持同时生
成多张表,下面上代码
生成器结构
代码生成器结构

package com.anka.apps.generator;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
/**
 * @Description 代码生成器,基于Freemarker 2.3.28
 * Jar包依赖由Maven代理。只要有依赖包,本生成器可以单独拿出使用
 * @author AnkaRebirth
 * @date 2019-01-25 23:44
 * @version 1.0.0
 */
public class AnkaGenerator {

	// private static final String driver = "oracle.jdbc.OracleDriver";
	private static final String DRIVER = "com.mysql.cj.jdbc.Driver";
	private static final String URL = "jdbc:mysql://127.0.0.1:3306/anka?serverTimezone=GMT%2B8";
	private static final String USER_NAME = "root";
	private static final String PASS_WORD = "123456";

	// 表名称,不限大小写,可包含单字符通配符("_"),或多字符通配符("%");
	private static final String TALBE_NAME = "CORE_USER";
	// 项目基础包名称,根据自己公司的项目修改
	private static final String BASE_PACKAGE = "com.anka.apps";
	// Model所在包
	private static final String MODEL_PACKAGE = BASE_PACKAGE + ".model";
	// Dao所在包
	private static final String DAO_PACKAGE = BASE_PACKAGE + ".dao";
	// Service所在包
	private static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";
	// ServiceImpl所在包
	private static final String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";
	// Controller所在包
	private static final String CONTROLLER_PACKAGE = BASE_PACKAGE + ".controller";
	// java文件路径
	private static final String JAVA_PATH = "src/main/java";
	// resource文件路径
	private static final String RESOURCES_PATH = "src/main/resources";
	// mapper所在路径
	private static final String MAPPER_PATH = "/mapper/";
	// 模板位置
    private static final String TEMPLATE_FILE_PATH = "src/test/resources/template/generator";
    
	public static void main(String[] args) throws SQLException {
		Connection con = JDBCConnection.INSTANCE.getConnection(DRIVER, URL, USER_NAME, PASS_WORD);
		DatabaseMetaData data = con.getMetaData();
		System.out.println(data.getDriverName());
		System.out.println(data.getURL());
		System.out.println(data.getUserName());
		System.out.println("");
		List<Map<String, Object>> list = GetTablesData.getTablesData(TALBE_NAME,
				data, BASE_PACKAGE, SERVICE_PACKAGE, SERVICE_IMPL_PACKAGE, MODEL_PACKAGE,
				DAO_PACKAGE, CONTROLLER_PACKAGE);
		GeneratorUtils.closeConnection(con);
		System.out.println("生成表"+list.size()+"个!SUCCESS");
		//==================================代码生成主体部分==================================
		for (Map<String, Object> map : list) {
			//model 生成
			genModel(map, GeneratorUtils.packageConvertPath(MODEL_PACKAGE));
			//Mapper 生成
			genMapper(map,MAPPER_PATH);
			//Dao 生成
			genDao(map, GeneratorUtils.packageConvertPath(DAO_PACKAGE));
			//Service 生成
			genService(map, GeneratorUtils.packageConvertPath(SERVICE_PACKAGE));
			//ServiceImpl 生成
			genServiceImpl(map, GeneratorUtils.packageConvertPath(SERVICE_IMPL_PACKAGE));
			//Controller 生成
			genController(map, GeneratorUtils.packageConvertPath(CONTROLLER_PACKAGE));
		}
		//==================================代码生成主体部分==================================
	}
	/**
	 * 生成Model
	 * @param tableData
	 * @param PACKAGE_PATH_MODEL
	 */
	private static void genModel(Map<String, Object> tableData, String PACKAGE_PATH_MODEL) {
		String path = JAVA_PATH + PACKAGE_PATH_MODEL + tableData.get("claszName") + ".java";
		GeneratorUtils.generatorCode(tableData, path, "model.ftl", TEMPLATE_FILE_PATH);
	}
	/**
	 * 生成Mapper
	 * @param tableData
	 */
	private static void genMapper(Map<String, Object> tableData,String MAPPER_PATH) {
		String path = RESOURCES_PATH + MAPPER_PATH + tableData.get("claszName") + "Mapper.xml";
		GeneratorUtils.generatorCode(tableData, path, "mapper.ftl", TEMPLATE_FILE_PATH);
	}
	/**
	 * 生成Dao
	 * @param tableData
	 * @param PACKAGE_PATH_DAO
	 */
	private static void genDao(Map<String, Object> tableData,  String PACKAGE_PATH_DAO) {
		String path = JAVA_PATH + PACKAGE_PATH_DAO + tableData.get("claszName") + "Dao.java";
		GeneratorUtils.generatorCode(tableData, path, "dao.ftl", TEMPLATE_FILE_PATH);
	}
	/**
	 * 生成Service
	 * @param tableData
	 * @param PACKAGE_PATH_SERVICE
	 */
	private static void genService(Map<String, Object> tableData, String PACKAGE_PATH_SERVICE) {
		String path = JAVA_PATH + PACKAGE_PATH_SERVICE + tableData.get("claszName") + "Service.java";
		GeneratorUtils.generatorCode(tableData, path, "service.ftl", TEMPLATE_FILE_PATH);
	}
	/**
	 * 生成ServiceImpl
	 * @param tableData
	 * @param PACKAGE_PATH_SERVICE_IMPL
	 */
	private static void genServiceImpl(Map<String, Object> tableData, String PACKAGE_PATH_SERVICE_IMPL) {
		String path = JAVA_PATH + PACKAGE_PATH_SERVICE_IMPL + tableData.get("claszName") + "ServiceImpl.java";
		GeneratorUtils.generatorCode(tableData, path, "service-impl.ftl", TEMPLATE_FILE_PATH);
	}
	/**
	 * 生成Controller
	 * @param tableData
	 * @param PACKAGE_PATH_CONTROLLER
	 */
	private static void genController(Map<String, Object> tableData, String PACKAGE_PATH_CONTROLLER) {
		String path = JAVA_PATH + PACKAGE_PATH_CONTROLLER + tableData.get("claszName") + "Controller.java";
		GeneratorUtils.generatorCode(tableData, path, "controller.ftl", TEMPLATE_FILE_PATH);
	}
}

package com.anka.apps.generator;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.JDBCType;
import java.sql.SQLException;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;

public class GeneratorUtils {

	/**
	 * 下划线转驼峰法
	 * 
	 * @param line
	 *            源字符串
	 * @param smallCamel
	 *            大小驼峰,是否为小驼峰
	 * @return 转换后的字符串
	 */
	public static String underlineCamel(String line, boolean smallCamel) {
		if (line == null || "".equals(line)) {
			return "";
		}
		StringBuffer sb = new StringBuffer();
		Pattern pattern = Pattern.compile("([A-Za-z\\d]+)(_)?");
		Matcher matcher = pattern.matcher(line);
		while (matcher.find()) {
			String word = matcher.group();
			sb.append(smallCamel && matcher.start() == 0 ? Character.toLowerCase(word.charAt(0))
					: Character.toUpperCase(word.charAt(0)));
			int index = word.lastIndexOf('_');
			if (index > 0) {
				sb.append(word.substring(1, index).toLowerCase());
			} else {
				sb.append(word.substring(1).toLowerCase());
			}
		}
		return sb.toString();
	}
	
	/**
	 * @author AnkaRebirth
	 * @param type java.sql.Types 对应的值
	 * @return
	 */
	public static String jdbcTojava(int type) {
		String temp = null;
		switch (type) {
		case -7:// BIT
			temp = "Boolean";
			break;
		case -6:// TINYINT
			temp = "Byte";
			break;
		case 5:// SMALLINT
			temp = "Short";
			break;
		case 4:// INTEGER
			temp = "Integer";
			break;
		case -5:// BIGINT
			temp = "Integer";
			break;
		case 6:// FLOAT
			temp = "Double";
			break;
		case 7:// REAL
			temp = "Float";
			break;
		case 8:// DOUBLE
			temp = "Double";
			break;
		case 2:// NUMERIC
			temp = "java.math.BigDecimal";
			break;
		case 3:// DECIMAL
			temp = "java.math.BigDecimal";
			break;
		case 1:// CHAR
			temp = "String";
			break;
		case 12:// VARCHAR
			temp = "String";
			break;
		case -1:// LONGVARCHAR
			temp = "String";
			break;
		case 91:// DATE
			temp = "Date";
			break;
		case 92:// TIME
			temp = "java.sql.Time";
			break;
		case 93:// TIMESTAMP
			temp = "Date";
			break;
		case -2:// BINARY
			temp = "Byte[]";
			break;
		case -3:// VARBINARY
			temp = "Byte[]";
			break;
		case -4:// LONGVARBINARY
			temp = "Byte[]";
			break;
		case 0:// NULL
			temp = null;
			break;
		case 1111:// OTHER
			temp = null;
			break;
		case 2000:// JAVA_OBJECT
			temp = null;
			break;
		case 2001:// DISTINCT
			temp = null;
			break;
		case 2002:// STRUCT
			temp = "java.sql.Struct";
			break;
		case 2003:// ARRAY
			temp = "java.sql.Array";
			break;
		case 2004:// BLOB
			temp = "java.sql.Blob";
			break;
		case 2005:// CLOB
			temp = "String";
			break;
		case 2006:// REF
			temp = "java.sql.Ref";
			break;
		case 70:// DATALINK
			temp = "java.net.URL";
			break;
		case 16:// BOOLEAN
			temp = "Boolean";
			break;
		// -------------------------JDBC 4.0 ------------------------------
		case -8:// ROWID
			temp = "java.sql.RowId";
			break;
		case -15:// NCHAR
			temp = "String";
			break;
		case -9:// NVARCHAR
			temp = "String";
			break;
		case -16:// LONGNVARCHAR
			temp = "String";
			break;
		case 2011:// NCLOB
			temp = "java.sql.NClob";
			break;
		case 2009:// SQLXML
			temp = "java.sql.SQLXML";
			break;
		// --------------------------JDBC 4.2 -----------------------------
		case 2012:// REF_CURSOR
			temp = null;
			break;
		case 2013:// TIME_WITH_TIMEZONE
			temp = "Date";
			break;
		case 2014:// TIMESTAMP_WITH_TIMEZONE
			temp = "Date";
			break;
		default:
			break;
		}
		return temp;
	}
	/**
	 * DATE DATETIME统一定义TIMESTAMP,CLOB转VARCHAR
	 * @param jdbcType
	 * @return
	 */
	public static String getJdbcTypeSame(String jdbcType) {
		String temp = jdbcType;
		if (jdbcType.equals(JDBCType.DATE.getName())) {
			temp = JDBCType.TIMESTAMP.getName();
		}
		if (jdbcType.equals(JDBCType.CLOB.getName())) {
			temp = JDBCType.VARCHAR.getName();
		}
		return temp;
	}
	/**
	 * 关闭数据库连接
	 * 
	 * @param conn
	 */
	public static void closeConnection(Connection conn) {
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 获取freemarker cfg
	 * @return
	 * @throws IOException
	 */
	public static freemarker.template.Configuration getConfiguration(String TEMPLATE_FILE_PATH) {
        freemarker.template.Configuration cfg = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_28);
        try {
			cfg.setDirectoryForTemplateLoading(new File(TEMPLATE_FILE_PATH));
		} catch (IOException e) {
			e.printStackTrace();
		}
        cfg.setDefaultEncoding("UTF-8");
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER);
        return cfg;
    }
	/**
	 * 路径转换,.替换为/
	 * @param packageName
	 * @return
	 */
	public static String packageConvertPath(String packageName) {
        return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName);
    }
	/**
	 * 代码生成
	 * @param tableData 表数据
	 * @param path 生成路径
	 * @param ftl 模版
	 * @param TEMPLATE_FILE_PATH 模版路径
	 */
	public static void generatorCode(Map<String, Object> tableData, String path, String ftl, String TEMPLATE_FILE_PATH){
		freemarker.template.Configuration cfg = getConfiguration(TEMPLATE_FILE_PATH);
		try {
			File file = new File(path);
	        if (!file.getParentFile().exists()) {
	            file.getParentFile().mkdirs();
	        }
	        try {
				cfg.getTemplate(ftl).process(tableData, new FileWriter(file));
			} catch (TemplateException e) {
				e.printStackTrace();
			}
	        System.out.println("路径:" + path + " 生成成功");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

package com.anka.apps.generator;

import java.sql.DatabaseMetaData;
import java.sql.JDBCType;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

public class GetTablesData {

	public static List<Map<String, Object>> getTablesData(String tableName, DatabaseMetaData data,
			String BASE_PACKAGE, String SERVICE_PACKAGE, String SERVICE_IMPL_PACKAGE, String MODEL_PACKAGE,
			String DAO_PACKAGE, String CONTROLLER_PACKAGE) throws SQLException {
		System.out.println(data.getDriverName());
		System.out.println(data.getURL());
		System.out.println(data.getUserName());
		System.out.println("");
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		/**
		 * 获取给定类别中使用的表的描述。 方法原型:ResultSet getTables(String catalog,String
		 * schemaPattern,String tableNamePattern,String[] types); catalog -
		 * 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。 schema -
		 * 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列;
		 * 可包含单字符通配符("_"),或多字符通配符("%"); tableNamePattern -
		 * 表名称;可包含单字符通配符("_"),或多字符通配符("%"); types - 表类型数组;
		 * "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL
		 * TEMPORARY"、"ALIAS" 和 "SYNONYM";
		 * null表示包含所有的表类型;可包含单字符通配符("_"),或多字符通配符("%");
		 */
		ResultSet rs = data.getTables(null, null, tableName == "" ? null : tableName, new String[] { "TABLE" });
		while (rs.next()) {
			System.out.println("表名:" + rs.getString("TABLE_NAME").toUpperCase());
			System.out.println("表类型:" + rs.getString("TABLE_TYPE"));
			System.out.println("表所属数据库:" + rs.getString("TABLE_CAT"));
			System.out.println("表备注:" + rs.getString("REMARKS"));
			Map<String, Object> map = getDateMap(rs.getString("TABLE_NAME").toUpperCase(), rs.getString("REMARKS"),
					data, BASE_PACKAGE, SERVICE_PACKAGE, SERVICE_IMPL_PACKAGE, MODEL_PACKAGE,
					DAO_PACKAGE, CONTROLLER_PACKAGE);
			list.add(map);
		}
		rs.close();
		return list;
	}

	/**
	 * 封装表数据
	 * 
	 * @param tableName
	 *            表名
	 * @param reMarks
	 *            表备注
	 * @param data
	 *            DatabaseMetaData data 对象
	 * @return Map<String, Object> 封装表信息数据
	 * @throws SQLException
	 */
	private static Map<String, Object> getDateMap(String tableName, String reMarks, DatabaseMetaData data,
			String BASE_PACKAGE, String SERVICE_PACKAGE, String SERVICE_IMPL_PACKAGE, String MODEL_PACKAGE,
			String DAO_PACKAGE, String CONTROLLER_PACKAGE) throws SQLException {
		Assert.hasText(tableName, "表名称不能为空!");
		Map<String, Object> map = new HashMap<String, Object>();
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		map.put("tableName", tableName);
		map.put("claszName", GeneratorUtils.underlineCamel(tableName, false));
		map.put("className", GeneratorUtils.underlineCamel(tableName, true));
		map.put("reMarks", reMarks);
		map.put("author", "AnkaRebirth");
		map.put("date", new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date()));
		map.put("version", "1.0.0");
		map.put("basePackage", BASE_PACKAGE);
		map.put("basePackageService", SERVICE_PACKAGE);
		map.put("basePackageServiceImpl", SERVICE_IMPL_PACKAGE);
		map.put("basePackageModel", MODEL_PACKAGE);
		map.put("basePackageDao", DAO_PACKAGE);
		map.put("basePackageController", CONTROLLER_PACKAGE);
		map.put("baseRequestMapping", GeneratorUtils.underlineCamel(tableName, true));
		/**
		 * 获取可在指定类别中使用的表列的描述。 方法原型:ResultSet getColumns(String catalog,String
		 * schemaPattern,String tableNamePattern,String columnNamePattern)
		 * catalog - 表所在的类别名称;""表示获取没有类别的列,null表示获取所有类别的列。 schema -
		 * 表所在的模式名称(oracle中对应于Tablespace);""表示获取没有模式的列,null标识获取所有模式的列;
		 * 可包含单字符通配符("_"),或多字符通配符("%"); tableNamePattern -
		 * 表名称;可包含单字符通配符("_"),或多字符通配符("%"); columnNamePattern - 列名称;
		 * ""表示获取列名为""的列(当然获取不到);null表示获取所有的列;可包含单字符通配符("_"),或多字符通配符("%");
		 */
		ResultSet cols = data.getColumns(null, "%", tableName, "%");
		while (cols.next()) {
			System.out.println("字段名:" + cols.getString("COLUMN_NAME") + "------ JAVA名:"
					+ GeneratorUtils.underlineCamel(cols.getString("COLUMN_NAME"), false) + "------" + "类型:"
					+ cols.getString("TYPE_NAME") + "------" + "长度:" + cols.getString("COLUMN_SIZE") + "------" + "备注:"
					+ cols.getString("REMARKS"));
			Map<String, String> col = new HashMap<String, String>();
			col.put("columnName", cols.getString("COLUMN_NAME"));
			col.put("javaNameUp", GeneratorUtils.underlineCamel(cols.getString("COLUMN_NAME"), false));
			col.put("javaNameLo", GeneratorUtils.underlineCamel(cols.getString("COLUMN_NAME"), true));
			Assert.hasText(GeneratorUtils.jdbcTojava(cols.getInt("DATA_TYPE")),
					"未能获取到对应的java变量类型,请检查【" + cols.getString("COLUMN_NAME") + "】数据库中对应类型!");
			col.put("javaType", GeneratorUtils.jdbcTojava(cols.getInt("DATA_TYPE")));
			col.put("jdbcType", GeneratorUtils.getJdbcTypeSame(JDBCType.valueOf(cols.getInt("DATA_TYPE")).getName()));
			col.put("remarks", cols.getString("REMARKS"));
			list.add(col);
		}
		cols.close();
		map.put("columns", list);
		return map;

	}
}

package com.anka.apps.generator;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * 
 * @Description: Connection 单例模式
 * @author AnkaRebirth
 * @date 2019-01-25 16:13
 * @version 1.0.0
 *
 */
public enum JDBCConnection {
	INSTANCE;
	public Connection getConnection(String driver, String url, String userName, String passWord){
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			System.out.println("加载数据库驱动失败!");
			e.printStackTrace();
		}
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(url, userName, passWord);
		} catch (SQLException e) {
			System.out.println("数据库连接失败!");
			e.printStackTrace();
		}
		return conn;
	}
}

下面是项目源码,直接导入MAVEN 项目即可
https://download.csdn.net/download/zzc199055/10938922

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值