Eclipse快捷鍵 Template用法探討

 
Eclipse Template用法探討
在編碼的過程中,對代碼重用的追求應該是我們的一個永恆的追求。我們先從相同或相似的代碼裏提出公用方法,來方便我們的重用;而後,隨着面向對象技術的提出,我們又提出父類或基類,在類的基礎上對代碼進行重用;後來,我們又有了模式這種層次的代碼重用,雖然模式不僅僅是爲了代碼重用,但這也是一個目的;最後,我們又創建了各種框架或架構,來在更高層次的重用代碼;展望未來,我們會在元數據、域領域的範圍內進行代碼的重用。
所有這一切,仍然還不能滿足我們對代碼重用的要求,我們還是會遇到各種各樣的代碼重用上的煩惱。以下我來簡單舉出幾個我們在編碼過程中遇到的實際問題:
System.out.println(……);
這個方法是我們在Java編程的過程中經常會用到的,用得太頻繁了,本來不是很長的方法調用,在我們使用頻率過高後,就會覺得非常的麻煩。爲什麼呢?我們每次使用這個方法,所不同的只是println方法裏面的參數,但每次不得不從Systemprintln一個一個字母的敲。
與之相同的情況還有:public final static String SEQUENCE_T_PRODUCT_HIST = "T_PRODUCT_HIST";這是一個爲常量賦值的語句,在我們的項目中,使用量也相當的大。
可能有人會說上面的語句比較簡單,不能重用也是可以忍受的,而挖空心思去重用它們,反倒好像走了極端。如果有人這麼想,那麼請看看下面的例子:
try
{
……
}
catch(SQLException Ex)
{
log.error(this.getClass(), "addUserRole", Ex, Ex.getMessage());
throw new PersistenceException(Ex);
}
Catch(Exception e)
{
……
}
比起上面的輸出語句,這種對違例的撲捉更讓人頭疼,重複的代碼更多,但又不能通過面向對象技術進行重用。
還有這樣的例子,由於需要在程序中記錄日誌的原因,需要在每一個類的開頭寫下這樣的語句:
public class ICRMValidationFormTag ……
{
private final static Logger.Module MOD = new Logger.Module(ModuleId.MOD_TAG);
private final static Logger LOG = Logger.getLogger(ICRMValidationFormTag.class, MOD);
private final static PerformanceLogger PLOG = PerformanceLogger.getLogger(ICRMValidationFormTag.class);
……
}
等等。
這樣的例子很多,我們在代碼中可以信手拈來。很多的情況,我們將會在後面的示例中看到。
從上面的例子可以看出,有這樣一些的代碼,有重用的需求,但我們卻很難在語言的基礎上、或面向對象技術、或模式、框架的基礎上進行代碼的重用。可能的原因主要有以下幾個方面:第一是語言規範方面的原因,如print方法的調用和定義靜態常量;第二是由於語言上的一些過程語句,如try…catch語句和case語句;第三可能是具體項目的一些性能或業務等方面的一些考慮。
對於這樣的一些代碼的重用方面的要求,Eclipse的模板給我們帶來了一個很好的解決方案。本文和後續的一些文字將探討這方面的問題,希望引起大家對使用這一工具的興趣。在我看來,實際的項目中,關於Eclipse模板的使用應該是大有用武之地,而且也相當的靈活,能解決很多的實際問題。本文將探討Eclipse模板的使用和自定義模板的一些初步知識;而後續的文字會接着探討一些自定義模板的深入使用。
一、Eclipse模板的使用
Eclipse模板的使用非常的簡單:在需要使用Eclipse模板的地方輸入模板的名稱,如println方法的模板名稱爲:sysout。如下:
然後點擊啓動模板的快捷鍵,如我的Eclipse上爲ctrl+space  。則出現如下的結果:
是不是很簡單?
大家如果覺得sysout模板並沒有給我們省多少功夫,那麼可以嘗試看看main函數,這也是我們經常要使用的一個方法。整個方法如下:
public static void main(String[] args)
{
}
對於這個函數,一個字母一個字母的輸入,大家是不是覺得相當的乏味。Eclipse也爲這個函數準備了一個模板,模板名稱爲main。現在請我們在適當的位置輸入main,然後點擊Alt /Eclipse會下拉一些選擇,我們選擇“main-main method”這個選擇,大家就會看到我們想要的代碼就會出現在相應的位置上。
二、更改快捷鍵
上面我將Eclipse模板的使用簡單的描述了一遍,可能有人在點擊Alt /的時候,並沒有得到想要的結果。不用着急,這是您的Eclipse對模板快捷鍵的設置不同的原因,而我們可以修改模板快捷鍵。
下面我們來看看如何更改模板快捷鍵:
1. 點擊Window/Perferences,如下
2. Perferences窗口裏選擇Workbench,如下
3. 選擇Workbench下的Keys,如下
4. Command欄裏的Category選項選擇“Edit”,Name選項選擇“content assist”,如下
5. Assignments欄裏選擇Ctrl Space那一行(因爲Ctrl SpaceWindows系統佔用,所以我們無法使用模板的這個快捷鍵),在Key Sequence欄裏將Ctrl Space刪掉,輸入Alt L,如下
6. 點擊“Add”按鈕,則在Assignments欄裏增加一行,如下
7. 最後點擊“Apply”按鈕和“OK”按鈕,完成更改模板快捷鍵的整個過程。
完成了上面的過程,我們就可以使用Alt L作爲Eclipse模板的啓動快捷鍵了。
三、如何自定義Eclipse模板
一旦我們學會了使用Eclipse模板,我們很快就會發現Eclipse自帶的模板遠遠不夠我們使用,這時候,我們就需要自定義模板,來適應我們具體項目的實際需求。
那麼,如何自定義Eclipse模板呢?
1. 點擊Window/Perferences,如下
2. Perferences窗口裏選擇Java/Edit/Template,如下:
3. 然後點擊“New”按鈕,出現“New Template”窗口,如下
4. 在“New Template”窗口的Name欄裏輸入你自定義模板的名稱,如“test”;在Content欄裏選擇javajava表示這個模板的內容是java代碼,如果選擇javadoc的話,表示這個模板的內容是註釋);在Description欄裏輸入你的自定義模板的描述,如“just for a test!ha”;最後是模板的java代碼,如“System.out.println(“just for a test!ha”);”。如下
5. 最後不要忘了點擊“OK”按鈕,關閉兩個窗口,我們的自定義模板就完成了。
現在,我們可以測試我們的test模板了,趕快試試吧!
四、幾個自定義Eclipse模板的示例
最後來談談怎麼創建模板,試着舉幾個簡單的例子來作說明。
1. 簡單的Eclipse模板的創建
直接將需要作爲模板的語句填寫在模板的Pattern欄裏,如前面的public final static String SEQUENCE_T_PRODUCT_HIST = "T_PRODUCT_HIST";這樣的常量的定義。我們可以定義一個strConstant的模板,將該模板的Pattern寫爲:“public final static String ${cursor} ;”。其中${cursor}的意思是光標所在的位置。
這樣,你如果在程序的適當位置輸入:strConstant,然後點擊Atl /,那麼你將得到如下的結果:
public final static String (光標所在位置) ;
在實際的項目中,我們會遇到這樣的情況:
if (LOG.isDebugEnabled()) {
LOG.debug(METHOD_NAME, "The user : " user.getName);
}
我們爲了性能的考慮,經常希望在日誌被關閉以後,不再執行LOG.debug方法裏面的任何操作,如"The user : " user.getName這樣的語句。所以我們在LOG.debug方法外面加上LOG.isDebugEnabled()這樣的判斷語句。加上了判斷語句以後,代碼的性能得到了提高,但每一個日誌都加上:
if (LOG.isDebugEnabled()) {
}
卻帶來了代碼重用上的困難。如今使用Eclipse模板正好解決了這個問題。
我們來創建一個enabledLOG的模板,它的Pattern爲:
if (LOG.isDebugEnabled()) {
LOG.debug(METHOD_NAME, "${cursor}");
}
還有一個例子,我們在寫自定義標籤的時候,經常需要編碼的是doEndTag方法,在這個方法裏面,我們要先寫日誌:
final String METHOD_NAME = "doEndTag";
PLOG.info(METHOD_NAME, PerformanceLogger.Event.METHOD_ENTRY);
然後將我們的代碼用try…catch包括起來,如下:
try {
……
} catch (Exception e) {
LOG.error(METHOD_NAME, "……", e);
}
省略號都是我們要寫的代碼。
最後,我們又需要紀錄日誌,然後返回,如下:
PLOG.info(METHOD_NAME, PerformanceLogger.Event.METHOD_EXIT);
return SKIP_BODY;
每一個自定義標籤的格式都是如此,因此,我們可以創建一個doEndTag的模板,它的Pattern爲:
public int doEndTag() throws JspException {
final String METHOD_NAME = "doEndTag";
PLOG.info(METHOD_NAME, PerformanceLogger.Event.METHOD_ENTRY);
try {
${cursor}
} catch (Exception e) {
LOG.error(METHOD_NAME, "", e);
}
PLOG.info(METHOD_NAME, PerformanceLogger.Event.METHOD_EXIT);
return SKIP_BODY;
}
在實際的編碼過程中,我們會遇到很多這樣的例子,使用Eclipse模板,將會把我們從煩躁而易於出錯的拷貝粘貼中解放出來。
2. 帶參數的Eclipse模板
Eclipse除了能讓我們創建簡單的、靜態的Eclipse模板以外,還可以讓我們創建動態的模板,這就是帶參數的模板。請看下面的例子:
private static final String EMPLOYEE_SQL = "SELECT * FROM EMPLOYEE";
protected String getEMPLOYEE_SQL () {
return EMPLOYEE_SQL;
}
private static final String DEPART_SQL = "SELECT * FROM DEPARTMENT";
protected String getDEPART_SQL () {
return DEPART_SQL;
}
這是我在實際項目中遇到過的代碼,這兩個相似的代碼,除了常量的值不同以外,還有常量名不同,get方法不同,但get方法都是“get 常量名”的組合。對於這樣的模板,我們就需要引入帶參數的Eclipse模板。具體方法如下:
我們創建一個名爲sqlConstant的模板,它的Pattern如下:
private static final String ${name} = "";
protected String get${name}() {
return ${name};
}
其中的${name}就是我們的模板參數,當我們在程序的適當位置輸入sqlConstant,然後點擊Alt /的時候,出現如下的效果:
這種參數的好處是,我們有三個地方爲name,當我們在一個地方修改nameEMPLOYEE_SQL的時候,其他的兩個地方的name同時改爲EMPLOYEE_SQL
我們看,這樣的帶參數的模板是不是很好用。
我們再來看一個例子:
假設我們有這樣的代碼,
protected static IEmployeeBSV getEmployeeBSV()
{
IBusinessServiceManager bsvmgr = GenericContainer.getInstance().getBusinessServiceManager();
return (IEmployeeBSV) bsvmgr.getBusinessService(IEmployeeBSV.class);
}
protected static IDepartmentBSV getDepartmentBSV()
{
IBusinessServiceManager bsvmgr = GenericContainer.getInstance().getBusinessServiceManager();
return (IDepartmentBSV) bsvmgr.getBusinessService(IDepartment.class);
}
我們就可以創建一個名爲bsv的模板,其Pattern如下:
protected static I${enclosing_method} get${enclosing_method}()
{
IBusinessServiceManager bsvmgr = GenericContainer.getInstance().getBusinessServiceManager();
return (I${enclosing_method}) bsvmgr.getBusinessService(I${enclosing_method}.class);
}
從上面的例子可以看出,給Eclipse模板帶上參數以後,對Eclipse模板的使用就更加的靈活了。這樣,我們就可以更加靈活的創建Eclipse模板,更加靈活的使用Eclipse模板了。
3. Eclipse模板的幾個特殊參數
我們可以引用${enclosing_type}參數來代表使用模板的代碼所在的類的類名。假如我們有如下的代碼:
public class ICRMValidationFormTag
{
private final static Logger.Module MOD = new Logger.Module(ModuleId.MOD_TAG);
private final static Logger LOG = Logger.getLogger(ICRMValidationFormTag.class, MOD);
private final static PerformanceLogger PLOG = PerformanceLogger.getLogger(ICRMValidationFormTag.class);
……
}
public class Employee
{
private final static Logger.Module MOD = new Logger.Module(ModuleId.MOD_TAG);
private final static Logger LOG = Logger.getLogger(Employee.class, MOD);
private final static PerformanceLogger PLOG = PerformanceLogger.getLogger(Employee.class);
……
}
我們可以將每個類的前面三行作爲一個模板,名爲myLog模板,Pattern爲:
private final static Logger.Module MOD = new Logger.Module(ModuleId.MOD_TAG);
private final static Logger LOG = Logger.getLogger(${enclosing_type}.class, MOD);
private final static PerformanceLogger PLOG = PerformanceLogger.getLogger
(${enclosing_type}.class);
這樣,如果我們在ICRMValidationFormTag類裏引用myLog模板,如下:
public class ICRMValidationFormTag
{
myLog
}
則模板中凡是${enclosing_type}的地方,都將被ICRMValidationFormTag代替。
如果我們在Employee類中引用該模板,如下:
public class Employee
{
myLog
}
則模板中凡是${enclosing_type}的地方,都將被Employee代替。
同理,我們可以使用${enclosing_method}參數來代替使用模板的代碼所在方法的方法名,如,如果我們想用模板來代替每一個方法裏形如final String METHOD_NAME = "getEmployee";的語句,我們可以使用這樣的模板:
模板名爲methodNamePattern爲:
final String METHOD_NAME = "${enclosing_method}";
這樣,如果你在getEmployee方法裏使用該模板,那麼結果爲:
final String METHOD_NAME = "getEmployee";
如果你在saveEmployee方法裏使用該模板,那麼結果爲:
final String METHOD_NAME = "saveEmployee";
其他的幾個常用的特殊參數有:enclosing_method_arguments—返回該參數所在方法的參數類型;encloging_package—返回該參數所在類的包名;enclosing_project—返回該參數所在的項目名;enclosing_type—返回該參數所在類的類名等等。
最後,我們以一個完整一點的例子作爲本文的結束語。
Spring的持久層,大家可能都寫過這樣的代碼:
1. Get方法
public ObjOwnedRolePrivilegeModel getRolePrivilegeById(int id) throws Exception
{
final ObjOwnedRolePrivilegeModel oorp = new ObjOwnedRolePrivilegeModel();
try
{
JdbcTemplate template = new JdbcTemplate(dataSource);
String sql = "select ID,ROLE_ID,OBJ_PRIV_ID,DESCRIPTION from t_obj_priv_role where ID=" id;
log.info(this.getClass(), "getRolePrivilegeById", "SQL: " sql);
template.query(sql, new RowCallbackHandler()
{
public void processRow(ResultSet rs) throws SQLException
{
//ObjOwnedRolePrivilege oorp = new ObjOwnedRolePrivilege(rs.getInt(1),rs.getInt(2),rs.getInt(3),rs.getString(4));
oorp.setId(rs.getInt(1));
oorp.setRoleId(rs.getInt(2));
oorp.setObjPrivId(rs.getInt(3));
oorp.setDescription(rs.getString(4));
}
});
}
catch(Exception Ex)
{
log
.error(this.getClass(), "getRolePrivilegeByid", Ex,
Ex.getMessage());
throw new PersistenceException(Ex);
}
return oorp;
}
2. Save方法
public void addPrivilege(final ObjOwnedPrivilegeModel oop) throws Exception
{
StringBuffer sbSql = new StringBuffer();
try
{
JdbcTemplate template = new JdbcTemplate(dataSource);
sbSql
.append("insert into t_obj_privilege(ID,OBJ_ID,OBJ_TYPEID,PRIV_NAME,PRIV_VALUE,DESCRIPTION)");
sbSql.append(" values(?,?,?,?,?,?)");
log.info(this.getClass(), "addPrivilege", "SQL: "
sbSql.toString());
template.update(sbSql.toString(), new PreparedStatementSetter()
{
public void setValues(PreparedStatement ps) throws SQLException
{
ps.setInt(1, oop.getId());
ps.setInt(2, oop.getObjId());
ps.setInt(3, oop.getObjType());
ps.setString(4, oop.getName());
ps.setInt(5, oop.getValue());
ps.setString(6, oop.getDescription());
}
});
}
catch(Exception Ex)
{
//System.out.println(Ex.getMessage());
log.error(this.getClass(), "addPrivilege", Ex, Ex.getMessage());
throw new PersistenceException(Ex);
}
}
3. Delete方法
public void removeUserRole(int[] id) throws Exception
{
String ids = "-1";
for(int i = 0; i < id.length; i )
{
ids = ids "," id[i];
}
String sql = "delete from t_user_role where id in (" ids ")";
log.info(this.getClass(), "removeUserRole", "SQL: " sql);
try
{
JdbcTemplate template = new JdbcTemplate(dataSource);
template.execute(sql);
}
catch(Exception Ex)
{
log.error(this.getClass(), "removeUserRole", Ex, Ex.getMessage());
throw new PersistenceException(Ex);
}
}
這些是典型的對數據庫的操作,包括查詢、新增、修改和刪除。每一種操作都是相似的,有很多的公用代碼,但由於代碼裏既有try…catch語句,又有匿名內部類,所以不好在面嚮對象的技術上實現重用。但是使用Eclipse模板卻是恰到好處。下面我以第一段代碼作爲例子,其餘的代碼大家可以自行實現。
我們設計一個名爲get的模板,其Pattern爲:
final ${return_type} retn ;
try
{
JdbcTemplate template = new JdbcTemplate(dataSource);
String sql = "";
log.info(this.getClass(), "${enclosing_type}", "SQL: " sql);
template.query(sql, new RowCallbackHandler()
{
public void processRow(ResultSet rs) throws SQLException
{
}
});
}
catch(Exception Ex)
{
log
.error(this.getClass(), "${enclosing_type}", Ex,
Ex.getMessage());
throw new PersistenceException(Ex);
}
return retn;

 
發佈了57 篇原創文章 · 獲贊 4 · 訪問量 34萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章