二、更改快捷键 上面我将Eclipse模板的使用简单的描述了一遍,可能有人在点击Alt+/的时候,并没有得到想要的结果。不用着急,这是您的Eclipse对模板快捷键的设置不同的原因,而我们可以修改模板快捷键。 下面我们来看看如何更改模板快捷键: 1. 点击Window/Perferences,如下
5. 在Assignments栏里选择Ctrl+Space那一行(因为Ctrl+Space被Windows系统占用,所以我们无法使用模板的这个快捷键),在Key Sequence栏里将Ctrl+Space删掉,输入Alt+L,如下
2. 在Perferences窗口里选择Java/Edit/Template,如下:
还有一个例子,我们在写自定义标签的时候,经常需要编码的是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;