程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 基於Eclipse平台的代碼生成技術

基於Eclipse平台的代碼生成技術

編輯:關於JAVA

簡介:代碼生成技術是項目建設中常用的減輕工作量的方法,但大部分開發人員對 Eclipse 平台下的代碼生成技術了解不多。本文詳細介紹在 Eclipse 平台下進行代碼生成的技術,包括 Eclipse 自身模板引擎 JET 的使用,進行 Eclipse 項目生成使用的技術,以及在 Eclipse 平台下進行代碼生成的相關輔助技術。本文對軟件架構師和 Eclipse 開發人員都將有所裨益。

Eclipse 的 Java Emitter Templates(JET)一個開源的模板引擎,其功能是在 Eclipse Modeling Framework(EMF)中生成代碼。 JET 的語法與 JSP 語法比較相似,但它們處於不同的應用領域。

JET 的模板文件(template files)後綴一般為(*.jet),但為區分生成文件的類型建議擴展名采用生成文件類型加 jet 後綴的方式,如 ***.javajet、***.textjet 等。

org.eclipse.emf.codegen.jet.JETEmitter 是 JET 的核心類,其 generate() 方法完成實現兩個功能,將模板文件轉換為模板執行類(template implementation class)然後通過模板執行類的輸出生成相應的代碼或文本。

圖 1. 文本生成流程圖

基於 Eclipse 平台的代碼生成技術

查看原圖(大圖)

JET 應用示例

本文隨附三個示例源碼,下文描述的三個示例分別對應示例源碼中的 demo1、demo2 及 demo3,示例中具體方法寫在示例源碼中 SampleNewWizard 的 doFinish 方法中。將示例項目以 Eclipse Application 方式運行後,在新運行的 Eclipse 平台上選擇菜單 FileNewOther,在彈出的 New 對話框中選擇 JET Sample Wizards Demo1 至 Demo3,在彈出對話框中填入相應內容即可顯示示例效果。

圖 2. JET Sample Wizards

基於 Eclipse 平台的代碼生成技術

下文用三個示例來演示 JET 的功能和用法。示例 1 演示使用 JETEmitter 類生成簡單的文件。示例 2 利用 JET 中的骨架 (skeleton) 技術對模板編譯後的模板執行類進行方法定制。示例 3 利用類 JMerger 與合並規則達到自動生成代碼與手工代碼合並的效果。

示例 1 簡單的文件生成(demo1)

1 編寫模板,JET 語法與 JSP 語法很相似。下面是一個最簡單的帶有參數的模板文件 demo1.jet 。

清單 1. Demo1.jet

<%@jet package="demo.translated" imports="java.util.List" class="Demo1"%>
  Hello, <%=((List)argument).get(0).toString()%>!
  The current time is <%=new java.util.Date()%>.

模板文件一般放在插件項目的 templates 目錄下,模板中的 argument 是 JET 的隱含變量,它代表用戶的輸入參數 , 一般是數據變量集。

模板的第一行表示生成內容的包路徑為 demo.translated,模板執行類是 Demo1.java,該類 import java.util.List 。

第二行和第三行是 JET 需要生成的文件內容,使用 <% …… %> 包括代碼,使用 <%= …… %> 打印表達式的值,與 JSP 類似,正確地使用 <% …… %> 標簽就可以添加任何邏輯循環或結構,其內容很好理解,但 JET 生成代碼中,常量字符串最終要以變量的形式存在,於是其生成內容如下:

清單 2. 生成內容

package demo.translated;

  import java.util.List;

  public class Demo1
  {
  protected static String nl;
  public static synchronized Demo1 create(String lineSeparator)
  {
  nl = lineSeparator;
  Demo1 result = new Demo1();
  nl = null;
  return result;
  }

  public final String NL = nl == null ? (System.getProperties().
  getProperty("line.separator")) : nl;
  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;

  public String generate(Object argument)
  {
  final StringBuffer stringBuffer = new StringBuffer();
  stringBuffer.append(TEXT_1);
  stringBuffer.append(((List)argument).get(0).toString());
  stringBuffer.append(TEXT_2);
  stringBuffer.append(new java.util.Date());
  stringBuffer.append(TEXT_3);
  stringBuffer.append(TEXT_4);
  return stringBuffer.toString();
  }
  }

調用 JET 執行模板生成操作的代碼如下:

清單 3. 生成操作代碼

