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 任務讀取


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM