首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Eclipse JET 實戰:從模板引擎到項目生成的完整代碼生成體系

     編輯:Java 相關知識

前言:代碼生成不止於「拼字符串」

Eclipse JET (Java Emitter Templates) 是 EMF 核心組件,語法類 JSP 但編譯為 Java 類,支援 Skeleton 復用、JMerger 代碼合併,結合 IJavaProject/IProject API 可實現「從模板到可編譯項目」的全自動化流水線。

JET 核心機制

模板 → 執行類 → 文本

JET 文本生成流程圖

  • org.eclipse.emf.codegen.jet.JETEmitter 核心類
  • generate() 完成:模板編譯 → 實例化執行類 → 調用 generate(argument) 輸出字符串
  • 模板文件建議命名 *.javajet、*.xmljet 區分輸出類型

隱含變量 argument

任意對象傳入模板,常用 List、Map 承載數據上下文。

三大進階特性實戰

Demo 1:基礎文本生成

<%@jet package="demo.translated" imports="java.util.List" class="Demo1"%>
Hello, <%=((List)argument).get(0)%>!
Time: <%=new java.util.Date()%>.

調用:

JETEmitter emitter = new JETEmitter(bundleEntry + "templates/demo1.jet");
String result = emitter.generate(new NullProgressMonitor(), new Object[]{ argumentList });

Demo 2:Skeleton 骨架注入公共邏輯

demo.skeleton

import java.util.Date;
public class CLASS {
    public String s = "Mission Completed!";
    private Date getCurrentDate() { return new Date(); }
    public String generate(Object argument) { return ""; }
}

demo2.jet

<%@jet package="demo.translated" class="Demo2" skeleton="demo.skeleton"%>
Hello, <%=((List)argument).get(0)%>!
Time: <%=getCurrentDate()%>.
<%=s%>

編譯後 Demo2 自動擁有 s、getCurrentDate(),CLASS 佔位符被替換為實際類名。注意:骨架最後一個方法必須是 generate(Object)。

Demo 3:JMerger 保護手工代碼

合併規則採用 EMF 內建 emf-merge.xml:

  • @generated NOT → 整方法保留
  • <!-- begin-user-doc --> ... <!-- end-user-doc --> → 區塊保留

流程:

JMerger merger = new JMerger();
merger.setControlModel(new JControlModel(mergeRuleUri));
merger.setSourceCompilationUnit(merger.createCompilationUnitForContents(generatedCode));
merger.setTargetCompilationUnit(merger.createCompilationUnitForInputStream(new FileInputStream(existingFile)));
merger.merge();
return merger.getTargetCompilationUnit().getContents().getBytes();

實現「重複生成不覆蓋手工修改」的工程化需求。

JET 技術評價

優勢劣勢
語法類 JSP,學習曲線平緩無專用模板編輯器(無語法高亮、補全)
編譯為 Java 類,執行效能高強依賴 Eclipse 插件機制,獨立運行麻煩
Skeleton 復用、JMerger 合併解決工程化痛點運行前難預覽生成類結構
輸出任意文本格式

JET vs JET2 (M2T)

  • org.eclipse.emf.codegen (JET/EMF.Codegen):EMF 核心,類前綴 JET*,本文主角
  • org.eclipse.jet (JET2/JET):M2T 項目,類前綴 JET2*,功能重疊但定位不同
  • Eclipse 官方已釐清命名,開發者以類前綴區分

Eclipse 項目生成 API 實戰

創建 JavaProject 完整步驟

// 1. IProject 創建與打開
IProject project = workspace.getRoot().getProject("demo");
project.create(null);
project.open(null);
IProjectDescription desc = workspace.newProjectDescription("demo");
desc.setNatureIds(new String[]{ JavaCore.NATURE_ID });
project.setDescription(desc, null);

// 2. 轉為 IJavaProject,調整 Classpath
IJavaProject javaProject = JavaCore.create(project);
List cp = new ArrayList<>(Arrays.asList(javaProject.getRawClasspath()));
// 移除默認錯誤 source root
cp.removeIf(e -> e.getEntryKind()==IClasspathEntry.CPE_SOURCE && e.getPath().toString().equals("/demo"));

// 3. 添加正確 source root、JRE 容器、輸出目錄
cp.add(JavaCore.newSourceEntry(new Path("/demo/src")));
cp.add(JavaCore.newContainerEntry(new Path("org.eclipse.jdt.launching.JRE_CONTAINER")));
javaProject.setRawClasspath(cp.toArray(new IClasspathEntry[0]), null);
javaProject.setOutputLocation(new Path("/demo/bin"), null);

// 4. 創建物理目錄
project.getFolder("src").create(true, true, null);
project.getFolder("bin").create(true, true, null);
javaProject.open(null);

生成的 JavaProject 結構

項目引用與 Plugin Project

  • 多項目依賴:IProjectDescription.setReferencedProjects()
  • Plugin Project 生成:參考 org.eclipse.pde.ui.NewProjectCreationOperation

開發環境集成三板斧

1. 配置管理工具集成


// 檢測 ClearCase
Object obj = resource.getSessionProperty(TeamPlugin.PROVIDER_PROP_KEY);
RepositoryProvider provider = (RepositoryProvider) obj;
if (provider.getID().contains("clearcase")) {
    FileModificationValidator validator = provider.getFileModificationValidator2();
    IStatus status = validator.validateEdit(new IFile[]{ file }, null);
    if (status.isOK()) { /* 已自動 checkout */ }
}

統一 IResource 接口屏蔽 CVS/SVN/ClearCase 差異。

2. 自動編譯觸發

  • 實現 org.eclipse.core.resources.builders 擴展點
  • 繼承 IncrementalProjectBuilder,覆寫 build(kind, args, monitor)
  • 資源變更自動觸發增量編譯、代碼生成後處理

3. Eclipse Error Log / Console 輸出


Bundle bundle = InternalPlatform.getDefault().getBundle(pluginId);
ILog log = Platform.getLog(bundle);
log.log(new Status(Status.ERROR, pluginId + "-" + location, message, throwable));

避免 Log4j 等第三方日志,融入 IDE 原生診斷視圖。

總結

Eclipse 代碼生成體系三層次:

  1. 模板引擎層:JET(語法、Skeleton、JMerger)
  2. 項目構建層:JDT/Core Resources API(創建項目、Classpath、目錄、依賴)
  3. 環境集成層:SCM 自動 Checkout、增量 Builder、原生日志/進度條

掌握這三層,即可構建企業級代碼生成工廠,將 Eclipse 從「編輯器」升級為「生產力平台」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved