一、前言:为什么要有代码的自动生成?
    对于这个问题 最简洁直接的回答就是:代替手动编写代码、提高工作效率。

什么样的场景和代码适合用自动生成这种方式呢?
    做过Java服务端的朋友一定都知道代码中我们需要编写与数据库表映射的Java实体类(Entity)、需要编写与实体对应的DAO类(XxDao.java类中有包含对应实体的增、删、改、查基本操作)。在这些实体类中通常都是一些属性方法以及属性对应的get/set方法、而实体对应的DAO类中也基本会包含有增、删、改、查这些与数据库操作相关的方法。在编写了那么多的实体类和Dao类的过程中 你是否发现了这些代码中有很多地方都相似或者差不多、只是名字不同而已呢?对、那么这个时候其实我们可以定义一个模板、通过模板我们来让代码自动生成去吧。

二、FreeMarker的简单介绍
   在进入正文前,让我们首先简单、快速了解一下FreeMarker。
  (做过Web开发的朋友肯定都是相当熟悉的、小吕当时 也是在做Web开发的时候第一次接触了FreeMarker)
   1、概述:FreeMarker是一款模板引擎:即一种基于模板、用来生成输出文本的通用工具。更多的是被用来设计生成HTML页面。

简单说就是:FreeMarker是使用模板生成文本页面来呈现已经准备好的数据。如下图表述

FreeMarker官网:http://freemarker.org/
   
   2、通过一个简单的例子来展示如何使用FreeMarker定义模板、绑定模型数据、生成最终显示的Html页面:
     1>.新建项目 在项目根目录下新建"template"文件夹,用来存放我们的Template file,

如我们新建模板文件test.ftl  内容如下:

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>
Welcome ${user}<#if user == "Big Joe">, our beloved leader</#if>!
</h1>
<p>Our latest product:
<a href="${latestProduct.url}">${latestProduct.name}</a>!
</body>
</html>

