关于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中不支持将首字母大写(属性名中用到),那么自己先写一个自定义宏如下:

  1. package  com;  
  2.   
  3. import  java.io.IOException;  
  4. import  java.io.Writer;  
  5. import  java.util.Map;  
  6.   
  7. import  freemarker.core.Environment;  
  8. import  freemarker.template.TemplateDirectiveBody;  
  9. import  freemarker.template.TemplateDirectiveModel;  
  10. import  freemarker.template.TemplateException;  
  11. import  freemarker.template.TemplateModel;  
  12. import  freemarker.template.TemplateModelException;  
  13.   
  14. public   class  UpperFirstCharacter  implements  TemplateDirectiveModel {  
  15.   
  16.     public   void  execute(Environment env,  
  17.             Map params, TemplateModel[] loopVars,  
  18.             TemplateDirectiveBody body)  
  19.             throws  TemplateException, IOException {  
  20.         // Check if no parameters were given:   
  21.         if  (!params.isEmpty()) {  
  22.             throw   new  TemplateModelException(  
  23.                     "This directive doesn't allow parameters." );  
  24.         }  
  25.         if  (loopVars.length !=  0 ) {  
  26.                 throw   new  TemplateModelException(  
  27.                     "This directive doesn't allow loop variables." );  
  28.         }  
  29.           
  30.         // If there is non-empty nested content:   
  31.         if  (body !=  null ) {  
  32.             // Executes the nested body. Same as <#nested> in FTL, except   
  33.             // that we use our own writer instead of the current output writer.   
  34.             body.render(new  UpperCaseFilterWriter(env.getOut()));  
  35.         } else  {  
  36.             throw   new  RuntimeException( "missing body" );  
  37.         }  
  38.     }  
  39.       
  40.     /**  
  41.      * A {@link Writer} that transforms the character stream to upper case  
  42.      * and forwards it to another {@link Writer}.  
  43.      */    
  44.     private   static   class  UpperCaseFilterWriter  extends  Writer {  
  45.          
  46.         private   final  Writer out;  
  47.              
  48.         UpperCaseFilterWriter (Writer out) {  
  49.             this .out = out;  
  50.         }  
  51.   
  52.         public   void  write( char [] cbuf,  int  off,  int  len)  
  53.                 throws  IOException {  
  54. //            char[] transformedCbuf = new char[len];   
  55. //            for (int i = 0; i < len; i++) {   
  56. //                transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]);   
  57. //            }   
  58. //            out.write(transformedCbuf);   
  59.             cbuf[0 ] = Character.toUpperCase(cbuf[ 0 ]);  
  60.             out.write(String.valueOf(cbuf).trim());///把右边空格去掉   
  61.         }  
  62.   
  63.         public   void  flush()  throws  IOException {  
  64.             out.flush();  
  65.         }  
  66.   
  67.         public   void  close()  throws  IOException {  
  68.             out.close();  
  69.         }  
  70.     }  
  71.   
  72. }  
