今日的北京氣溫回升,昨天是降溫。天氣的變暖,讓大家感覺十分溫暖,課上睡意連綿。湯兄弟有發(fā)現(xiàn)大家的狀況,所以今天拿出了一點時間與大家交流學習方法或技術上的一些問題。授課進度完全在掌握之中。
未來三天的內容,學習使用JBMP解決審批流轉這一大模塊的需求。今日的課程內容比較簡單,但在實際項目中的應用卻十分重要。把WEB基礎搞的差不多了,這些框架并沒什么難的。更多的是應該多使用,多熟悉他們。兩大重點內容:通用超強分頁功能、JBPM審批流程管理。
一、通用超強分頁功能
1.分頁效果
(圖1.1)
圖1.1中顯示的分頁功能是目前我見到的,功用最全的分頁功能。當然也是論壇中比較常用的分頁功能。我們今日就實現(xiàn)這個通用超級分頁功能。
2.分頁Bean
湯老師使用自己的講課風格(應該也是他做項目時的編寫風格),由廣入微、由粗糙到細致。使用他的方法做分析比較好,這或許是通用的分析方式吧!
我們看圖1.1中具有的屬性:
v 頁碼:1/11頁
v 每頁顯示:30條
v 總記錄數(shù):301條
v 分頁: [首頁] [上一頁] [下一頁] [尾頁] 1 2 3 4 5 6 7 8 9 10
OK,我們根據(jù)頁面信息取出了分頁Bean的屬性,并設計分頁Bean:
import java.util.List; public class PageView { // 通過參數(shù)指定的信息 private int currentPage;// 當前頁碼 private int pageSzie;// 每頁顯示記錄數(shù)量 // 通過查詢數(shù)據(jù)庫獲取的信息,外部獲取 private int recordTotal;// 總記錄數(shù) private List recordList;// 當前面記錄信息列表 // 通過計算生成的信息 private int pageTotal;// 總頁面數(shù)量 private int startIndex;// 起始頁面索引 private int endIndex;// 結束頁面索引 // 顯示的頁面數(shù)量 private static final int PAGE_INDEX_COUNT = 10; // 在構造方法中生成各種需要的信息 public PageView(int currentPage, int pageSize, int recordTotal, List recordList) { this.currentPage = currentPage; this.pageSzie = pageSize; this.recordTotal = recordTotal; this.recordList = recordList; // 通過計算生成startIndex和endIndex /* * 因為顯示的頁面索引數(shù)量是有限的 我們不能把所以的頁面索引一下子全列出來 我們需要動態(tài)顯示頁面索引列表 */ this.pageTotal = (this.recordTotal + this.pageSzie - 1) / this.pageSzie; // 如果頁面總數(shù)<=顯示頁面索引數(shù)量 if (this.pageTotal <= PAGE_INDEX_COUNT) { this.startIndex = 1; this.endIndex = this.pageTotal; } else { // 根據(jù)當前頁面索引生成,頁面起始索引和結束索引。 // 區(qū)分偶數(shù)和奇數(shù) 頁面索引數(shù)量 if (PAGE_INDEX_COUNT % 2 == 0) { this.startIndex = this.currentPage - (PAGE_INDEX_COUNT / 2 - 1); this.endIndex = this.currentPage + (PAGE_INDEX_COUNT / 2); } else { this.startIndex = this.currentPage - (PAGE_INDEX_COUNT / 2); this.endIndex = this.currentPage + (PAGE_INDEX_COUNT / 2); } // 如果生成的起始索引小于1 if(this.startIndex < 1){ this.startIndex = 1; this.endIndex = PAGE_INDEX_COUNT; } // 如果生成的結束索引大于總頁面索引數(shù)量 if(this.endIndex > this.pageTotal){ this.endIndex = this.pageTotal; this.startIndex = this.pageTotal - PAGE_INDEX_COUNT; } } } // ...getters AND setters } |
3.審批流程的DispathcAction
我們與上次課程一樣,需要為審批流程編寫一個DispatchAction。涉及到顯示審批流程列表只有一個方法——list:
/** * 顯示審批流程列表 */ public ActionForward list(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { int pageNum = Integer.parseInt(request.getParameter("pageNum")); // 調用ProcessDefinitionService接口的getPageView方法獲取PageView對象 PageView pageView = processDefinitionService.getPageView(pageNum); // 將PageView對象存放到request的pageView屬性中 request.setAttribute("pageView", pageView); return mapping.findForward("list"); // list.jsp } |
其中用到的“processDefinitionService.getPageView”方法:
/** * 獲取pageView信息 */ public PageView getPageView(int pageNum) { // 每面顯示10條記錄 int pageSize = 10; // 查詢數(shù)據(jù)庫 // 使用Number防止不同數(shù)據(jù)庫返回的數(shù)值類型不同,而引發(fā)的異常。 int count = ((Number) this.getSession().createQuery( "SELECT COUNT(*) FROM " + ProcessDefinition.class.getName() + " pd").uniqueResult()).intValue(); // 第一條記錄的索引 int firstRecoderIndex = (pageNum - 1) * pageSize; // 獲取記錄列表 List list = this.getSession().createQuery( "FROM " + ProcessDefinition.class.getName() + " pd") .setFirstResult(firstRecoderIndex).setMaxResults(pageSize) .list(); return new PageView(pageNum, pageSize, count, list); } |
4.顯示分頁信息的pageView.jspf頁面
多處使用到分頁頁面,所以我們將分頁頁面單獨提取出來。如果有哪個頁面需要顯示分頁信息,直接include就可以了。
<%@ page language="java" pageEncoding="utf-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <c:if test="${pageView.totalPage gt 1 }"> <!-- 分頁信息 --> 頁碼:${pageView.currentPage}/${pageView.totalPage}頁 每頁顯示:${pageView.pageSize}條 總記錄數(shù):${pageView.recordCount}條 分頁: <a href="javascript:gotoPage(1)">[首頁]</a> <c:if test="${pageView.currentPage gt 1}"> <a href="javascript:gotoPage(${pageView.currentPage - 1})">[上一頁]</a> </c:if> <c:if test="${pageView.currentPage lt pageView.totalPage}"> <a href="javascript:gotoPage(${pageView.currentPage + 1})">[下一頁]</a> </c:if> <a href="javascript:gotoPage(${pageView.totalPage})">[尾頁]</a> <!-- 顯示頁碼 --> <c:forEach begin="${pageView.startPageIndex}" end="${pageView.endPageIndex}" var="pageNum"> <c:if test="${pageNum eq pageView.currentPage}"> <span class="current_page">${pageNum}</span> </c:if> <c:if test="${pageNum ne pageView.currentPage}"> <a href="javascript:gotoPage(${pageNum})">${pageNum}</a> </c:if> </c:forEach> 轉到: <input type="text" id="txtPageNum" size="4" class="input_pagenum"/> <input type="button" onclick="gotoPage(document.getElementById('txtPageNum').value)" value="Go"/> <script type="text/javascript"> /** * 跳轉到指定的頁碼 */ function gotoPage( pageNum ){ if( isNaN(pageNum) ){ // not a number alert("請輸入正確的頁碼"); document.getElementById('txtPageNum').focus(); return false; } if( pageNum < 1 || pageNum > ${pageView.totalPage} ){ alert("請輸入正確的頁碼,范圍為 1-${pageView.totalPage}"); document.getElementById('txtPageNum').focus(); return false; } window.location.href = getPageViewUrl( pageNum ); // getPageViewUrl為在include頁面添加的javscript代碼, // 所以此頁面可以適用于任何分頁信息的顯示。例如下: //function getPageViewUrl( pageNum ){ // return "?method=list&pageNum=" + pageNum; //} } </script> </c:if> |
二、審批流轉管理
審批流轉就是把單位內部的各項審批電子化,如工作請求、出差申請、采購申請、請假、報銷等日常工作流程。
審批流轉(工作流):
1.流程與表單管理
2.執(zhí)行流程
3.查詢
有類似的審批請求,有兩大重點:流程定義和表單模板,一個表單對應一個流程。
要求:
1.方便 定義/修改 與 管理 流程定義
2.方便 定義/修改 與 管理 表單模板
3.執(zhí)行流程(讓表單(數(shù)據(jù))按指定的流程進行流轉,并且記錄)
4.方便查詢所有的表單實例(數(shù)據(jù)) 記錄(查詢流轉過的表單)
今日沒有講解設計與審批流轉相關的模塊,只是講解將打包成zip的JBPM工作流自動部署到OA項目中,并可查看顯示工作流的文件信息以及刪除工作流。
1.顯示部署流程
/** * 部署流程頁面 */ public ActionForward deployUI(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { return mapping.findForward("deployUI"); // deployUI.jsp } |
2.部署流程
/** * 部署流程 */ public ActionForward deploy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { try { // 獲取<html:file>表單提交過來的流程資源 ProcessDefinitionActionForm adaf = (ProcessDefinitionActionForm) form; ZipInputStream zipIn = new ZipInputStream(adaf.getParResource().getInputStream()); // 創(chuàng)建流程定義 ProcessDefinition pd = ProcessDefinition.parseParZipInputStream(zipIn); // 部署流程定義 this.processDefinitionService.deploy(pd); } catch (Exception e) { // 發(fā)生異常顯示錯誤 ActionErrors errors = new ActionErrors(); errors.add("error", new ActionMessage("非法的文件格式!",false)); this.saveErrors(request, errors); return mapping.findForward("deployUI"); } return mapping.findForward("toList"); // path="/pd.do?method=list" redirect="true" } |
因為部署流程時確保一個線程使用的是同一個“JbpmContext”,并確保Jbpm事件的正確提交或回滾。所以我們還需要為JbpmContext添加一個過濾器。
3.刪除流程
/** * 刪除流程 */ public ActionForward del(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取流程ID并刪除 Long id = Long.parseLong(request.getParameter("id")); this.processDefinitionService.delete(id); // 需要刷新流程顯示列表 String pageNum = request.getParameter("pageNum"); ActionForward af = mapping.findForward("toList"); return new ActionForward(af.getPath() + "&pageNum=" + pageNum, af.getRedirect()); } |
4.查看流程中的“processdefinition.xml”文件
/** * 查詢流程定義文件(processdefinition.xml) */ public ActionForward showProcessFile(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取流程id Long id = Long.parseLong(request.getParameter("id")); // 獲取流程定義 ProcessDefinition pd = this.processDefinitionService.getById(id); // 獲取文件 byte[] content = pd.getFileDefinition().getBytes( "processdefinition.xml"); // 寫出文件 response.setContentType("text/xml;charset=UTF-8"); response.getWriter().write(new String(content, "UTF-8")); return null; } |
5.查看流程中的“processimage.jpg”文件
/** * 查詢流程圖片(processimage.jpg) */ public ActionForward showProcessImage(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { // 獲取流程id Long id = Long.parseLong(request.getParameter("id")); // 獲取流程定義 ProcessDefinition pd = this.processDefinitionService.getById(id); // 獲取文件 byte[] content = pd.getFileDefinition().getBytes("processimage.jpg"); // 寫出文件 response.setContentType("image/jpeg"); response.getOutputStream().write(content); return null; } |
明天將學習自定義表單模板,和向流程中加入控制代碼。今天的內容還需要在大腦里整理整理...!
加油!