2>.项目引入freemarker.jar(下载地址:https://jarfiles.pandaidea.com/freemarker.html),
   在Java类中使用FreeMarker API方法引用模板文件、创建数据模型、合并数据模型与模板文件最终输入,

代码如下:

import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;public class HtmlGeneratorClient {public static void main(String[] args) {try {Configuration cfg = new Configuration();// 指定模板文件从何处加载的数据源,这里设置成一个文件目录cfg.setDirectoryForTemplateLoading(new File("./template"));cfg.setObjectWrapper(new DefaultObjectWrapper());// 获取或创建模板Template template = cfg.getTemplate("test.ftl");// 创建数据模型Map root = new HashMap();root.put("user", "Big Joe");        Map latest = new HashMap();root.put("latestProduct", latest);latest.put("url", "products/greenmouse.html");latest.put("name", "green mouse");// 将模板和数据模型合并 输出到ConsoleWriter out = new OutputStreamWriter(System.out);template.process(root, out);out.flush();} catch (IOException e) {e.printStackTrace();} catch (TemplateException e) {e.printStackTrace();}}}

3>.最终生成的HTML的页面代码如下:

<html>
<head>
<title>Welcome!</title>
</head>
<body>
<h1>
Welcome Big Joe, our beloved leader!
</h1>
<p>Our latest product:
<a href="products/greenmouse.html">green mouse</a>!
</body>
</html>

三、如何使用FreeMerker完成Java类代码的自动生成
   上面示例 我们的ftl模板文件定义的是HTML页面模板,那么我们将ftl模板定义为Java代码呢 通过数据模板的绑定不就可以生成Java类啦,
   下面小吕将利用模板来自动创建实体对象的java类(编写实体类的模板文件相对逻辑简单,但简单归简单,最重要的还是我们要掌握它的思想)
   1、属性类型的枚举类 PropertyType.java

/*** 属性类型枚举类* @author  lvzb.software@qq.com**/
public enum PropertyType {Byte, Short, Int, Long, Boolean, Float, Double, String, ByteArray, Date
}

2、实体对应的字段属性类 Property.java

/*** 实体对应的属性类* @author  lvzb.software@qq.com**/
public class Property {// 属性数据类型private String javaType;// 属性名称private String propertyName;private PropertyType propertyType;public String getJavaType() {return javaType;}public void setJavaType(String javaType) {this.javaType = javaType;}public String getPropertyName() {return propertyName;}public void setPropertyName(String propertyName) {this.propertyName = propertyName;}public PropertyType getPropertyType() {return propertyType;}public void setPropertyType(PropertyType propertyType) {this.propertyType = propertyType;}}

3、实体模型类 Entity.java

import java.util.List;/*** 实体类* @author  lvzb.software@qq.com**/
public class Entity {// 实体所在的包名private String javaPackage;// 实体类名private String className;// 父类名private String superclass;// 属性集合List<Property> properties;// 是否有构造函数private boolean constructors;    public String getJavaPackage() {return javaPackage;}public void setJavaPackage(String javaPackage) {this.javaPackage = javaPackage;}public String getClassName() {return className;}public void setClassName(String className) {this.className = className;}public String getSuperclass() {return superclass;}public void setSuperclass(String superclass) {this.superclass = superclass;}public List<Property> getProperties() {return properties;}public void setProperties(List<Property> properties) {this.properties = properties;}public boolean isConstructors() {return constructors;}public void setConstructors(boolean constructors) {this.constructors = constructors;}    }

4、在项目根目录下新建"template"文件夹,用来存放我们的Template file, 新建实体模板entity.ftl 内容如下:

package ${entity.javaPackage};/*** This code is generated by FreeMarker* @author lvzb.software@qq.com**/
public class ${entity.className}<#if entity.superclass?has_content> extends ${entity.superclass} </#if>
{/********** attribute ***********/
<#list entity.properties as property>private ${property.javaType} ${property.propertyName};</#list>/********** constructors ***********/
<#if entity.constructors>public ${entity.className}() {}public ${entity.className}(<#list entity.properties as property>${property.javaType} ${property.propertyName}<#if property_has_next>, </#if></#list>) {<#list entity.properties as property>this.${property.propertyName} = ${property.propertyName};</#list>}
</#if>/********** get/set ***********/
<#list entity.properties as property>public ${property.javaType} get${property.propertyName?cap_first}() {return ${property.propertyName};}public void set${property.propertyName?cap_first}(${property.javaType} ${property.propertyName}) {this.${property.propertyName} = ${property.propertyName};}</#list>
}

5、自动生成实体类 客户端代码 EntityGeneratorClient.java

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/*** 自动生成实体类客户端* @author lvzb.software@qq.com**/
public class EntityGeneratorClient {private static File javaFile = null;public static void main(String[] args) {Configuration cfg = new Configuration();  try { // 步骤一:指定 模板文件从何处加载的数据源,这里设置一个文件目录cfg.setDirectoryForTemplateLoading(new File("./template"));cfg.setObjectWrapper(new DefaultObjectWrapper());// 步骤二:获取 模板文件Template template = cfg.getTemplate("entity.ftl");// 步骤三:创建 数据模型Map<String, Object> root = createDataModel();// 步骤四:合并 模板 和 数据模型// 创建.java类文件if(javaFile != null){Writer javaWriter = new FileWriter(javaFile);template.process(root, javaWriter);javaWriter.flush();System.out.println("文件生成路径:" + javaFile.getCanonicalPath());javaWriter.close();}// 输出到Console控制台Writer out = new OutputStreamWriter(System.out);template.process(root, out);out.flush();out.close();} catch (IOException e) {e.printStackTrace();} catch (TemplateException e) {e.printStackTrace();}}/*** 创建数据模型* @return*/private static Map<String, Object> createDataModel() {Map<String, Object> root = new HashMap<String, Object>();Entity user = new Entity();user.setJavaPackage("com.study.entity"); // 创建包名user.setClassName("User");  // 创建类名user.setConstructors(true); // 是否创建构造函数// user.setSuperclass("person");List<Property> propertyList = new ArrayList<Property>();// 创建实体属性一 Property attribute1 = new Property();attribute1.setJavaType("String");attribute1.setPropertyName("name");attribute1.setPropertyType(PropertyType.String);// 创建实体属性二Property attribute2 = new Property();attribute2.setJavaType("int");attribute2.setPropertyName("age");attribute2.setPropertyType(PropertyType.Int);propertyList.add(attribute1);propertyList.add(attribute2);// 将属性集合添加到实体对象中user.setProperties(propertyList);// 创建.java类文件File outDirFile = new File("./src-template");if(!outDirFile.exists()){outDirFile.mkdir();}javaFile = toJavaFilename(outDirFile, user.getJavaPackage(), user.getClassName());root.put("entity", user);return root;}/*** 创建.java文件所在路径 和 返回.java文件File对象* @param outDirFile 生成文件路径* @param javaPackage java包名* @param javaClassName java类名* @return*/private static File toJavaFilename(File outDirFile, String javaPackage, String javaClassName) {String packageSubPath = javaPackage.replace('.', '/');File packagePath = new File(outDirFile, packageSubPath);File file = new File(packagePath, javaClassName + ".java");if(!packagePath.exists()){packagePath.mkdirs();}return file;}}

6、运行程序 我们将会在项目根目录下 生成文件夹 src-template以及自动生成的实体类User.java
    效果图如下:
       --- 运行后 --->

<程序运行前目录结构>                                                <程序运行后目录结构>

自动生成的实体类User.java 代码如下:

package com.study.entity;/*** This code is generated by FreeMarker* @author lvzb.software@qq.com**/
public class User
{/********** attribute ***********/private String name;private int age;/********** constructors ***********/public User() {}public User(String name, int age) {this.name = name;this.age = age;}/********** get/set ***********/public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

四、背后的思考

通过上面两个简单的示例我们了解到所谓的自动生成代码其实就是:

1、定义java类模板文件 2、定义模板数据  3、引用模板文件(.ftl)与模板数据合并生成Java类。

上面的示例中 有的朋友可能会问不就是要编写一个实体对象吗?干嘛搞那么麻烦、又建.ftl文件、又写了那么多类、定义模板数据的过程也是那么麻烦、我还不如手动去写、声明几个属性、set/get快捷键一下子就编写好啦。 真的是这样吗?
    从一个辅助工具和软件架构的方面去思考,假设做成一个开发的辅助工具或是插件去完成实体类和对应DAO类的自动生成。假设需要建10个实体类和对应含有增删改查基本操作的DAO类。我在C/S客户端上填写包名、类名、属性字段等信息 然后一键生成,想想那是多么爽、多么痛快的一件事(当然 前提是你的模板类要编写的非常强大、通用),而你也许还在不停的 Ctrl+C、Ctrl+V。

五、其他
   关于如何编写.ftl模板文件、就需要自己去翻阅资料自我学习啦!

小吕还是提供FreeMarker官网:http://freemarker.org/

最后小吕 附上本篇的源码下载地址:http://download.csdn.net/detail/l416112167/8305899

六、扩展学习

使用 Velocity 模板引擎快速生成代码:[非常值得扩展学习]

http://www.ibm.com/developerworks/cn/java/j-lo-velocity1/index.html

Java进阶之 如何自动生成代码相关推荐

  1. eclipse创建pojo_使用Eclipse Hibernate插件逐步为POJO域Java类和hbm自动生成代码

    eclipse创建pojo 概述: 在本教程中,我们将使用Eclipse Hibernate工具自动生成域对象和相应的hbm xml文件. 如果您正在处理大型或中型项目,并且开始时有超过5个以上的表, ...

  2. 使用Eclipse Hibernate插件逐步为POJO域Java类和hbm自动生成代码

    概述: 在本教程中,我们将使用Eclipse Hibernate工具自动生成域对象和相应的hbm xml文件. 如果您正在处理大型或中型项目,并且开始时有超过5个以上的表,则可能会发现此插件是自动生成 ...

  3. 黑科技:进阶必备,推荐两款自动生成代码神器

    关注上方"测试开发技术",选择星标, 干货技术,第一时间送达! 最近两年,在互联网行业各大技术峰会上,都能看到关于工程效能这个概念,从侧面也反映出了研发效能已经逐渐被各企业所重视! ...

  4. C#分析数据库结构,使用XSL模板自动生成代码

    <html> <head> <TITLE>分析数据库结构,自动生成代码</TITLE> <meta http-equiv="Conten ...

  5. 简单的利用IDEA搭建SpringBoot+Maven+Mybatis+自动生成代码

    最近在系统的学习SpringBoot框架,并且要用该框架做个项目--网上也大大小小看了很多教程,感觉很多写文章的人都不太负责任,只知道搬运,大概都没有实际操作过,问题也是有很多,所以自己写一篇文章记录 ...

  6. SpringBoot如何自动生成实体类和Dao层以及映射文件(mybatis generator 自动生成代码)

    一.首先添加自动生成代码插件 <!-- mybatis generator 自动生成代码插件 生成时解除注释 --><plugin><groupId>org.myb ...

  7. 【MyBatis】MyBatis自动生成代码之查询爬坑记

    前言 项目使用SSM框架搭建Web后台服务,前台后使用restful api,后台使用MyBatisGenerator自动生成代码,在前台使用关键字进行查询时,遇到了一些很宝贵的坑,现记录如下.为展示 ...

  8. 使用Mybatis Generator自动生成代码

    MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代码生成器. 它将为所有版本的MyBatis以及版本2.2.0之后的iBATIS版本生成代码. 它将内省数 ...

  9. SpringBoot入门篇--整合mybatis+generator自动生成代码+druid连接池+PageHelper分页插件

    我们这一一篇博客讲的是如何整合Springboot和Mybatis框架,然后使用generator自动生成mapper,pojo等文件.然后再使用阿里巴巴提供的开源连接池druid,这个连接池的好处我 ...

最新文章

  1. 【Qt】Qt中使用ssl时报错:qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
  2. mysql using filesort_mysql using filesort Using temporary
  3. 在茫茫人海中发现相似的你——局部敏感哈希(LSH)
  4. 通过stream去重_stream去重
  5. 全栈工程师已经过时?
  6. python textrank_TextRank算法提取文本摘要
  7. 干货:科大讯飞最新语音识别系统和框架深度剖析
  8. Codeforces976D Degree Set 【构造】
  9. 配置 eNSP 连接VMware虚拟机网络
  10. 圆弧周长公式_弧长计算公式
  11. 基于JS/H5实现二维码扫码增强版-带视频演示
  12. ie浏览器多开-----同时登陆多个账号
  13. Esp8266 Node Mcu 一直乱码的问题详解
  14. RTI DDS 01
  15. 将ppt转换成html文件格式,如何将幻灯片.pptx格式转换成.ppt格式
  16. CVTE面试总结(全网面经,已收offer)
  17. Android Studio基础输入文本框EditText
  18. 经典重写alert方法
  19. OpenNi学习笔记
  20. java实习生简历模板

热门文章

  1. Android 11 从沙盒拷贝文件到外部共享存储区域
  2. matlab找出定价规律,基于MATLAB建立数学模型对定价系统的研究
  3. 地理住宅区的特点_北京各地区居住生活的人,有区域性特点么?
  4. 《我的世界》Python编程入门(0) 给家长的建议
  5. 顶尖棋牌游戏源码_完整
  6. 【基于STM32F103C8T6的智能风扇控制】
  7. 2018夏天的俄罗斯之旅
  8. 像大牛一样写代码: 31个Android 开发者工具
  9. 当服务器突然down机,你又不知道之前跑了哪些服务时
  10. Mac OS X下MATLAB R2012b安装及破解