[Java]  view plain copy
  1. package com;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.Writer;  
  5. import java.util.Map;  
  6.   
  7. import freemarker.core.Environment;  
  8. import freemarker.template.TemplateDirectiveBody;  
  9. import freemarker.template.TemplateDirectiveModel;  
  10. import freemarker.template.TemplateException;  
  11. import freemarker.template.TemplateModel;  
  12. import freemarker.template.TemplateModelException;  
  13.   
  14. public class UpperFirstCharacter implements TemplateDirectiveModel {  
  15.   
  16.     public void execute(Environment env,  
  17.             Map params, TemplateModel[] loopVars,  
  18.             TemplateDirectiveBody body)  
  19.             throws TemplateException, IOException {  
  20.         // Check if no parameters were given:  
  21.         if (!params.isEmpty()) {  
  22.             throw new TemplateModelException(  
  23.                     "This directive doesn't allow parameters.");  
  24.         }  
  25.         if (loopVars.length != 0) {  
  26.                 throw new TemplateModelException(  
  27.                     "This directive doesn't allow loop variables.");  
  28.         }  
  29.           
  30.         // If there is non-empty nested content:  
  31.         if (body != null) {  
  32.             // Executes the nested body. Same as <#nested> in FTL, except  
  33.             // that we use our own writer instead of the current output writer.  
  34.             body.render(new UpperCaseFilterWriter(env.getOut()));  
  35.         } else {  
  36.             throw new RuntimeException("missing body");  
  37.         }  
  38.     }  
  39.       
  40.     /** 
  41.      * A {@link Writer} that transforms the character stream to upper case 
  42.      * and forwards it to another {@link Writer}. 
  43.      */   
  44.     private static class UpperCaseFilterWriter extends Writer {  
  45.          
  46.         private final Writer out;  
  47.              
  48.         UpperCaseFilterWriter (Writer out) {  
  49.             this.out = out;  
  50.         }  
  51.   
  52.         public void write(char[] cbuf, int off, int len)  
  53.                 throws IOException {  
  54. //            char[] transformedCbuf = new char[len];  
  55. //            for (int i = 0; i < len; i++) {  
  56. //                transformedCbuf[i] = Character.toUpperCase(cbuf[i + off]);  
  57. //            }  
  58. //            out.write(transformedCbuf);  
  59.             cbuf[0] = Character.toUpperCase(cbuf[0]);  
  60.             out.write(String.valueOf(cbuf).trim());///把右边空格去掉  
  61.         }  
  62.   
  63.         public void flush() throws IOException {  
  64.             out.flush();  
  65.         }  
  66.   
  67.         public void close() throws IOException {  
  68.             out.close();  
  69.         }  
  70.     }  
  71.   
  72. }  

 

下面呢就可以编写模板了,代码如下:

  1. package  ${ package };  
  2.   
  3. //这个地方可以事先定义好需要的类   
  4. import  java.util.Date;  
  5.   
  6. import  java.io.Serializable;  
  7.   
  8. public   class  ${className}  implements  Serializable{  
  9. <#list properties as pro>  
  10.     private  ${pro.proType} ${pro.proName};  
  11. </#list>  
  12.       
  13. <#list properties as pro>  
  14.     public   void  set< @upperFC >${pro.proName}</ @upperFC >(${pro.proType} ${pro.proName}){  
  15.         this .${pro.proName}=${pro.proName};  
  16.     }  
  17.       
  18.     public  ${pro.proType} get< @upperFC >${pro.proName}</ @upperFC >(){  
  19.         return   this .${pro.proName};  
  20.     }  
  21.       
  22. </#list>  
  23. }  
[Java]  view plain copy
  1. package ${package};  
  2.   
  3. //这个地方可以事先定义好需要的类  
  4. import java.util.Date;  
  5.   
  6. import java.io.Serializable;  
  7.   
  8. public class ${className} implements Serializable{  
  9. <#list properties as pro>  
  10.     private ${pro.proType} ${pro.proName};  
  11. </#list>  
  12.       
  13. <#list properties as pro>  
  14.     public void set<@upperFC>${pro.proName}</@upperFC>(${pro.proType} ${pro.proName}){  
  15.         this.${pro.proName}=${pro.proName};  
  16.     }  
  17.       
  18.     public ${pro.proType} get<@upperFC>${pro.proName}</@upperFC>(){  
  19.         return this.${pro.proName};  
  20.     }  
  21.       
  22. </#list>  
  23. }  

模板文件取名为javabean.html,在com包下

