60门户日志:几个自定义Eclipse模板的示例

来源:百度文库 编辑:中财网 时间:2024/05/12 05:19:07
   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;