// 模板文件所在插件項目的名稱
  String pluginId = "jet3";
  // 通過插件項目獲得其路徑(basePath)
  String basePath = Platform.getBundle(pluginId).getEntry("/").toString();
  // 模板文件在項目中的路徑及文件名 
  String uri = "templates/echo.jet";
  JETEmitter emitter = new JETEmitter(basePath + uri);
  IProgressMonitor progress = new NullProgressMonitor();
  // 聲明一個 List 作為數據變量集的 container
  List<String> argument = new ArrayList<String>();
  argument.add(fileName);
  argument.add("12334");
  // 對當前模板進行轉換並將需要輸出成實際文件的內容返回以便通過輸出流輸出
  String result = emitter.generate(progress, new Object[] { argument });

示例 2 骨架(skeleton)的使用(demo2)

實際應用中往往會有多個代碼執行類調用公用的方法或變量的情況,這時候我們通常會希望能夠對代碼執行類加入特定的方法,或在代碼的生成過程中定制處理。對這類問題 JET 提供了一種強大的解決方案,骨架(skeleton)。

所謂骨架,簡單來說是修改編譯後的模板文件代碼的樣子。比如我們希望模板文件編譯後的代碼執行類要繼承某個基類、實現某個接口、包含某個常量或方法,就應采用骨架技術。

以下對示例 1 中的模板進行少許修改,以對骨架有一個基本的了解。

在 templates 目錄中,創建 demo.skeleton 文件,編輯其內容為

清單 4. 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 "";
  }
  }

在該文件中,我們 import java.util.Date 類,聲明了 String s 及聲明了方法 getCurrentDate(),這些內容將被合並到對模板文件進行編譯後的代碼中。此外,在文件中的類名“ CLASS ”在代碼執行類中會被模板文件中的代碼執行類類名替換。

將 demo1.jet 文件修改為以下內容,並將文件另存為 demo2.jet 。

清單 5. demo2.jet

<%@jet package="demo.translated" imports="java.util.List" class="Demo2"
  skeleton="demo.skeleton"%>
  Hello, <%=((List)argument).get(0).toString()%>!
  The current time is <%=getCurrentDate()%>.
  <%=s%>

經 JET 編譯後的模板文件代碼內容如下,其中紅色文字為利用骨架合並的效果。

清單 6. 模板文件代碼

package demo.translated;

  import java.util.Date;
  import java.util.List;

  public class Demo2 {
  protected static String nl;
  public static synchronized Demo1 create(String lineSeparator)
  {
  nl = lineSeparator;
  Demo2 result = new Demo2();
  nl = null;
  return result;
  }

  public final String NL = nl == null ?
  (System.getProperties().getProperty("line.separator")) : nl;
  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;
  protected final String TEXT_5 = NL;

  public String s = "Mission Completed!";

  private Date getCurrentDate() {
  return new Date();
  }

  public String generate(Object argument)
  {
  final StringBuffer stringBuffer = new StringBuffer();
  stringBuffer.append(TEXT_1);
  stringBuffer.append(((List)argument).get(0).toString());
  stringBuffer.append(TEXT_2);
  stringBuffer.append(getCurrentDate());
  stringBuffer.append(TEXT_3);
  stringBuffer.append(TEXT_4);
  stringBuffer.append(s);
  stringBuffer.append(TEXT_5);
  return stringBuffer.toString();
  }
  }

在這裡有一點需要注意,JET 對模板文件的編譯只會將其內容編譯到最後一個方法中。因此,骨架最後一個方法必須為 public String generate(Object argument),若將其他方法放在最後,代碼執行類在將模板編譯後與骨架進行合並時會出錯。

示例 3 使用 JMerger 實現代碼合並(demo3)

JET 可以根據事先編輯好的模板文件生成代碼,並且還支持重復生成。實際項目開發中,有時需要將自動生成的代碼進行手工修改,這時如果因某種原則需重新執行代碼生成,會導致手工編寫的代碼丟失。在 JET 中解決此類問題的方法是代碼合並技術,它能將自動生成的內容和手工編寫的內容區分開,在必要時進行合並,JET 中負責合並代碼的類是 JMerger 。本示例討論利用 JMerger 對代碼進行合並的技術。

執行 JET 引擎的程序代碼如下。

清單 7. JET 引擎的程序代碼