下面编写测试类:

  1. package  com;  
  2.   
  3. import  java.io.File;  
  4. import  java.io.FileOutputStream;  
  5. import  java.io.IOException;  
  6. import  java.io.OutputStreamWriter;  
  7. import  java.util.ArrayList;  
  8. import  java.util.HashMap;  
  9. import  java.util.List;  
  10. import  java.util.Map;  
  11.   
  12. import  freemarker.template.Configuration;  
  13. import  freemarker.template.Template;  
  14. import  freemarker.template.TemplateException;  
  15.   
  16. public   class  Test {  
  17.   
  18.     /**  
  19.      * @param args  
  20.      */   
  21.     public   static   void  main(String[] args) {  
  22.         //System.out.println(System.getProperty("user.dir")+"============");   
  23.         Configuration cfg = new  Configuration();  
  24.         try  {  
  25.             cfg.setClassForTemplateLoading(Test.class  "/com" ); //指定模板所在的classpath目录   
  26.             cfg.setSharedVariable("upperFC"  new  UpperFirstCharacter()); //添加一个"宏"共享变量用来将属性名首字母大写   
  27.             Template t = cfg.getTemplate("javabean.html" ); //指定模板   
  28.             FileOutputStream fos = new  FileOutputStream( new  File( "d:/Student.java")); //java文件的生成目录   
  29.               
  30.             //模拟数据源   
  31.             Map data = new  HashMap();  
  32.             data.put("package"  "edu" ); //包名   
  33.             data.put("className"  "Student" );  
  34.               
  35.             List pros = new  ArrayList();  
  36.             Map pro_1 = new  HashMap();  
  37.             pro_1.put("proType" , String. class .getSimpleName());  
  38.             pro_1.put("proName"  "name" );  
  39.             pros.add(pro_1);  
  40.               
  41.             Map pro_2 = new  HashMap();  
  42.             pro_2.put("proType" , String. class .getSimpleName());  
  43.             pro_2.put("proName"  "sex" );  
  44.             pros.add(pro_2);  
  45.               
  46.             Map pro_3 = new  HashMap();  
  47.             pro_3.put("proType" , Integer. class .getSimpleName());  
  48.             pro_3.put("proName"  "age" );  
  49.             pros.add(pro_3);  
  50.               
  51.             data.put("properties" , pros);  
  52.             t.process(data, new  OutputStreamWriter(fos, "utf-8" )); //   
  53.             fos.flush();  
  54.             fos.close();  
  55.         } catch  (IOException e) {  
  56.             e.printStackTrace();  
  57.         } catch  (TemplateException e) {  
  58.             e.printStackTrace();  
  59.         }  
  60.     }  
  61.   
  62. }  
[Java]  view plain copy
  1. package com;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.OutputStreamWriter;  
  7. import java.util.ArrayList;  
  8. import java.util.HashMap;  
  9. import java.util.List;  
  10. import java.util.Map;  
  11.   
  12. import freemarker.template.Configuration;  
  13. import freemarker.template.Template;  
  14. import freemarker.template.TemplateException;  
  15.   
  16. public class Test {  
  17.   
  18.     /** 
  19.      * @param args 
  20.      */  
  21.     public static void main(String[] args) {  
  22.         //System.out.println(System.getProperty("user.dir")+"============");  
  23.         Configuration cfg = new Configuration();  
  24.         try {  
  25.             cfg.setClassForTemplateLoading(Test.class"/com");//指定模板所在的classpath目录  
  26.             cfg.setSharedVariable("upperFC"new UpperFirstCharacter());//添加一个"宏"共享变量用来将属性名首字母大写  
  27.             Template t = cfg.getTemplate("javabean.html");//指定模板  
  28.             FileOutputStream fos = new FileOutputStream(new File("d:/Student.java"));//java文件的生成目录  
  29.               
  30.             //模拟数据源  
  31.             Map data = new HashMap();  
  32.             data.put("package""edu");//包名  
  33.             data.put("className""Student");  
  34.               
  35.             List pros = new ArrayList();  
  36.             Map pro_1 = new HashMap();  
  37.             pro_1.put("proType", String.class.getSimpleName());  
  38.             pro_1.put("proName""name");  
  39.             pros.add(pro_1);  
  40.               
  41.             Map pro_2 = new HashMap();  
  42.             pro_2.put("proType", String.class.getSimpleName());  
  43.             pro_2.put("proName""sex");  
  44.             pros.add(pro_2);  
  45.               
  46.             Map pro_3 = new HashMap();  
  47.             pro_3.put("proType", Integer.class.getSimpleName());  
  48.             pro_3.put("proName""age");  
  49.             pros.add(pro_3);  
  50.               
  51.             data.put("properties", pros);  
  52.             t.process(data, new OutputStreamWriter(fos,"utf-8"));//  
  53.             fos.flush();  
  54.             fos.close();  
  55.         } catch (IOException e) {  
  56.             e.printStackTrace();  
  57.         } catch (TemplateException e) {  
  58.             e.printStackTrace();  
  59.         }  
  60.     }  
  61.   
  62. }  

 

运行一下测试类,在D盘可以找到一个Student.java的文件,打开看看对不对

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值