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 上为 Alt+/ 。则出现如下的结果:
 
是不是很简单?
大家如果觉得 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;
  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值