// 模板文件所在插件項目的名稱
  String pluginId = "demo3";
  // 模板文件在項目中的路徑及文件名 
  String uri = Platform.getBundle(pluginId).getEntry("/").toString();
  uri += "templates/demo4.jet";

  // 聲明 JETEmitter
  JETEmitter emitter = new JETEmitter(uri);
  IProgressMonitor progress = new NullProgressMonitor();
  // 聲明一個 Map 作為數據變量集的 container
  Map argument = new HashMap();
  argument.put("fileName", fileName);
  argument.put("className", fileName.substring(0, fileName.indexOf(".")));

  // 對當前模板進行轉換並將需要輸出成實際文件的內容返回以便通過輸出流輸出
  String result = emitter.generate(progress, new Object[] { argument });

  // 聲明 JMerger
  JMerger jmerger = new JMerger();
  // 合並規則文件在項目中的路徑及文件名 
  String uri2 = Platform.getBundle(pluginId).getEntry("/").toString();
  uri2 += "/templates/emf-merge.xml";
  // 聲明 JControlModel,作為合並規則 
  JControlModel controlModel = new JControlModel(uri2);
  jmerger.setControlModel(controlModel);
  // 在 JMerger 中設置需要合並的源文件內容 
  jmerger.setSourceCompilationUnit(jmerger
  .createCompilationUnitForContents(result));
  // 在 JMerger 中設置需要合並的目標文件內容 
  jmerger.setTargetCompilationUnit(jmerger
  .createCompilationUnitForInputStream(new FileInputStream(file
  .getLocation().toFile())));
  // 對 JMerger 中目標文件與源文件進行內容合並 
  jmerger.merge();
  return new ByteArrayInputStream(jmerger.getTargetCompilationUnit()
  .getContents().getBytes());

示例的模板內容如下

清單 8. 示例模板內容

