zoukankan      html  css  js  c++  java
  • 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 任务读取

  • 相关阅读:
    2015531 网络攻防 Exp1 PC平台逆向破解(5)M
    2017-2018-1 20155331 嵌入式C语言
    20155330 《网络对抗》 Exp9 web安全基础实践
    20155330 《网络对抗》 Exp8 Web基础
    20155330 《网络对抗》 Exp7 网络欺诈防范
    20155330 《网络对抗》 Exp6 信息搜集与漏洞扫描
    20155330 《网络对抗》 Exp5 MSF基础应用
    20155330 《网络攻防》 Exp4 恶意代码分析
    20155330 《网络攻防》 Exp3 免杀原理与实践
    20155330 《网络对抗》 Exp2 后门原理与实践
  • 原文地址:https://www.cnblogs.com/lyh421/p/6484373.html
Copyright © 2011-2022 走看看