• 2017.2.28 activiti实战--第七章--Spring容器集成应用实例(五)普通表单


    学习资料:《Activiti实战》

    第七章  Spring容器集成应用实例(五)普通表单

    第六章中介绍了动态表单、外置表单。这里讲解第三种表单:普通表单。

    普通表单的特点:

    1 把表单内容写在表现层(JSP、JSF、HTML)文件中
    2 一个用户任务对应一个页面
    3 业务数据和流程数据分离
    4 适用于业务相对固定但复杂、流程相对固定但表现层变化多的情况

    因为普通表单中,业务数据和流程数据是分离的,所以存在统一事务管理的问题。要保证Activiti和业务数据操作在同一个事务中执行。前面集成Spring时的事务管理器的配置可表明这点。本节基于第六章的主要针请假流程,对数据和表单都分离的情况下,采用普通表单实现该功能。

    本节采用Spring、SpringMVC和Hibernete。

    7.5.1 业务建模

    (1)表结构

    (2)其他

    DAO和Manger用来针对请假实体的CRUD,Leave-workflowService用来处理流程相关操作。

    7.5.2 启动流程

    (1)部署流程

    在启动流程之前,先部署流程。

    第六章已经实现过这个页面,不再提。总之,点击浏览,选择文件,然后submit,将chapter7/leave.bpmn和leave.png打包部署。部署完毕之后,在该列表页面中,会出现一个新的processDefinition记录。

    (2)jsp

    普通表单使用时,需要将表单内容保存在一个单独的文件中。这里采用jsp文件格式。

    表单设计如下:

     1     <form action="${ctx }/chapter7/leave/start" class="form-horizontal" method="post" onsubmit="beforeSend()">
     2         <input type="hidden" name="startTime" />
     3         <input type="hidden" name="endTime" />
     4         <fieldset>
     5             <legend><small>请假申请</small></legend>
     6             <div id="messageBox" class="alert alert-error input-large controls" style="display:none">输入有误,请先更正。</div>
     7             <div class="control-group">
     8                 <label for="loginName" class="control-label">请假类型:</label>
     9                 <div class="controls">
    10                     <select id="leaveType" name="leaveType" class="required">
    11                         <option>公休</option>
    12                         <option>病假</option>
    13                         <option>调休</option>
    14                         <option>事假</option>
    15                         <option>婚假</option>
    16                     </select>
    17                 </div>
    18             </div>
    19             <div class="control-group">
    20                 <label for="name" class="control-label">开始时间:</label>
    21                 <div class="controls">
    22                     <input type="text" id="startDate" class="datepicker input-small" data-date-format="yyyy-mm-dd" />
    23                     <input type="text" id="startTime" class="time input-small" />
    24                 </div>
    25             </div>
    26             <div class="control-group">
    27                 <label for="plainPassword" class="control-label">结束时间:</label>
    28                 <div class="controls">
    29                     <input type="text" id="endDate" class="datepicker input-small" data-date-format="yyyy-mm-dd" />
    30                     <input type="text" id="endTime" class="time input-small" />
    31                 </div>
    32             </div>
    33             <div class="control-group">
    34                 <label for="groupList" class="control-label">请假原因:</label>
    35                 <div class="controls">
    36                     <textarea name="reason"></textarea>
    37                 </div>
    38             </div>
    39             <div class="form-actions">
    40                 <button type="submit" class="btn"><i class="icon-play"></i>启动流程</button>
    41             </div>
    42         </fieldset>
    43     </form>
    form

    webapp/WEB-INF/views/chapter7/leave/leaveApply.jsp如下:

     1 <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
     2 <!DOCTYPE html>
     3 <html>
     4 <head>
     5     <%@ include file="/common/global.jsp"%>
     6     <%@ include file="/common/meta.jsp" %>
     7     <%@ include file="/common/include-base-styles.jsp" %>
     8     <link rel="stylesheet" href="${ctx}/js/common/plugins/timepicker.css">
     9     <title>请假申请</title>
    10     <script type="text/javascript" src="${ctx }/js/common/jquery.js"></script>
    11     <script type="text/javascript" src="${ctx }/js/common/bootstrap.min.js"></script>
    12     <script type="text/javascript" src="${ctx }/js/common/bootstrap-datepicker.js"></script>
    13     <script type="text/javascript" src="${ctx }/js/common/plugins/bootstrap-timepicker.js"></script>
    14     <script type="text/javascript">
    15     $(function() {
    16         $('.datepicker').datepicker();
    17         $('.time').timepicker({
    18             minuteStep: 10,
    19             showMeridian: false
    20         });
    21     });
    22 
    23     function beforeSend() {
    24         $('input[name=startTime]').val($('#startDate').val() + ' ' + $('#startTime').val());
    25         $('input[name=endTime]').val($('#endDate').val() + ' ' + $('#endTime').val());
    26     }
    27     </script>
    28 </head>
    29 <body>
    30     <c:if test="${not empty message}">
    31         <div id="message" class="alert alert-success">${message}</div>
    32         <!-- 自动隐藏提示信息 -->
    33         <script type="text/javascript">
    34         setTimeout(function() {
    35             $('#message').hide('slow');
    36         }, 5000);
    37         </script>
    38     </c:if>
    39     <form>
    40         <!--表单的代码放在这里-->
    41     </form>
    42 </body>
    43 </html>
    View Code

    (3)Controller

     在上面的流程定义列表页面中,增加一个字段"操作",里面包含两个button,一个是启动,一个是删除。

    当点击"启动时",应该要显示表单,并且点击申请时,流程启动。

     1 @Controller
     2 @RequestMapping(value = "/chapter7/leave")
     3 public class LeaveController {
     4 
     5     private Logger logger = LoggerFactory.getLogger(getClass());
     6 
     7     @Autowired
     8     private LeaveManager leaveManager;
     9 
    10     @Autowired
    11     private LeaveWorkflowService leaveService;
    12 
    13     @Autowired
    14     private TaskService taskService;
    15 
    16     @Autowired
    17     private RuntimeService runtimeService;
    18 
    19     @RequestMapping(value = {"apply", ""})
    20     public String createForm(Model model) {
    21         model.addAttribute("leave", new Leave());
    22         return "/chapter7/leave/leave-apply";
    23     }
    24 
    25     /**
    26      * 启动请假流程
    27      */
    28     @RequestMapping(value = "start", method = RequestMethod.POST)
    29     public String startWorkflow(Leave leave, RedirectAttributes redirectAttributes, HttpSession session) {
    30         try {
    31             User user = UserUtil.getUserFromSession(session);
    32             Map<String, Object> variables = new HashMap<String, Object>();
    33             ProcessInstance processInstance = leaveService.startWorkflow(leave, user.getId(), variables);
    34             redirectAttributes.addFlashAttribute("message", "流程已启动,流程ID:" + processInstance.getId());
    35         } catch (ActivitiException e) {
    36             if (e.getMessage().indexOf("no processes deployed with key") != -1) {
    37                 logger.warn("没有部署流程!", e);
    38                 redirectAttributes.addFlashAttribute("error", "没有部署请假流程");
    39             } else {
    40                 logger.error("启动请假流程失败:", e);
    41                 redirectAttributes.addFlashAttribute("error", "系统内部错误!");
    42             }
    43         } catch (Exception e) {
    44             logger.error("启动请假流程失败:", e);
    45             redirectAttributes.addFlashAttribute("error", "系统内部错误!");
    46         }
    47         return "redirect:/chapter7/leave/apply";
    48     }
    49     
    50     ...
    51 }

    (4)Service

    前面提过,这里要实现业务和流程数据的分离。即业务数据存在一个表里,流程数据存在另一个表。但是又要将二者联系起来。

    这里采取的办法是:

    1 业务表:增加一个字段process_instance_id,方便从业务层面查询流程数据。
    2 流程表:用entity的ID作为processDefinitionKey,方便从流程层面查询业务数据。

    可以从代码中看出来,这里不只是单纯的启动流程。还进行了数据的存储与关联。

     1 @Service
     2 @Transactional
     3 public class LeaveWorkflowService {
     4 
     5     private Logger logger = LoggerFactory.getLogger(getClass());
     6 
     7     @Autowired
     8     LeaveManager leaveManager;
     9 
    10     @Autowired
    11     private IdentityService identityService;
    12 
    13     @Autowired
    14     private RuntimeService runtimeService;
    15 
    16     @Autowired
    17     private TaskService taskService;
    18 
    19     @Autowired
    20     private RepositoryService repositoryService;
    21 
    22     /**
    23      * 保存请假实体并启动流程
    24      */
    25     public ProcessInstance startWorkflow(Leave entity, String userId, Map<String, Object> variables) {
    26         if (entity.getId() == null) {
    27             entity.setApplyTime(new Date());
    28             entity.setUserId(userId);
    29         }
    30         leaveManager.save(entity);//持久化请假实体
    31         String businessKey = entity.getId().toString();//实体保存后的ID,作为流程中的业务key
    32 
    33         // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中
    34         identityService.setAuthenticatedUserId(userId);
    35 
    36         ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables);//将业务主ID设置为流程实例的key
    37         String processInstanceId = processInstance.getId();
    38         entity.setProcessInstanceId(processInstanceId);// 将流程实例的ID保存至业务表
    39         logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"leave", businessKey, processInstanceId, variables});
    40         leaveManager.save(entity);
    41         return processInstance;
    42     }
    43 
    44     ...
    45 }

     7.5.3 任务读取

  • 相关阅读:
    dajngo控制台添加数据报错Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured.
    windows cmd编辑文本
    Centos pip 安装uwsgi 报错“fatal error: Python.h: No such file or directory”
    linux 配置启动supervisor详细
    安装supervisor 失败 :/usr/bin/python: bad interpreter: No such file
    yum 安装,可以list,但是无法安装Error downloading packages: 。。。。 No such file or directory
    linux 所有命令无法使用
    mysql库、表、记录的基本操作
    2数据库的三大范式
    1初识数据库mysql
  • 原文地址:https://www.cnblogs.com/lyh421/p/6484373.html
Copyright © 2020-2023  润新知