<%@jet package="demo.translated" class="Demo3"%>
  package demo3;

  public class <%=((java.util.Map)argument).get("className")%> {
  /**
  * Target javadoc 11
  * Target javadoc 14
  *
  * @generated
  */
  public void printMessage1() {
  // This is my owner code
  System.out.print("Will be replace");
  System.out.println("Source code 1");
  }

  /**
  * Target javadoc 21
  * Target javadoc 24
  *
  * @generated
  */
  public void printMessage2() {
  // This is my owner code
  System.out.print("Will be replace");
  System.out.println("Source code 2");
  }

生成類加入手工代碼後的代碼

清單 9. 加入手工代碼後的代碼

/**
  * Target javadoc 11
  * Target javadoc 12
  * Target javadoc 13
  * Target javadoc 14
  *
  * @generated NOT this target delete or add a word NOT
  */
  public void printMessage1() {
  // This is my owner code
  System.out.print("This is user code");
  }

  /**
  * Target javadoc 21
  * <!-- begin-user-doc -->
  * Target javadoc 22
  * Target javadoc 23
  * <!-- end-user-doc -->
  * Target javadoc 24
  *
  * @generated
  */
  public void printMessage2() {
  // This is my owner code
  System.out.print("This code will be replace");
  System.out.print("Will be replace");
  System.out.println("Source code 2");
  }

再次執行 JET,重新生成 XXXX,新的生成代碼如下,其中 printMessage1 方法 @generated 被設置為 NOT,該方法的 javadoc 注釋及方法體內容都不會被合並,printMessage2 方法 javadoc 注釋中加入標簽 <!-- begin-user-doc --> 和 <!-- end-user-doc --> 在兩個標簽中間的間隔部分的注釋信息將會合並到自動生成的代碼中。

清單 10. 新生成的代碼

/**
  * Target javadoc 11
  * Target javadoc 12
  * Target javadoc 13
  * Target javadoc 14
  *
  * @generated NOT this target delete or add a word NOT
  */
  public void printMessage1() {
  // This is my owner code
  System.out.print("This is user code");
  }

  /**
  * Target javadoc 21
  * <!-- begin-user-doc -->
  * Target javadoc 22
  * Target javadoc 23
  * <!-- end-user-doc -->
  * Target javadoc 24
  *
  * @generated
  */
  public void printMessage2() {
  // This is my owner code
  System.out.print("This code will be replace");
  System.out.print("Will be replace");
  System.out.println("Source code 2");
  }

對 JMerger 合並規則的描述的文章很多,本文不再累述。本例中使用的合並規則是插件 org.eclipse.emf.codegen.ecore 中的 emf-merge.xml 的內容。將其復制到項目的 templates 文件夾中即可達到效果。

JET 技術總結

Eclipse 中的 JET 技術作為 EMF 不可或缺的技術之一,其優勢顯而易見,易學、易用、易上手使開發人員可以在很短的時間就可以開始開發工作,其與 JSP 類似的模板語言也降低了模板開發時的門檻。它可以生成開發人員需要的任何格式的文本類型文件,例如 java、xml、sql 等等。此外 , 骨架技術使模板開發人員在針對特定類型模板文件編寫時,可以進行單獨優化,以減少開發人員的工作量。

JET 支持代碼合並功能,通過使用簡便的代碼和實現定義好的合並規則就可以將自動生成代碼與人工手寫代碼有效的整合。

但所有的事物都是有利有弊的,JET 也不例外。 JET 未提供專用的模板和骨架編輯工具,效率對開發效率造成一定影響。另外 JET 極大程度上依賴 Eclipse 的插件機制,而其模板和骨架在代碼運行前無法很簡便的得知其生成的模板執行類的內容也是件比較麻煩的事情。

JET 與 M2T

剛剛接觸 JET 的開發人員會存在一個困惑,在 Eclipse 關於 EMF 的 org.eclipse.emf.codegen 插件項目中存在一層名稱為 jet 的包路徑,而 Eclipse 在項目 M2T 中也存在有 org.eclipse.jet 插件項目,它們有什麼關系呢?

org.eclipse.jet 一般稱為 JET2,其內部很多關鍵類也都是用 JET2 作為類名的前綴,而 org.eclipse.emf.codegen 一般稱為 JET,是 EMF 項目不可缺少的核心,其中很多關鍵類都是用 JET 作為類名前綴。但是即使是這樣,有不少開發人員仍舊對其名稱發生困惑,因此,Eclipse 在其網站中對這兩者的名稱已經正式發布,org.eclipse.emf.codegen 插件定名為 EMF.Codegen,org.eclipse.jet 插件定名為 JET,本文考慮到大多開發人員的描述習慣以及關鍵詞與類名前綴的統一,文章中討論的 JET 技術是指 Eclipse 的插件 org.eclipse.emf.codegen,也即俗稱的 JET 技術,或 Eclipse 中 EMF 的 EMF.Codegen 技術。

Eclipse 的項目生成技術

在前文的描述中,利用 JET 技術中的類 JETEmitter 能夠生成 JavaProject 。但實際項目開發的需求往往比這要靈活得多,可能需指定編譯器、設置插件引用、設定 jar 包引用等。通過 org.eclipse.jdt.core 中的 IJavaProject 及 org.eclipse.core.resources 中的 Iproject 開發人員可以靈活調整 JavaProject 的屬性。。

下一示例演示 JavaProject 的創建及屬性修改。該示例將創建名稱為 demo 的 JavaProject

圖 3. demo 的 JavaProject 項目在 Package Explorer View 中的展示

首先在當前 IWorkspace 中獲得 IProject 的實例,並通過 create() 方法在文件系統中創建該 Project 。

清單 11. 生成項目

// 生成的項目的名稱
  String _projectName = "demo";
  IWorkspace workspace = ResourcesPlugin.getWorkspace();
  // 從當前 workspace 中獲取 IProject 實例,其名稱為 demo
  IProject project = workspace.getRoot().getProject(_projectName);
  // 創建項目
  project.create(null);
  // 對該項目進行描述,其內容輸出到 .project 文件 
  IProjectDescription description = workspace
  .newProjectDescription(project.getName());
  description.setNatureIds(new String[] { JavaCore.NATURE_ID });
  description.setLocation(null);
  // 在當前 Workspace 環境中打開該項目
  project.open(null);
  // 在項目中設置剛設置的項目描述 
  project.setDescription(description, null);

通過 JavaCore 將當前項目轉換為 JavaProject,並將其原有的 source root 刪除,由於 Project 默認的 source root 為項目的根目錄而非 JavaProject 使用的項目下的 src 路徑,需要對其進行修改,本文由於在後面將會介紹對 source root 的創建,因此在這裡采用刪除的方式,實際創建時可依據需要進行修改。

清單 12. 生成 JAVA 項目

// 在 JavaCore 中將當前 IProject 創建為 IJavaProject
  IJavaProject javaProject = JavaCore.create(project);
  // 獲得生成項目中的 classpath 信息,並將項目中的 source 目錄信息刪除
  // 由於在下面將重新生成項目的 source root,因此為了保證不重復,
  // 在這裡將多余的錯誤 source root 刪除
  List<IClasspathEntry> classpath = new UniqueEList<IClasspathEntry>(
  Arrays.asList(javaProject.getRawClasspath()));
  for (int i = 0, len = classpath.size(); i < len; i++) {
  IClasspathEntry entry = classpath.get(i);
  if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE
  && ("/" + project.getName()).equals(entry.getPath()
  .toString())) {
  classpath.remove(i);
  }
  }

