前言
记一次Freemarker的套路过程,通过JDBC访问数据库,查询表结构,对应生成Dao、Service、Entity、ServiceImpl等java文件,主要是为了实现之前一篇博文的注解整合SSM项目代码的生成功能。
传入freemarker的数据格式为:Map<String, Map<String, Object>>
也可以用其他的,个人感觉这个方便一点。
具体套路如下:
1. 涉及的JAR
freemarker-2.3.19.jar(各版本均可)
mysql-connector-java-5.1.13-bin.jar
- 代码实现
2.1 使用JDBC方式连接数据库,组装好数据并且存入map
public static Map<String, Map<String, Params>> connect(String driver,
String url, String username, String password) {
try {
//加载驱动类
Class.forName(driver);
}catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
//将各种流放入try()中,将由try来执行close()操作
try (Connection con
= DriverManager.getConnection(url, username,password);
PreparedStatement ps
= con.prepareStatement(
"select table_name,column_name,column_comment,
column_type,column_key,column_default
from INFORMATION_SCHEMA.Columns
where table_name='m_user'
and table_schema='test'");
ResultSet rs = ps.executeQuery();
) {
Map<String, Map<String, Params>> map = new HashMap<>();
Map<String, Params> mapCommon = new HashMap<>();
int i = 0;
while (rs.next()) {
String tableName = rs.getString("table_name");
String className = tableName.replaceAll("m_", "");
String columnName = rs.getString("column_name");
String type = rs.getString("column_type");
if("(varchar(255)".equals(type)){
type = "String";
}else if("int(11)".equals(type)){
type = "int";
}
// 使首字母大写
String classNameUpCase = FreemarkUtil.toUpString(className);
String columnNameUpCase = FreemarkUtil.toUpString(columnName);
//这里只是使用一个实体类接收ResultSet的结果
Params p = new Params.Build()
.column(columnName)
.comment(rs.getString("column_comment"))
.defaultName(rs.getString("column_default"))
.type(type)
.key(rs.getString("column_key")).tableName(tableName)
.className(className).classNameUpCase(classNameUpCase)
.columnNameUpCase(columnNameUpCase)
.buildParams();
//将每一个组装好的实体类存入MAP,指定key
mapCommon.put("Params" + i, p);
i++;
}
//全部的MAP
map.put("Paramss", mapCommon);
System.out.println(map);
return map;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
2.2 Freemarker的使用
2.2.1 代码的调用
public class FreemarkUtil {
private static String driver = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://localhost:3306/test";
private static String username = "root";
private static String password = "*******";
//你模板放置的路径
private static String basePath = "D:\\Workspaces\\MyEclipse for Spring 2014\\genateJavaCode\\src\\genateJavaCode";
// 创建Configuration实例
private static Configuration cfg = new Configuration();
public static void genateCode() {
Template temp = null;
File loadTemplateFile = new File(basePath);
try {
cfg.setDirectoryForTemplateLoading(loadTemplateFile);
String saveDir = basePath + "/test";
Map<String, Map<String, Params>> classPropties = ConnectMySql
.connect(driver, url, username, password);
SetJavaCode(temp, saveDir, classPropties);
} catch (IOException e) {
e.printStackTrace();
}
}
// 首字母大写
public static String toUpString(String className) {
char[] cs = className.toCharArray();
cs[0] -= 32;
String ClassName = String.valueOf(cs);
return ClassName;
}
public static void SetJavaCode(Template temp, String saveDir,
Map<String, Map<String, Params>> classPropties) {
Map<String, Params> m = classPropties.get("Paramss");
//每一个实例里面都存有tableName,这里取第0个拿tableName
String tableName = (String) (m.get("Params0").getTableName());
//表明为m_user,指定类名为User
String className = tableName.replaceAll("m_", "");
// 使首字母大写
String ClassName = toUpString(className);
// 存入,作为参数给页面 className:作为引用名 ClassName:作为类名
String fileNameEntityPath = saveDir
+ "/entity/" + ClassName + ".java";
String fileNameDaoPath = saveDir
+ "/dao/" + ClassName + "Dao.java";
String fileNameServicePath = saveDir
+ "/service/" + ClassName+ "Service.java";
String fileNameServiceImplPath = saveDir
+ "/service/impl/" + ClassName + "ServiceImpl.java";
File newsDir = new File(saveDir);
File newsDir2 = new File(saveDir + "/dao/");
File newsDir3 = new File(saveDir + "/service/");
File newsDir4 = new File(saveDir + "/service/impl/");
File newsDir5 = new File(saveDir + "/entity/");
boolean flag = false;
flag = (Boolean) (newsDir.exists() == false ? newsDir.mkdirs() : true);
flag = (Boolean) (newsDir2.exists() == false ? newsDir2.mkdirs() : true);
flag = (Boolean) (newsDir3.exists() == false ? newsDir3.mkdirs() : true);
flag = (Boolean) (newsDir4.exists() == false ? newsDir4.mkdirs() : true);
flag = (Boolean) (newsDir5.exists() == false ? newsDir5.mkdirs() : true);
try (Writer out = new OutputStreamWriter(new FileOutputStream(
fileNameDaoPath), "utf-8");
Writer out2 = new OutputStreamWriter(new FileOutputStream(
fileNameServicePath), "utf-8");
Writer out3 = new OutputStreamWriter(new FileOutputStream(
fileNameServiceImplPath), "utf-8");
Writer out4 = new OutputStreamWriter(new FileOutputStream(
fileNameEntityPath), "utf-8");) {
temp = cfg.getTemplate("Dao.ftl");
temp.process(classPropties, out);
System.out.println("------------DAO生成完毕-------------");
temp = cfg.getTemplate("Service.ftl");
temp.process(classPropties, out2);
System.out.println("------------Service生成完毕-------------");
temp = cfg.getTemplate("ServiceImpl.ftl");
temp.process(classPropties, out3);
System.out.println("------------ServiceImpl生成完毕-------------");
temp = cfg.getTemplate("Object.ftl");
temp.process(classPropties, out4);
System.out.println("------------Entity生成完毕-------------");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
genateCode();
}
2.2.2 模板文件.ftl的配置
将封装好的Map<String, Map<String, Object>>
格式数据传入ftl
提一下:
顶级的MAP–key=Paramss
次一级的MAp—key0==Params0,key1==Params1,key…==Params….
参见前面put的代码
这里只举一个例子,模板文件名:entity.ftl,简单的实现。
import java.util.Date;
import com.pdsu.edu.domain.entity.${Paramss.Params0.classNameUpCase};
//通过mapKey.mapKey的方式获取设置的类名,因为每一个实体类中都有classNameUpCase
//这里取Params0这个key来用
public class ${Paramss.Params0.classNameUpCase} {
//以下为循环实体类的代码
<#list Paramss?values as value>
//${value.comment}
private ${value.type} ${value.column};
</#list>
<#list Paramss?values as value>
public ${value.type} get${value.columnNameUpCase}(){
return ${value.column};
}
public void set${value.columnNameUpCase} (${value.type} ${value.column}s){
this.${value.column} = ${value.column}s;
}
</#list>
}
2.2.3 用到的实体类代码
顺便使用了一下《effective JAVA》中提及的对象创建方式,方便入参,因为参数可能经常变化,table的还是属性比较多。
public class Params {
private String tableName;
private String column;
private String columnNameUpCase;
private String comment;
private String type;
private String keyName;
private String defaultName;
private String className;
private String classNameUpCase;
public Params(Build build) {
this.className = build.className;
this.classNameUpCase = build.classNameUpCase;
this.tableName = build.tableName;
this.column = build.column;
this.comment = build.comment;
this.type = build.type;
this.keyName = build.keyName;
this.defaultName = build.defaultName;
this.columnNameUpCase = build.columnNameUpCase;
}
public static class Build {
private String className;
private String classNameUpCase;
private String tableName;
private String column;
private String columnNameUpCase;
private String comment;
private String keyName;
private String type;
private String defaultName;
public Build className(String classN) {
className = classN;
return this;
}
public Build classNameUpCase(String classNameUpC) {
classNameUpCase = classNameUpC;
return this;
}
public Build tableName(String tableN) {
tableName = tableN;
return this;
}
public Build columnNameUpCase(String columnNameUpCaseN) {
columnNameUpCase = columnNameUpCaseN;
return this;
}
public Build column(String columnN) {
column = columnN;
return this;
}
public Build key(String keyN) {
keyName = keyN;
return this;
}
public Build comment(String commentN) {
comment = commentN;
return this;
}
public Build type(String typeN) {
type = typeN;
return this;
}
public Build defaultName(String defaultN) {
defaultName = defaultN;
return this;
}
public Params buildParams() {
return new Params(this);
}
}
public String getTableName() {
return tableName;
}
public String getColumn() {
return column;
}
public String getColumnNameUpCase() {
return columnNameUpCase;
}
public String getComment() {
return comment;
}
public String getType() {
return type;
}
public String getKeyName() {
return keyName;
}
public String getDefaultName() {
return defaultName;
}
public String getClassName() {
return className;
}
public String getClassNameUpCase() {
return classNameUpCase;
}
}
以上就是本人套路Freemarker的全过程!