讲代码生成器之前先要说说模板,什么叫模板呢,举个例子吧,汇款单都见过吧,你不填写的那些内容都属于模板范畴
说到这应该明白了吧,模板就是把共性提取出来反复使用,节约时间、工作量。。。。。
那跟代码生成器有什么关系呢,思考一下在编程语言中所有的语言是不是都用共性或者说规范,这些都是固定不变的,在具体点,软件行业也是分主营业务 的,比如OA、CRM、ERP、SCM等等,那么各个业务方向的软件是不是也有其行业特点,这是不是也是固定的,那么这就完了,这些独特的地方是不是可以 提取出来作为模板呢,不言而喻
言归正传,说到模板就不得不说现在主流的模板技术了,FreeMarker、Velocity(这个google在用),模板技术推崇一种模式:
输出=模板+数据,所以运用到代码生成器上也是一样的道理,举个简单例子比如要生成一个javabean组件,就普通的pojo类,
那么先分析一下生成这种类有什么共性呢,关键字就不用说了,getter和setter方法都是get+属性名uppercase首字母和set+ 属性名uppercase首字母,还有“{}”、“;”、“()”等等这些都是不变的,那么这些内容就可以作为模板内容,包名、类名、属性名这些是人为要 取的,这些是变化的,故变的这部分就作为数据,这样就可以根据不同的‘数据’来生成不同的javabean
项目准备:先去down个freemarker.jar包, http://freemarker.org/freemarkerdownload.html
上篇讨论了代码生成器的原理,输出=模板+数据,那么现在就生成一个Student.java文件做个简单例子。
首先先写出模板,先解决一个问题,上篇有讲到属性名首字母大写的问题
由于freemarker中不支持将首字母大写(属性名中用到),那么自己先写一个自定义宏如下:
- package com;
- import java.io.IOException;
- import java.io.Writer;
- import java.util.Map;
- import freemarker.core.Environment;
- import freemarker.template.TemplateDirectiveBody;
- import freemarker.template.TemplateDirectiveModel;
- import freemarker.template.TemplateException;
- import freemarker.template.TemplateModel;
- import freemarker.template.TemplateModelException;
- public class UpperFirstCharacter implements TemplateDirectiveModel {
- public void execute(Environment env,
- Map params, TemplateModel[] loopVars,
- TemplateDirectiveBody body)
- throws TemplateException, IOException {
- // Check if no parameters were given:
- if (!params.isEmpty()) {
- throw new TemplateModelException(
- “This directive doesn’t allow parameters.” );
- }
- if (loopVars.length != 0 ) {
- throw new TemplateModelException(
- “This directive doesn’t allow loop variables.” );
- }
- // If there is non-empty nested content:
- if (body != null ) {
- // Executes the nested body. Same as <#nested> in FTL, except
- // that we use our own writer instead of the current output writer.
- body.render(new UpperCaseFilterWriter(env.getOut()));
- } else {
- throw new RuntimeException( “missing body” );
- }
- }
- /**
- * A {@link Writer} that transforms the character stream to upper case
- * and forwards it to another {@link Writer}.
- */
- private static class UpperCaseFilterWriter extends Writer {
- private final Writer out;
- UpperCaseFilterWriter (Writer out) {
- this .out = out;
- }
- public void write( char [] cbuf, int off, int len)
- throws IOException {
- // char[] transformedCbuf = new char[len];
- // for (int i = 0; i < len; i++) {
- // transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]);
- // }
- // out.write(transformedCbuf);
- cbuf[0 ] = Character.toUpperCase(cbuf[ 0 ]);
- out.write(String.valueOf(cbuf).trim());///把右边空格去掉
- }
- public void flush() throws IOException {
- out.flush();
- }
- public void close() throws IOException {
- out.close();
- }
- }
- }
- package com;
- import java.io.IOException;
- import java.io.Writer;
- import java.util.Map;
- import freemarker.core.Environment;
- import freemarker.template.TemplateDirectiveBody;
- import freemarker.template.TemplateDirectiveModel;
- import freemarker.template.TemplateException;
- import freemarker.template.TemplateModel;
- import freemarker.template.TemplateModelException;
- public class UpperFirstCharacter implements TemplateDirectiveModel {
- public void execute(Environment env,
- Map params, TemplateModel[] loopVars,
- TemplateDirectiveBody body)
- throws TemplateException, IOException {
- // Check if no parameters were given:
- if (!params.isEmpty()) {
- throw new TemplateModelException(
- “This directive doesn’t allow parameters.”);
- }
- if (loopVars.length != 0) {
- throw new TemplateModelException(
- “This directive doesn’t allow loop variables.”);
- }
- // If there is non-empty nested content:
- if (body != null) {
- // Executes the nested body. Same as <#nested> in FTL, except
- // that we use our own writer instead of the current output writer.
- body.render(new UpperCaseFilterWriter(env.getOut()));
- } else {
- throw new RuntimeException(“missing body”);
- }
- }
- /**
- * A {@link Writer} that transforms the character stream to upper case
- * and forwards it to another {@link Writer}.
- */
- private static class UpperCaseFilterWriter extends Writer {
- private final Writer out;
- UpperCaseFilterWriter (Writer out) {
- this.out = out;
- }
- public void write(char[] cbuf, int off, int len)
- throws IOException {
- // char[] transformedCbuf = new char[len];
- // for (int i = 0; i < len; i++) {
- // transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]);
- // }
- // out.write(transformedCbuf);
- cbuf[0] = Character.toUpperCase(cbuf[0]);
- out.write(String.valueOf(cbuf).trim());///把右边空格去掉
- }
- public void flush() throws IOException {
- out.flush();
- }
- public void close() throws IOException {
- out.close();
- }
- }
- }
下面呢就可以编写模板了,代码如下:
- package ${
package }; - //这个地方可以事先定义好需要的类
- import java.util.Date;
- import java.io.Serializable;
- public class ${className} implements Serializable{
- <#list properties as pro>
- private ${pro.proType} ${pro.proName};
- </#list>
- <#list properties as pro>
- public void set< @upperFC >${pro.proName}</ @upperFC >(${pro.proType} ${pro.proName}){
- this .${pro.proName}=${pro.proName};
- }
- public ${pro.proType} get< @upperFC >${pro.proName}</ @upperFC >(){
- return this .${pro.proName};
- }
- </#list>
- }
- package ${
package}; - //这个地方可以事先定义好需要的类
- import java.util.Date;
- import java.io.Serializable;
- public class ${className} implements Serializable{
- <#list properties as pro>
- private ${pro.proType} ${pro.proName};
- </#list>
- <#list properties as pro>
- public void set<@upperFC>${pro.proName}</@upperFC>(${pro.proType} ${pro.proName}){
- this.${pro.proName}=${pro.proName};
- }
- public ${pro.proType} get<@upperFC>${pro.proName}</@upperFC>(){
- return this.${pro.proName};
- }
- </#list>
- }
模板文件取名为javabean.html,在com包下
下面编写测试类:
- package com;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.OutputStreamWriter;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import freemarker.template.Configuration;
- import freemarker.template.Template;
- import freemarker.template.TemplateException;
- public class Test {
- /**
- * @param args
- */
- public static void main(String[] args) {
- //System.out.println(System.getProperty(“user.dir”)+”============”);
- Configuration cfg = new Configuration();
- try {
- cfg.setClassForTemplateLoading(Test.class , “/com” ); //指定模板所在的classpath目录
- cfg.setSharedVariable(“upperFC” , new UpperFirstCharacter()); //添加一个”宏”共享变量用来将属性名首字母大写
- Template t = cfg.getTemplate(“javabean.html” ); //指定模板
- FileOutputStream fos = new FileOutputStream( new File( “d:/Student.java”)); //java文件的生成目录
- //模拟数据源
- Map data = new HashMap();
- data.put(“package” , “edu” ); //包名
- data.put(“className” , “Student” );
- List pros = new ArrayList();
- Map pro_1 = new HashMap();
- pro_1.put(“proType” , String. class .getSimpleName());
- pro_1.put(“proName” , “name” );
- pros.add(pro_1);
- Map pro_2 = new HashMap();
- pro_2.put(“proType” , String. class .getSimpleName());
- pro_2.put(“proName” , “sex” );
- pros.add(pro_2);
- Map pro_3 = new HashMap();
- pro_3.put(“proType” , Integer. class .getSimpleName());
- pro_3.put(“proName” , “age” );
- pros.add(pro_3);
- data.put(“properties” , pros);
- t.process(data, new OutputStreamWriter(fos, “utf-8” )); //
- fos.flush();
- fos.close();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (TemplateException e) {
- e.printStackTrace();
- }
- }
- }
- package com;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.OutputStreamWriter;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import freemarker.template.Configuration;
- import freemarker.template.Template;
- import freemarker.template.TemplateException;
- public class Test {
- /**
- * @param args
- */
- public static void main(String[] args) {
- //System.out.println(System.getProperty(“user.dir”)+”============”);
- Configuration cfg = new Configuration();
- try {
- cfg.setClassForTemplateLoading(Test.class, “/com”);//指定模板所在的classpath目录
- cfg.setSharedVariable(“upperFC”, new UpperFirstCharacter());//添加一个”宏”共享变量用来将属性名首字母大写
- Template t = cfg.getTemplate(“javabean.html”);//指定模板
- FileOutputStream fos = new FileOutputStream(new File(“d:/Student.java”));//java文件的生成目录
- //模拟数据源
- Map data = new HashMap();
- data.put(“package”, “edu”);//包名
- data.put(“className”, “Student”);
- List pros = new ArrayList();
- Map pro_1 = new HashMap();
- pro_1.put(“proType”, String.class.getSimpleName());
- pro_1.put(“proName”, “name”);
- pros.add(pro_1);
- Map pro_2 = new HashMap();
- pro_2.put(“proType”, String.class.getSimpleName());
- pro_2.put(“proName”, “sex”);
- pros.add(pro_2);
- Map pro_3 = new HashMap();
- pro_3.put(“proType”, Integer.class.getSimpleName());
- pro_3.put(“proName”, “age”);
- pros.add(pro_3);
- data.put(“properties”, pros);
- t.process(data, new OutputStreamWriter(fos,“utf-8”));//
- fos.flush();
- fos.close();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (TemplateException e) {
- e.printStackTrace();
- }
- }
- }
运行一下测试类,在D盘可以找到一个Student.java的文件,打开看看对不对
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133050.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...