BSTEK Development Framework2(BDF2) : 10.4.动作

概述

       动作是Rapido当中提供的用于实现将前台数据提交给后台处理或执行一个Ajax调用的功能,从本质上来说,它所完成的就是Dorado7当中的UpdateAction与AjaxAction两种类型Action要做的事情。动作在定义的过程当中,如果选择与某实体关联,那么最终将会生成一个UpdateAction;如果不选择与某实体关联,那么它就是一个AjaxAction。

       动作定义中,除了可以选择具体要绑定的实体外,还允许用户编写BeanShell脚本与绑定若干个预先定义好的实现了IAction接口的实现类,这样就尽可能赋予动作最大的灵活性,在不编写Java代码的情况下完成足够多的后台复杂的业务逻辑,以进一步增加Rapido开发复杂业务页面的能力。

操作

       切换到Rapido工作区,展开动作节点,在需要维护动作的包下双击,就可以打开动作维护页面,效果如下图所示:

       点击添加按钮,在弹出的窗口当中就可以添加一个动作,在动作定义时还可以定义动作使用的参数,这些参数在支持执行期间会从前台页面传输到后台供使用。

扩展

       前面提过,动作定义时可以添加若干个预置的“具体动作”,它们是一些实现了IAction接口的配置在Spring当中的Java类,在Rapido当中默认提供了三个IAction接口实现,分别是:

  1. 根据流程模版的ID,开启一个流程实例。
  2. 保存流程任务审批过程中的审批意见信息。
  3. 根据任务ID完成一个具体的流程任务。

       可以看到,这三个接口实现都与流程相关,有了这三个实现,就可以将Rapido做的页面与流程关联起来,从而实现与流程相关业务页面开发。IAction接口内容如下:

package com.bstek.bdf2.rapido.action;
import java.util.Collection;
import java.util.Map;
import com.bstek.bdf2.rapido.domain.Parameter;
/**
 * 用于定义前后台交互时要执行的具体动作,<br>
 * 动作可以累加,也就是说可以一次性执行多个当前接口的实现类,<br>
 * 用户可以通过实现该接口,在execute方法中添加具体的需要执行的具体逻辑代码,然后将实现类配置到spring当中即可
 * @author jacky.gao@bstek.com
 * @since 2012-7-5
 */
public interface IAction {
	/**
	 * 返回当前动作的名称
	 * @return 返回动作名称
	 */
	String getName();
	/**
	 * 具体要执行的动作代码,这里的参数只有一个Map,<br>
	 * 在这个Map当中包含了当前业务数据的ID(key为businessId)以及所有在动作定义时定义的参数
	 * @param map 外部传入的参数
	 */
	Map<String,Object> execute(Map<String,Object> map);
	
	/**
	 * 执行这个实现时需要哪些参数
	 * @return 返回一个Parameter对象实例集合
	 */
	Collection<Parameter> requiredParameters();
}

       如果您需要编写一个IAction接口实现,那么同样需要将实现类配置到Spring上下文当中。

       在编写BeanShell脚本时,除了可以使用Rapido内置的变量外,用户可以通过实现com.bstek.bdf2.bsh.VariableRegister,该接口源码如下:

package com.bstek.bdf.bsh;
import java.util.Map;
/**
 * 注册BeanShell脚本中要使用的变量信息,实现类需要配置到Spring环境当中,<br>
 * 因此在注册时可使用Spring环境中各种类型的Bean对象
 * @author jacky.gao@bstek.com
 * @since 2012-8-28
 */
public interface VariableRegister {
	/**
	 * 返回注册到BeanShell上下文中的变量集合
	 * @return 返回一个变量集合的Map,Map中key为变量名,Value就是一个VariableInfo对象,用于描述变量信息
	 */
	Map<String,VariableInfo> register();
}

       一旦将实现该接口的Bean配置到Spring当中,我们在动作中编写BeanShell脚本时就可以下图所示的可用脚本变量中看到新加的BeanShell变量信息。

扩展示例

       自定义执行存储过程的BeanShell变量示例:

       1.定义ProcedureTemplate对象

package com.bstek.rapido.demo;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import com.bstek.bdf.rapido.RapidJdbcDaoSupport;
/**
 * 存储过程执行对象
 * @author Lucas
 * 
 */