創建 JavaProject 的 classpath 信息,每個 IClasspathEntry 對應 classpath 中的一條細目,並將其加入到 classpath 中。

清單 13. 生成 Classpath

// 添加新的 classpath 細目,包括 source 目錄,bin 目錄運行時的 container
  // 以及其他需要添加的如變量(variable),jar 包(library)等等
  // 生成效果為 <classpathentry kind="src" path="src"/>
  IClasspathEntry classpathEntry = JavaCore.newSourceEntry(new Path("/"
  + project.getName() + "/src"));
  // 生成效果為 
  // <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
  IClasspathEntry jreClasspathEntry = JavaCore
  .newContainerEntry(new Path(
  "org.eclipse.jdt.launching.JRE_CONTAINER"));
  classpath.add(classpathEntry);
  classpath.add(jreClasspathEntry);
  // 在此處可以創建其他需要的 classpath 信息

通過 IFolder 在文件系統中創建項目需要的 src 文件夾和 bin 文件夾。

清單 14. 生成 SRC 文件夾

// 在 JavaProject 的文件系統中創建文件夾 src
  IFolder sourceFolder = project.getFolder(new Path("src"));
  if (!sourceFolder.exists()) {
  sourceFolder.create(false, true, null);
  }
  // 在 JavaProject 的文件系統中創建文件夾 bin 
  IFolder runtimeFolder = project.getFolder(new Path("bin"));
  if (!runtimeFolder.exists()) {
  runtimeFolder.create(false, true, null);
  }

將設置好的 classpath 賦值給 JavaProject,其結果反映到 JavaProject 的 .classpath 文件中,並對 JavaProject 的 outputLocation 賦值,最後在當前 workspace 中打開該 JavaProject 。

清單 15. 設置 Classpath 和 bin 目錄

// 將設置好的 classpath 賦值給 JavaProject
  javaProject.setRawClasspath(classpath 
   .toArray(new IClasspathEntry[classpath.size()]), null);
  // 設置 JavaProject 的 bin 目錄
  javaProject.setOutputLocation(
   new Path("/" + project.getName() + "/bin"), null);
  // 在當前 Workspace 環境中打開該項目
  javaProject.open(null);

以上內容可以創建基本的 JavaProject,如果多個 Project 之間存在引用關以,用 Iworkspace 創建引用關系

清單 16. 設置項目引用

// 獲得當前 Eclipse 運行環境中的 IWorkspace 實例
  IWorkspace workspace = ResourcesPlugin.getWorkspace();
  // 從當前 workspace 中獲取 IProject 實例 
  IProject project = workspace.getRoot().getProject(_projectName);

創建 PluginProject 需要調用到 Eclipse 的 PDE 平台,其生成所需要代碼在 org.eclipse.pde.core 中,具體生成方式可參看 org.eclipse.pde.ui 中 NewProjectCreationOperation 的 execute 方法。

開發環境集成技術

模板引擎和項目生成是代碼生成工作中最重要的工作,完成這些內容,就已經完成了大部分工作。但實際項目開發沒有這種簡單,開發人員還會受到幾個開發環境有關的問題的困擾,這些問題不但會使整個自動代碼生成過程變得無趣,還在一定程序上影響開發人員的生成效率。本文只討論在 Eclipse 平台下的解決。如果您正在使用的集成開發環境不支持擴展或沒有開發的 API,可以考慮將項目轉移到 Eclipse 環境。

與配置管理工具集成

企業級大型項目,往往需要可靠穩定的配置管理工具,常用的配置管理工具有 CVS、SVN、ClearCase、SourceSafe 等。 IBM 的 ClearCase 因其出色的能力,往往成為開發大型項目的首選,但 ClearCase 的工作原理與 SVN 有明顯不同,它對文件的操作有嚴格的要求,需將加入版本控制的所有的文件設為只讀,只有檢出操作後才會改為可寫,而且要檢出代碼也能在 ClearCase 中留下完成的版本控制記錄,有利於項目的管理。這樣就要求生成代碼工具支持 ClearCase 的特性,需要時能夠自動檢出目標文件。幸運的是 Eclipse 的提供了統一的機制操作文件,並且提供編程接口。

