freemarker入门 – 关于java代码生成器详解编程语言
讲代码生成器之前先要说说模板,什么叫模板呢,举个例子吧,汇款单都见过吧,你不填写的那些内容都属于模板范畴
说到这应该明白了吧,模板就是把共性提取出来反复使用,节约时间、工作量。。。。。
那跟代码生成器有什么关系呢,思考一下在编程语言中所有的语言是不是都用共性或者说规范,这些都是固定不变的,在具体点,软件行业也是分主营业务 的,比如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 [email protected] Writer} that transforms the character stream to upper case * and forwards it to another [email protected] 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(); } } }
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 [email protected] Writer} that transforms the character stream to upper case * and forwards it to another [email protected] 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 }
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(); } } }
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(); } } }
相关文章
- Java 反射 -超详细讲解(附源码)「建议收藏」
- java从入门到精通_Java 入门到精通的过程
- 常用的Java工具,16个
- Java入门基础学习总结[通俗易懂]
- JAVA入门学习七
- java在线播放_Java实现视频在线播放flv视频
- Java方法重载_java入门方法的使用
- java发送请求网络请求
- java爬虫入门实战详解编程语言
- java压缩与解压(Java.util.zip)详解编程语言
- Java网络编程入门SocketServer与Socket详解编程语言
- Java版本的浏览器HtmlUnit入门示例详解编程语言
- Java学习笔记之七java函数的语法规则总结详解编程语言
- java-jpa-criteriaBuilder使用入门详解编程语言
- java 标准输出与标准错误 out与 err 区别 用法 联系 java中的out与err区别 System.out和System.err的区别 System.out.println和System.err.println的区别 Java重定向System.out和System.err详解编程语言
- Java多线程入门详解编程语言
- Java数据持久层框架 MyBatis之API学习二(入门)详解编程语言
- Java多线程超详解编程语言
- 玩转Linux:Java开发入门指南(linux上开发java)
- 面试前准备:Java技术和Redis快速入门(java面试redis)
- MacOS下Java开发环境搭建指南(macos开发java)
- Java面试中的Redis题目剖析(java面试题redis)
- 教程:在Linux系统下安装Java(linux下java安装)
- Novice:学习Java 7 在Linux上的简单入门(java 7 linux)
- Linux系统下Java软件环境搭建指导(linux java软件)
- Java Redis一次实现无限数据加速的尝试(用java redis)
- 异常Java程序捕获Oracle异常从失败中学习(java捕获oracle)
- Oracle搭建Java开发环境的步骤(oracle中java)