public class ProcedureTemplate extends RapidJdbcDaoSupport {
	/**
	 * @param procedureSql
	 *            执行存储过程语句
	 * @param param
	 *            向存储过程传递的参数
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public Map<String, Object> call(final String procedureSql,
			final Map<String, Object> param) {
		final Map<String, Object> outParam = new HashMap<String, Object>();
		this.getJdbcTemplate().execute(new CallableStatementCreator() {
			@Override
			public CallableStatement createCallableStatement(Connection con)
					throws SQLException {
				CallableStatement cs = con.prepareCall(procedureSql);
				int i = 1;
				for (String key : param.keySet()) {
					Object obj = param.get(key);
					if (obj instanceof String) {
						int j = i++;
						cs.setString(j, (String) obj);
						cs.registerOutParameter(j, Types.VARCHAR);
					} else if (obj instanceof Integer) {
						int j = i++;
						cs.registerOutParameter(j, Types.INTEGER);
						cs.setInt(j, (Integer) obj);
					} else if (obj instanceof Long) {
						int j = i++;
						cs.registerOutParameter(j, Types.INTEGER);
						cs.setLong(j, (Long) obj);
					}
				}
				return cs;
			}
		}, new CallableStatementCallback() {
			@Override
			public Object doInCallableStatement(CallableStatement cs)
					throws SQLException, DataAccessException {
				cs.execute();
				int i = 1;
				for (String key : param.keySet()) {
					Object obj = param.get(key);
					if (obj instanceof String) {
						outParam.put(key, cs.getString(i++));
					} else if (obj instanceof Integer) {
						outParam.put(key, cs.getInt(i++));
					} else if (obj instanceof Long) {
						outParam.put(key, cs.getLong(i++));
					}
				}
				return null;
			}
		});
		return outParam;
	}
	/**
	 * 执行无参存储过程
	 * 
	 * @param procedureSql
	 *            执行存储过程语句
	 */
	public void execute(final String procedureSql) {
		this.getJdbcTemplate().execute(procedureSql);
	}
}

       2.将ProcedureTemplate对象注册为BeanShell变量

package com.bstek.rapido.demo;
import java.util.HashMap;
import java.util.Map;
import com.bstek.bdf.d7.bsh.VariableExecutor;
import com.bstek.bdf.d7.bsh.VariableInfo;
import com.bstek.bdf.d7.bsh.VariableRegister;
/**
 * 注册ProcedureTemplate对象实例
 * @author Lucas
 * 
 */
public class ProcedureTemplateRegister implements VariableRegister {
	private ProcedureTemplate procedureTemplate;
	public ProcedureTemplate getProcedureTemplate() {
		return procedureTemplate;
	}
	public void setProcedureTemplate(ProcedureTemplate procedureTemplate) {
		this.procedureTemplate = procedureTemplate;
	}
	@Override
	public Map<String, VariableInfo> register() {
		Map<String, VariableInfo> map = new HashMap<String, VariableInfo>();
		VariableInfo procedureTemplateInfo = new VariableInfo();
		procedureTemplateInfo.setName("procedureTemplate");
		procedureTemplateInfo.setDesc("自定义的执行存储过程的ProcedureTemplate对象实例");
		procedureTemplateInfo.setVariableExecutor(new VariableExecutor() {
			public Object execute() {
				return procedureTemplate;
			}
		});
		map.put("procedureTemplate", procedureTemplateInfo);
		return map;
	}
}

       3.配置到Spring配置文件中

<bean id="procedureTemplate" class="com.bstek.rapido.demo.ProcedureTemplate" />
<bean class="com.bstek.rapido.demo.ProcedureTemplateRegister">
		<property name="procedureTemplate" ref="procedureTemplate" />
</bean>

       4.BeanShell脚本中使用procedureTemplate变量

Map resultMap=new HashMap();
Map paramMap=new HashMap();
	paramMap.put("id","123");
	paramMap.put("name","beanShell");
	resultMap = procedureTemplate.call("exec test_insert ?,?",paramMap);
	resultMap.put("id_test",resultMap.get("id"));
return resultMap;