Java进阶之 如何自动生成代码
一、前言:为什么要有代码的自动生成?
对于这个问题 最简洁直接的回答就是:代替手动编写代码、提高工作效率。
什么样的场景和代码适合用自动生成这种方式呢?
做过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进阶之 如何自动生成代码相关推荐
- eclipse创建pojo_使用Eclipse Hibernate插件逐步为POJO域Java类和hbm自动生成代码
eclipse创建pojo 概述: 在本教程中,我们将使用Eclipse Hibernate工具自动生成域对象和相应的hbm xml文件. 如果您正在处理大型或中型项目,并且开始时有超过5个以上的表, ...
- 使用Eclipse Hibernate插件逐步为POJO域Java类和hbm自动生成代码
概述: 在本教程中,我们将使用Eclipse Hibernate工具自动生成域对象和相应的hbm xml文件. 如果您正在处理大型或中型项目,并且开始时有超过5个以上的表,则可能会发现此插件是自动生成 ...
- 黑科技:进阶必备,推荐两款自动生成代码神器
关注上方"测试开发技术",选择星标, 干货技术,第一时间送达! 最近两年,在互联网行业各大技术峰会上,都能看到关于工程效能这个概念,从侧面也反映出了研发效能已经逐渐被各企业所重视! ...
- C#分析数据库结构,使用XSL模板自动生成代码
<html> <head> <TITLE>分析数据库结构,自动生成代码</TITLE> <meta http-equiv="Conten ...
- 简单的利用IDEA搭建SpringBoot+Maven+Mybatis+自动生成代码
最近在系统的学习SpringBoot框架,并且要用该框架做个项目--网上也大大小小看了很多教程,感觉很多写文章的人都不太负责任,只知道搬运,大概都没有实际操作过,问题也是有很多,所以自己写一篇文章记录 ...
- SpringBoot如何自动生成实体类和Dao层以及映射文件(mybatis generator 自动生成代码)
一.首先添加自动生成代码插件 <!-- mybatis generator 自动生成代码插件 生成时解除注释 --><plugin><groupId>org.myb ...
- 【MyBatis】MyBatis自动生成代码之查询爬坑记
前言 项目使用SSM框架搭建Web后台服务,前台后使用restful api,后台使用MyBatisGenerator自动生成代码,在前台使用关键字进行查询时,遇到了一些很宝贵的坑,现记录如下.为展示 ...
- 使用Mybatis Generator自动生成代码
MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代码生成器. 它将为所有版本的MyBatis以及版本2.2.0之后的iBATIS版本生成代码. 它将内省数 ...
- SpringBoot入门篇--整合mybatis+generator自动生成代码+druid连接池+PageHelper分页插件
我们这一一篇博客讲的是如何整合Springboot和Mybatis框架,然后使用generator自动生成mapper,pojo等文件.然后再使用阿里巴巴提供的开源连接池druid,这个连接池的好处我 ...
最新文章
- 【Qt】Qt中使用ssl时报错:qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
- mysql using filesort_mysql using filesort Using temporary
- 在茫茫人海中发现相似的你——局部敏感哈希(LSH)
- 通过stream去重_stream去重
- 全栈工程师已经过时?
- python textrank_TextRank算法提取文本摘要
- 干货:科大讯飞最新语音识别系统和框架深度剖析
- Codeforces976D Degree Set 【构造】
- 配置 eNSP 连接VMware虚拟机网络
- 圆弧周长公式_弧长计算公式
- 基于JS/H5实现二维码扫码增强版-带视频演示
- ie浏览器多开-----同时登陆多个账号
- Esp8266 Node Mcu 一直乱码的问题详解
- RTI DDS 01
- 将ppt转换成html文件格式,如何将幻灯片.pptx格式转换成.ppt格式
- CVTE面试总结(全网面经,已收offer)
- Android Studio基础输入文本框EditText
- 经典重写alert方法
- OpenNi学习笔记
- java实习生简历模板