代码自动生成技术学习之一JET

JET(Java Emitter Templates)一种语法和思想都和jsp非常相似的代码生成模板技术。他是EMF代码生成中使用的技术。模板技术的思想都是描述某个东东的大体样子,然后加上一些参数和条件控制语句来生成目标的的东东。JET在.jetXx文件中定义要生成代码的结构,然后编译生成java文件,使用生成java代码来输出目标的代码。(其中Xx代表要生成代码的文件类型,例如像生成java代码则后缀名为.jetjava)这个过程和jsp非常相似,jsp相当于.jetXxx,而jsp编译成的servlet则和.jetXxx模板编译生成的java文件一样。.jet和jsp类似也有隐含变量:argument, stringBuffer,它代表输入参数。
下面看一个例子来说明这个过程:
我们定义能够生成一个像别人问好,而这个人可以参数话来定制:
首先创建一个java工程,然后New > Other... > Java Emitter Templates > Convert Projects to JET Projects,就转化成jet project了,然后生成了template文件夹,在里面来写模板(.jetXx)和骨架(.skeleton)。
<%@ jet package="hello" class="GreetingTemplate" %>
 Hello, <%=argument%>!

当我们保存完整个模板的时候,我们发现在hello包中,自动translate成一个GreetingTemplate类:
package hello;
 
 public class TranslationDemoTemplate
 {
   protected final String NL =           System.getProperties().getProperty("line.separator");
   protected final String TEXT_1 = "Hello, ";
   protected final String TEXT_2 = "!";
 
   public String generate(Object argument)
   {
     StringBuffer stringBuffer = new StringBuffer();
     stringBuffer.append(TEXT_1);
     stringBuffer.append(argument);
     stringBuffer.append(TEXT_2);
     return stringBuffer.toString();
   }
 }

我们发现这个思想和实现方法完全jsp相同,jsp是生成一大堆的out.println
我们在模版中加上一句:
<%@ jet package="hello" class="TranslationDemoTemplate" %>

Hello, <%=argument%>!
<% stringBuffer.append("Hello again!"); %>
结果翻译成jav类的代码在
<b>stringBuffer.append(TEXT_2);</b>
后面多了一个
<b>stringBuffer.append("Hello again!");</b>

然而这个翻译的过程可以被定制,默认的翻译过程使用了骨架:
 public class CLASS
 {
   public String generate(Object argument)
   {
     return "";
   }
 }

我们可以通过这个骨架来定制生成的代码,如:我们希望生成的代码继承接口
public interface IGenerator {
     String generate(Object argument);
}

那么只需要改变一下这个骨架:
在template文件夹中建一个generator.skeleton文件,代码如下:
 
public class CLASS implements IGenerator
 {
/* (non-javadoc)
    * @see IGenerator#generate(Object)
    */
public String generate(Object argument)
   {
     return "";
   }
 }

然后再模板中指定这个skeleton="generator.skeleton"
 <%@ jet package="hello" class="GreetingTemplate" skeleton="generator.skeleton" %>
 Hello, <%=argument%>!
 The current time is <%=new java.util.Date()%>.

然后生成的代码如下:
package hello;
 
 public class GreetingTemplate implements IGenerator
 {
   protected final String NL = System.getProperties().getProperty("line.separator");
   protected final String TEXT_1 = "Hello, ";
   protected final String TEXT_2 = "!" + NL + "The current time is ";
   protected final String TEXT_3 = ".";
   protected final String TEXT_4 = NL;
 

/* (non-javadoc)
    * @see IGenerator#generate(Object)
    */
public String generate(Object argument)
   {
     StringBuffer stringBuffer = new StringBuffer();
     stringBuffer.append(TEXT_1);
     stringBuffer.append(argument);
     stringBuffer.append(TEXT_2);
     stringBuffer.append(new java.util.Date());
     stringBuffer.append(TEXT_3);
     stringBuffer.append(TEXT_4);
     return stringBuffer.toString();
   }
 }

jet可以同时用startTag和endTag来指明模板使用scriptlet, expression, or include directive开始和结束,这个对于生成jsp代码很有用:
 <%@ jet package="tags.demo" class="JspTemplate" startTag="<$" endTag="$>" %>

 <$ String paramName = (String) argument; /* This is an executed scriptlet */ $>
 <$ if (paramName != null) { $>
   <%= request.getParameter("<$=paramName$>") %> <!-- this is generated JSP -->

 <$ } $>

生成的代码为:
<%= request.getParameter("button") %> <!-- this is generated JSP -->

jet可以向jsp一样使用<%@ include file="copyright.inc" %>来导入一段公用的模板。
jet可以使用条件控制scriptlet和内置的标签和jsp一样的<c:if><c:get>等
<% if (Calendar.getInstance().get(Calendar.AM_PM) == Calendar.AM) {%>
 Good Morning
 <% } else { %>
 Good Afternoon
 <% } %>

你可能感兴趣的:(java,html,jsp,servlet)