Posted on 2010-01-15 23:29
長城 阅读(731)
评论(0) 编辑 收藏
来到北京,今天的天气似乎是最好的,希望不要再有降温天气了。今日继续我们的审批流程,今天的内容似乎有点多,同学们需要努力学习哦!
我个人认为今天的内容多,是为因今天加入了测试部分。使用JBPM开发OA系统,说简单些就是将自定义表单数据放到JBPM工作流中流转。我们所需要实现的功能就是,使用户可以向系统中部署自定义工作流,用户可以自己添加自定义表单。我们通过编写通用表单实体,让任何自定义表单在工作流中流转即可。
我来总结一下今天的各部分重点内容。
一、表单定义
我们可以使用FCKEDIT这个免费的工具来设计自定义表单,但我们并未使用外部工具。而是自己编写了一个简单的表单设计工具,在下面我会一一介绍。
与其他模块一样,我们需要为表单定义(表单模板管理)编写自己的DispathcAction,根据下面的表单模板管理流程,编写DispatchAction。
在实现DispatchAction有必须先定义struts的ActionForm和表单定义的实体(FormDefinition),因为我们的OA系统可以添加任意自定义的表单,所以我们需要编写一个通用的ActionForm和FormDefinition。实体中具有哪些属性字段,是这里的难点。汤老师,在OA项目的第一就领着大家把事个系统简单分析了一下,之后的每次讲课都从大模块框架开始。因为只有讲了整个相关功能的大模块应用,才能更好的理解这些小模块需要什么,比如下面定义的实体是因为在生成表单实例时、提交申请和工作流流转时使用。我们先来看一下实体的全景图:
(新增加:FormDefinition、FormInstance、ApproveInfo,今日我们只学习FormDefinition)
FormDefinitionActionForm:
public class FormDefinitionActionForm extends ActionForm { private static final long serialVersionUID = 1L; private Long id; private String name; // 自定义表单名称 private String templatePath;// 自定义表单存放路径(html) private String processName;// 自定义表单使用的流程名称 private String[] propertyNameList; // 存放表单字段名称的数组与propertyValueTypeList对应 private Class[] propertyValueTypeList;// 存放表单字段类型的数组与propertyNameList对应 // setters and getters… } |
FormDefinition:
public class FormDefinition { private Long id; private String name; // 自定义表单名称 private String templatePath;// 自定义表单存放路径(html) private String processName;// 自定义表单使用的流程名称 // 存放表单字段名称与字段类型的MAP private Map<String,Class> fieldDefinitionList = new HashMap<String, Class>(); // setters and getters… } |
一如继往还需要一个FormDefinitionService和FormDefinitionService,不需要为它们添加任何额外实现直接继承自DaoBase就可以了,因为jbpm也使用hibernate哦!而我们的DaoBase是一个通用的数据库基本操作。
DispatchAction:
1.表单定义列表
/** * 显示自定义表单列表 */ public ActionForward list(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 查询数据列表并将信息添加到request的formDefinitionList属性中 List<FormDefinition> formDefinitionList = formDefinitionService.findAll(); request.setAttribute("formDefinitionList", formDefinitionList); return mapping.findForward("list"); // list.jsp } |
2.显示添加表单页面
/** * 添加自定义表单页面 */ public ActionForward addUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取自定义表单需要使用的流程信息 List<String> processNameList = processDefinitionService .findAllNameList(); // 将流程信息添加到request中,用于在页面显示 request.setAttribute("processNameList", processNameList); return mapping.findForward("addUI"); // addUI.jsp } |
3.添加表单
/** * 添加自定义表单 */ public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取表单提单过来的信息 FormDefinitionActionForm actionForm = (FormDefinitionActionForm) form; // 将ActionForm中的信息封装到FormDefinition中 FormDefinition formDefinition = new FormDefinition(); BeanUtils.copyProperties(formDefinition, actionForm); // 下面就是用户自定义的所有表单字段 for (int i = 0; i < actionForm.getPropertyNameList().length; i++) { String name = actionForm.getPropertyNameList()[i]; Class valueType = actionForm.getPropertyValueTypeList()[i]; // 判断字段名称是否有效 if (name != null && name.trim().length() > 0) { formDefinition.getFieldDefinitionList().put(name, valueType); } } // 保存表单定义 formDefinitionService.save(formDefinition); return mapping.findForward("toList"); } |
4.删除表单
/** * 删除自定义表单 */ public ActionForward del(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 获取将被删除的表单记录id Long id = Long.parseLong(request.getParameter("id")); formDefinitionService.delete(id); return mapping.findForward("toList"); } |
二、设计流程
我们学习的内容以“请假流程”为例。
1. 设计流程
开始->提交申请->部门经理审批->结束:
| 开始 |
为其添加一个名称为“提交申请”的Task,设置它的Assignment的Actor为“#{applicantActorId}”。 |
为其添加一个名称为“审批”的Task,设置它的Assignment的handler为“cn.itcast.oa.process.leave.DeptManagerAssignmentHandler”。 |
结束 |
DeptManagerAssignmentHandler类的实现明天再列出,将上面设计的流程部署到OA项目中。然后编写测试类对流程进行测试。因为使用JBPM流程在前边已经讲过了,所以在些就不详细列出了。上面的流程执行过程为,开始:创建流程实例à办理任务:提交申请à办理任务:部门经理审批à结束。
三、表单实例
我们已经将流程定义、表单定义搞定了和测试执行流程,接下来我们应该生成表单实例。将表单实例入到流程中进行流转处理。
通过第一部分的全景图我们知道:FormDefinition、FormInstance、ApproveInfo与Employee之间的关系。
FormDefinition:表单定义,能过定义生成实例。
FormInstance:表单实例,一个流程中只能有一个表单实例。
ApproveInfo:审批信息,一个流程中可以具有多个审批。
Employee:职员
FormInstance:
public class FormInstance { // 表单状态常量 public static final String STATUS_PROCESSING = "正在审批中"; public static final String STATUS_APPROVED = "已通过审批"; public static final String STATUS_NOT_APPROVED = "未通过审批"; private Long id; private FormDefinition formDefinition;// 使用的表单定义 private Map<String, Serializable> propertyMap = new HashMap<String, Serializable>();// 表单信息 private Employee applicant; // 申请人 private Date applyTime; // 申请时间 private String title; // 标题 private String status; // 状态 private Set<ApproveInfo> approveInfos = new HashSet<ApproveInfo>();// 审批信息 private Long processInstanceId; // 流程实例ID //setters and getters… } |
ApproveInfo:
public class ApproveInfo { private Long id; private Employee approver;//审批人 private Date approveTime;//审批时间 private FormInstance formInstance;//表单实例 private boolean approval;//是否同意 private String comment;//意见 private Long taskInstanceId;//任务实例ID //setters and getters… } |
现在看一看什么才是最重要的?就是这些实体,实体体现了业务逻辑。把业务逻辑搞明白了,实体设计出来了。实现上没有什么太难的。
明日将学习具体生成表单实例并应用到流程中,生成审批信息等。我们也可以查看自己的申请和待我申请等与审批模块相关的操作信息。