转:Eclipse快捷键 Template用法探讨

Eclipse Template用法探讨
在编码的过程中,对代码重用的追求应该是我们的一个永恒的追求。我们先从相同或相似的代码里提出公用方法,来方便我们的重用;而后,随着面向对象技术的提出,我们又提出父类或基类,在类的基础上对代码进行重用;后来,我们又有了模式这种层次的代码重用,虽然模式不仅仅是为了代码重用,但这也是一个目的;最后,我们又创建了各种框架或架构,来在更高层次的重用代码;展望未来,我们会在元数据、域领域的范围内进行代码的重用。
所有这一切,仍然还不能满足我们对代码重用的要求,我们还是会遇到各种各样的代码重用上的烦恼。以下我来简单举出几个我们在编码过程中遇到的实际问题:
System.out.println(……);
这个方法是我们在 Java 编程的过程中经常会用到的,用得太频繁了,本来不是很长的方法调用,在我们使用频率过高后,就会觉得非常的麻烦。为什么呢?我们每次使用这个方法,所不同的只是 println 方法里面的参数,但每次不得不从 System println 一个一个字母的敲。
与之相同的情况还有: 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 Space Windows 系统占用,所以我们无法使用模板的这个快捷键),在 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 栏里选择 java java 表示这个模板的内容是 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 ,当我们在一个地方修改 name EMPLOYEE_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"; 的语句,我们可以使用这样的模板:
模板名为 methodName Pattern 为:
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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值