zl程序教程

您现在的位置是:首页 >  后端

当前栏目

freemarker入门 – 关于java代码生成器详解编程语言

JAVA入门编程语言 详解 &# 关于 8211 代码生成
2023-06-13 09:20:40 时间

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

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

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