解決上述問題,有兩個關鍵點:

1. 需要找到配置管理工具的類型,在 Eclipse 中所有在 Workspace 中的資源類都會實現 IResource 接口,在其中有 getSessionProperty(QualifiedName key) 方法,該方法可以獲得配置工具的類型代碼如下

清單 17. 獲得配置管理工具對象

// 獲得配置工具對象 
  Object obj = resource.getSessionProperty(TeamPlugin.PROVIDER_PROP_KEY);
  RepositoryProvider provider = (RepositoryProvider) obj;

當 provider.getID().contains("clearcase") 為真的時候就能確定該資源使用 ClearCase 來管理。

2. 從 ClearCase ChecktOut 資源

FileModificationValidator 可以幫助我們完成 CheckOut 資源,具體代碼如下

清單 18. 從配置管理工具 CheckOut 文件

// 從 RepositoryProvider 獲得 FileModificationValidator
  FileModificationValidator validator = provider.getFileModificationValidator2();
  // 完成 CheckOut 操作 
  IStatus status = validator.validateEdit(new IFile[] { (IFile) resource }, null);

當 status.isOK() 為 true 時文件證明文件 CheckOut 成功項目應根據需要顯示提示窗口或自動完成檢出操作。

使用 Eclipse 的自動編譯功能

生成代碼之後開發人員可能還需做一些手工操作,如識別文件變化、程序編譯、配置類型文件處理等。為提升自動化處理程序,我們需要系統能自動發現文件變化,並自動進行處理。

org.eclipse.core.resources.builders 擴展點提供了以上類型的機制。實現 Builder 擴展點,在 Extension 頁中增加 org.eclipse.core.resources.builders 擴展點,並指定其實現類。該實現類必須繼承 org.eclipse.core.resources.IncrementalProjectBuilder,過載下列方法

protected abstract IProject[] build(int kind, Map args, IProgressMonitor monitor)
  throws CoreException;

在項目資源發生變化時 Eclipse 將自動調用上述方法。方法參數請參閱 Eclipse 文檔。

這樣可以在代碼生成之後對文件變化做出自動處理。

使用 Eclipse 的 Error Log 顯示生成狀態

在 Eclipse 平台中進行代碼自動生成時,應盡量使用 Eclipse 提供的控制台機制或問題處理機制,避免使用 Log4j 第三方工具。,一個是將錯誤輸出到 Eclipse 的 Console 中。記錄在文件中有多種方式就不在此詳述。輸出到 Console 中就需要使用 Eclipse 的提供的機制。

要達到這個目的需要調用 Eclipse 的 ILog 接口實現代碼如下

清單 19. 使用 ILog 接口

// 獲得 Bundle
  Bundle bundle = InternalPlatform.getDefault().getBundle(pluginid);
  // 獲得 ILog 
  ILog elogger = Platform.getLog(bundle);
得到 ILog 對象後可以記錄以下幾個級別的錯誤
  //Cancel 級別
  elogger.log(new Status(Status.CANCEL, pluginid + "-" + loc, message,throwable));
  //Error 級別
  elogger.log(new Status(Status.ERROR, pluginid + "-" + loc, message,throwable));
  //Info 級別
  elogger.log(new Status(Status.INFO, pluginid + "-" + loc, message,throwable));

以此方式可在Eclipse平台中顯示生成狀態信息,提高用戶體驗。

結束語

“自動代碼生成技術”已成為項目開發不可或缺的一項技能,它通過自動生成文本的方式,減少開發工作量並防止缺陷產生。一般來說,開發人員僅使用模板引擎生成程序代碼和數據文件,但從事大型項目開發時,這還遠遠不夠。基於 Eclipse 開發環境,我們可以自動創建項目、添加依賴項、生成代碼文件、編譯或處理已生成代碼、並與配置管理工作交互,甚至可以在 Eclipse 平台中顯示執行進度和信息提示。本文融合筆者多年項目開發經驗,涵蓋自動代碼生成工作的各方面技術。希望本文能對使用 Eclipse 平台的技術人員有所啟發,在實踐中深度發掘 Eclipse 平台的潛能,而不只是將之視為簡單的集成開發環境。

原文地址:http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-jet/index.html

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved