关于java代码生成器

关于java代码生成器讲代码生成器之前先要说说模板,什么叫模板呢,举个例子吧,汇款单都见过吧,你不填写的那些内容都属于模板范畴说到这应该明白了吧,模板就是把共性提取出来反复使用,节约时间、工作量。。。。。那跟代码生成器有什么关系呢,思考一下在编程语言中所有的语言是不是都用共性或者说规范,这些都是固定不变的,在具体点,软件行业也是分主营业务的,比如OA、CRM、ERP、SCM等等,那么各个业务方向的软件

大家好,又见面了,我是你们的朋友全栈君。

讲代码生成器之前先要说说模板,什么叫模板呢,举个例子吧,汇款单都见过吧,你不填写的那些内容都属于模板范畴

说到这应该明白了吧,模板就是把共性提取出来反复使用,节约时间、工作量。。。。。

那跟代码生成器有什么关系呢,思考一下在编程语言中所有的语言是不是都用共性或者说规范,这些都是固定不变的,在具体点,软件行业也是分主营业务 的,比如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的文件,打开看看对不对

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/133050.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • js单项选择答题_完成窗口切换的方法

    js单项选择答题_完成窗口切换的方法业务背景:系统有一个数据列表,其中的每行数据都可以进行详细信息修改配置。为了提升用户体验,需要在用户触发单条任务记录详细配置界面之后添加进入上一题和下一题的操作。实现构思: 有两种办法:第一种简单点的话就是不去数据库实时查询数据,利用已经在列表中的数据信息进行数据切换展示与修改。 第二种办法稍微麻烦一点,数据切换的时候实时rownum去数据库查询定位当前数据行的index,然后切换…

    2022年4月19日
    48
  • 数组转对象,对象转数组对不对_对象数组初始化

    数组转对象,对象转数组对不对_对象数组初始化<scripttype=”text/javascript”>//数组转对象vara=[1,2,3,4]varobj={…a}//{0:1,1:2,2:3,3:4}varobj2={}a.forEach((item,index)=>{obj2[index]=item})//{0:1,1:2,2:3,3:4}functiontoObj(a.

    2022年9月11日
    1
  • python ddos攻击_DDoS攻击工具

    python ddos攻击_DDoS攻击工具DDoS攻击工具综合性工具综合性工具除了可以进行DDoS攻击外,还可用于其他的用途,例如:端口扫描、安全审计、防火墙等。实际上,大部分综合性工具开发的原始目的并不是用于DDoS,而是“网络检查或测试工具”Hping?Hping是一个编码和解码TCP/IP协议的命令行开发工具,常用于测试网络及主机的安全,同时也可以做安全审计、防火墙测试等工具的标配工具;Hping的命令行就像常用的ping命令,不…

    2022年7月27日
    16
  • pycharm激活码2021年csdn[在线序列号]

    pycharm激活码2021年csdn[在线序列号],https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月20日
    49
  • java的定时器用法

    java的定时器用法

    2021年12月1日
    36
  • android gridview控件使用详解_android tablelayout

    android gridview控件使用详解_android tablelayoutfrom:http://blog.csdn.net/weich_java/article/details/6987198笔者在用GridView时发现GridView的selectstyle会根据系统而不同,因为在客户端中一边具有统一的显示风格,所以尝试了下指定GridView的选中样式。首先看一下代码:menu.xmlandroid:layout_width=”fill_parent”andr…

    2022年9月25日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号