Struts原理與實踐(8)
大家知道,樹型選單在應用中有著十分廣泛的用途。實現樹型選單的途徑較多,本文介紹的一種覺得理解起來比較直觀,與上篇文章的方法比較類似:就是將樹型選單的節點儲存在資料庫表中(當然,在實際專案中,節點的資訊往往並不是放在一個單一的表中的。比如:在一個許可權管理系統中,這些資訊可能分別放在使用者表、角色表、功能表等表中,只要設法讓查詢出來的結果與下面給出的表格的內容相似就可以了。只要稍微有些資料庫方面的知識做到這點並不難,詳細的實現細節超出了本文的主題,不在此細說)。通過資料訪問物件將其從資料庫中查出後放在一個集合物件中,並將該集合物件傳遞給客戶端,再用一段現存的JavaScript程式碼--dtree(一個免費的JavaScript程式)來操作集合中的資料。大方向確定之後,我們就來具體著手來實現它。
根據dtree的要求,我們來建一個數據庫表來儲存樹的節點資訊,表名為functions,其結構如下:
id欄位:varchar 10 主鍵--節點標識碼 pid欄位:varchar 10 not null--父節點標識碼 name欄位:varchar 20 not null url欄位:varchar 50 not null--這個欄位儲存的是點選該節點時,要定位的資源(比如一個頁面的url), 為了不使本文的篇幅過長,暫時不給出相應的頁面, 您可以隨便輸入一個字母比如:a,以使本例能夠正常執行。 title欄位:varchar 20 target欄位:varchar 10 icon欄位:varchar 20 iconopen欄位:varchar 20 opened欄位:char 1 |
在表中輸入如下一些記錄以供後面的實驗用:
0、-1、我的許可權、javascript: void(0); 00、0、使用者管理、javascript: void(0); 0001、00、建立新使用者; 0002、00、刪除使用者; 01、0、 文章管理、javascript: void(0); 0101、01、新增新文章; 0102、01、修改文章; 0103、01、刪除文章; |
到此,資料庫方面的準備工作就告一段落。
接下來的工作我們仍然在先前介紹的mystruts專案中進行。先編寫一個名為:FunctionsForm的ActionForm,其程式碼如下:
package entity; import org.apache.struts.action.*; import javax.servlet.http.*; public class FunctionsForm extends ActionForm { private String icon; private String iconOpen; private String id; private String name; private String opened; private String pid; private String target; private String title; private String url; public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getIconOpen() { return iconOpen; } public void setIconOpen(String iconOpen) { this.iconOpen = iconOpen; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getOpened() { return opened; } public void setOpened(String opened) { this.opened = opened; } public String getPid() { return pid; } public void setPid(String pid) { this.pid = pid; } public String getTarget() { return target; } public void setTarget(String target) { this.target = target; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } } |
因為我們的樹型節點的資料都儲存在資料庫表中,接下來,要做一個數據訪問物件類,名稱為:FunctionsDao.java,其程式碼如下:
package db; import java.sql.*; import java.util.*; import entity.FunctionsForm; public class FunctionsDao { private static Connection con = null; public FunctionsDao(Connection con) { this.con=con; } public static Collection findTree() { PreparedStatement ps=null; ResultSet rs = null; ArrayList list=new ArrayList(); String sql="select * from functions"; try{ if(con.isClosed()){ throw new IllegalStateException("error.unexpected"); } ps=con.prepareStatement(sql); rs=ps.executeQuery(); while(rs.next()){ FunctionsForm functionsForm=new FunctionsForm(); functionsForm.setId(rs.getString("id")); functionsForm.setPid(rs.getString("pid")); functionsForm.setName(rs.getString("name")); functionsForm.setUrl(rs.getString("url")); functionsForm.setTitle(rs.getString("title")); functionsForm.setTarget(rs.getString("target")); functionsForm.setIcon(rs.getString("icon")); functionsForm.setIconOpen(rs.getString("iconOpen")); functionsForm.setOpened(rs.getString("opened")); list.add(functionsForm); } return list; } catch(SQLException e){ e.printStackTrace(); throw new RuntimeException("error.unexpected"); } finally{ try{ if(ps!=null) ps.close(); if(rs!=null) rs.close(); }catch(SQLException e){ e.printStackTrace(); throw new RuntimeException("error.unexpected"); } } } } |
這裡值得注意的是:在以往我們見到的一些顯示樹型選單的程式,如:一些asp程式中往往簡單地採用遞迴呼叫的方法來查詢到樹的各個節點。這對那些樹的深度不確定的場合還是有些用處,但這種處理方法也有一個致命的弱點,那就是反覆地進行資料庫查詢,對一些節點較多的應用,對應用程式效能的影響是非常大的,有時會慢得讓人難以接受;而在實際的應用中大多數情況下樹的深度往往是有限的,如:用於會計科目的樹一般最多也在六層以下。又如:用作網頁功能選單的情況,網頁設計的原則就有一條是:達到最終目的地,滑鼠點選次數最好不要多於三次。因此,在實際設計儲存樹型結構的表時要考慮查詢的效率。對能確定樹的最大深度的情況下,要設法儘量優化查詢語句,減少查詢次數,以提高應用程式的效能同時減少資料庫的負荷。
本例對應的Action的名稱為FunctionsAction,其程式碼如下:
package action; import entity.*; import org.apache.struts.action.*; import javax.servlet.http.*; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; import java.util.Collection; import db.FunctionsDao; public class FunctionsAction extends Action { public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { DataSource dataSource; Connection cnn=null; ActionErrors errors=new ActionErrors(); try{ dataSource = getDataSource(httpServletRequest,"A"); cnn = dataSource.getConnection(); FunctionsDao functionsDao=new FunctionsDao(cnn); Collection col=functionsDao.findTree(); httpServletRequest.setAttribute("treeList",col); return actionMapping.findForward("success"); } catch(Throwable e){ e.printStackTrace(); //throw new RuntimeException("未能與資料庫連線"); ActionError error=new ActionError(e.getMessage()); errors.add(ActionErrors.GLOBAL_ERROR,error); } finally{ try{ if(cnn!=null) cnn.close(); } catch(SQLException e){ throw new RuntimeException(e.getMessage()); } } saveErrors(httpServletRequest,errors); return actionMapping.findForward("fail"); } } |
在struts-config.xml檔案中加入如下內容:
<form-beans> <form-bean name="functionsForm" type="entity.FunctionsForm" /> </form-beans> <action-mappings> <action name="functionsForm" path="/functionsAction" scope="request" type="action.FunctionsAction" validate="false" > <forward name="success" path="/testDTree.jsp" /> <forward name="fail" path="/genericError.jsp" /> </action> </action-mappings> |
為了對應配置中的,我們還要提供一個顯示錯誤資訊的jsp頁面,其程式碼如下:
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <html> <head> <title> genericError </title> <link href="css/mycss.css" rel="stylesheet" type="text/css"> </head> <body bgcolor="#ffffff"> <html:errors/> </body> </html> |
下面,我們來看一下我們顯示樹型選單的頁面程式碼,從配置中可以看出,頁面的名稱為testDTree.jsp,程式碼如下:
<%@ page contentType="text/html; charset=UTF-8" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %> <html> <head> <title> testDTree </title> <link rel="StyleSheet" href="css/dtree.css" type="text/css" /> </head> <body bgcolor="#eeeeee"> <body leftmargin="0" topmargin="0"><table width="180"> <tr><td height="300" valign="top" nowrap> <script type="text/javascript" src="js/dtree.js"></script> <script type='text/javascript'> tree = new dTree('tree'); tree.config.folderLinks=false; tree.config.useCookies=false; <logic:iterate id="functionsForm" name="treeList" scope="request" type="entity.FunctionsForm"> tree.add("<bean:write name="functionsForm" property="id"/>","<bean:write name="functionsForm" property="pid"/>","<bean:write name="functionsForm" property="name"/>","<bean:write name="functionsForm" property="url"/>","<bean:write name="functionsForm" property="title"/>","<bean:write name="functionsForm" property="target"/>","<bean:write name="functionsForm" property="icon"/>"); </logic:iterate> document.write(tree); </script> </td> </tr> </table> </body> </html> |
從 可以看出,我們要在mystruts目錄下,建一個名為js的目錄,並將下載的dtree檔案dtree.js放在該目錄中。
再在mystruts目錄下分別建一個名為img和名為css的目錄,將dtree中用到的圖示和層疊樣式表單檔案分別放在相應的目錄中。
有關dtree的使用方法,詳見其說明文件,如:api.html。筆者在此要感謝dtree的作者為我們提供了一個結構如此清晰的javascript程式!
現在,可以編譯執行這個例子程式了,編譯後在瀏覽器中輸入:http://127.0.0.1:8080/mystruts/functionsAction.do就可以看到執行效果。效果圖為:
注:dtree的下載地址為: http://www.destroydrop.com/javascripts/tree/
本文作者:張永美 羅會波 湖北省當陽市國稅局 可通過[email protected]與他們聯絡
相關文章
·Struts原理與實踐(1)·(2)·(3)·(4)·(5)·(6)·(7)
相關推薦
Struts原理與實踐(8)
在上一篇文章中介紹JavaScript實現級聯下拉選單的例子,本篇繼續介紹一個利用現存的JavaScript程式碼配合struts構成一個樹型選單的例子。 大家知道,樹型選單在應用中有著十分廣泛的用途。實現樹型選單的途徑較多,本文介紹的一種覺得理解起來比較直觀,與上篇
Struts原理與實踐(三)
一、JDBC的工作原理 Struts在本質上是java程式,要在Struts應用程式中訪問資料庫,首先,必須搞清楚Java Database Connectivity API(JDBC)的工作原理。正如其名字揭示的,JDBC庫提供了一個底層API,用來支援獨立於任何特定SQL實
struts原理與實踐(四)
本篇我們來討論一下struts的國際化程式設計問題,即所謂的i18n程式設計問題,這一篇我們討論其基礎部分。與這個問題緊密相關的是在各java論壇中被頻繁提及的中文亂碼問題,因為,英、美程式設計人員較少涉及到中文亂碼問題,因此,這方面的英文資料也是非常奇缺的,同時也很少找到這方面比較完整的中文資料,本文也嘗試
Struts原理與實踐(4)
本篇我們來討論一下struts的國際化程式設計問題,即所謂的i18n程式設計問題,這一篇我們討論其基礎部分。與這個問題緊密相關的是在各java論壇中被頻繁提及的中文亂碼問題,因為,英、美程式設計人員較少涉及到中文亂碼問題,因此,這方面的英文資料也是非常奇缺的,同時也很少找到這
struts原理與實踐(二)
(第2部分) 下面,我們就一步步按照上面所說的步驟來完成我們的應用程式: 第一步,我們的應用程式的Views部分包含兩個.jsp頁面:一個是登入頁面logon.jsp,另一個是使用者登入成功後的使用者功能頁main.jsp,暫時這個頁面只是個簡單的歡迎頁面。 其中,
Struts原理與實踐(6)
本文我們來討論一下Struts中的輸入校驗問題。我們知道,資訊系統有垃圾進垃圾出的特點,為了避免垃圾資料的輸入,對輸入進行校驗是任何資訊系統都要面對的問題。在傳統的程式設計實踐中,我們往往在需要進行校驗的地方分別對它們進行校驗,而實際上需要校驗的東西大多都很類似,如必需的欄位
Webpack原理與實踐(一):打包流程
寫在前面的話 在閱讀 webpack4.x 原始碼的過程中,參考了《深入淺出webpack》一書和眾多大神的文章,結合自己的一點體會,總結如下。 總述 webpack 就像一條生產線,要經過一系列處理流程後才能將原始檔轉換成輸出結果。 這條生產線上的每個處理流程的職責都是單一的,多個流程之間有存在依賴關
Docker容器的原理與實踐(上)
系統 rest 引擎 服務器 分類 file creat 產品 maintain 歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。虛擬化是一種資源管理技術,將計算機的各種資源予以抽象、轉換後呈現出來, 打破實體結構間的不可切割的障礙,使用戶可以比原本更好的方式來應用這些資
機器學習演算法原理與實踐(三)、卡爾曼濾波器演算法淺析及matlab實戰
卡爾曼濾波器是一種利用線性系統狀態方程,通過系統輸入輸出觀測資料,對系統狀態進行最優估計的演算法。而且由於觀測包含系統的噪聲和干擾的影響,所以最優估計也可看做是濾波過程。 卡爾曼濾波器的核心
機器學習演算法原理與實踐(六)、感知機演算法
感知機 感知機是二分類的線性分類模型,輸入為例項的特徵向量,輸出為例項的類別(取+1和-1)。感知機對應於輸入空間中將例項劃分為兩類的分離超平面。感知機旨在求出該超平面,為求得超平面匯入了基於誤分類的損失函式,利用梯度下降法對損失函式進行最優化(最優
Spring Boot自動配置原理與實踐(一)
前言 Spring Boot眾所周知是為了簡化Spring的配置,省去XML的複雜化配置(雖然Spring官方推薦也使用Java配置)採用Java+Annotation方式配置。如下幾個問題是我剛開始接觸Spring Boot的時候經常遇到的一些疑問,現在總結出來希望能幫助到更多的人理解Spring B
深度優先搜尋原理與實踐(java)
概論 深度優先搜尋屬於圖演算法的一種,是一個針對圖和樹的遍歷演算法,英文縮寫為 DFS 即 Depth First Search。深度優先搜尋是圖論中的經典演算法,利用深度優先搜尋演算法可以產生目標圖的相應拓撲排序表,利用拓撲排序表可以方便的解決很多相關的圖論問題,如最大路徑問題等等。一般用堆資料結構來輔
數字圖像處理原理與實踐(MATLAB版)勘誤表
blog 核心 灰度變換 圖像復原 京東 .html href target 數字圖像處理 本文系《數字圖像處理原理與實踐(MATLAB版)》一書的勘誤表。【內容簡單介紹】本書全面系統地介紹了數字圖像處理技術的理論與方法,內容涉及幾何變換、灰度變換、圖像增強、圖像切割、
編碼原則實例------c++程序設計原理與實踐(進階篇)
組類型 運算 奇怪 head 不能 gui 簡單的 版本 布局 編碼原則: 一般原則 預處理原則 命名和布局原則 類原則 函數和表達式原則 硬實時原則 關鍵系統原則 (硬實時原則、關鍵系統原則僅用於硬實時和關鍵系統程序設計) (嚴格原則都用一個大寫字母R及其編號標識,而
有符號數和無符號數------c++程序設計原理與實踐(進階篇)
效果 進階 str 二進制位 bsp () 都是 有符號 重新 有符號數與無符號數的程序設計原則: 當需要表示數值時,使用有符號數(如 int)。 當需要表示位集合時,使用無符號數(如unsigned int)。 有符號數和無符號數混合運算有可能會帶來災難性的後果。例如
動態內存分配存在的問題(內存空洞)------c++程序設計原理與實踐(進階篇)
我們 程序 動態 height ++ idt 很多 alt 空間 new的問題究竟在哪裏呢?實際上問題出在new和delete的結合使用上。考察下面程序中內存分配和釋放過程: while(1){ Big* p=new big; //...... Smal
數值限制------c++程序設計原理與實踐(進階篇)
c++程序 its positive size true 設置 malle 設計原理 硬件 每種c++的實現都在<limits>、<climits>、<limits.h>和<float.h>中指明了內置類型的屬性,因此程序
實現求解線性方程(矩陣、高斯消去法)------c++程序設計原理與實踐(進階篇)
ipy 類型 cat sys sca solution gaussian 拷貝 img 步驟: 其中A是一個n*n的系數方陣 向量x和b分別是未知數和常量向量: 這個系統可能有0個、1個或者無窮多個解,這取決於系數矩陣A和向量b。求解線性系統的方法有很多,這裏使用一種經典
(c++11)隨機數------c++程序設計原理與實踐(進階篇)
ber linear 而在 希望 double 元素 light eal 區間 隨機數既是一個實用工具,也是一個數學問題,它高度復雜,這與它在現實世界中的重要性是相匹配的。在此我們只討論隨機數哦最基本的內容,這些內容可用於簡單的測試和仿真。在<random>
Exp2 後門原理與實踐(未完待續)
bin image alt job 模塊 加強 ont .sh 問題 Exp2 後門原理與實踐 實驗環境 攻擊機 kali 4.14(64位) (IP: 10.0.2.6/24) 靶機 ubuntu 16.04(32位) (IP: 10.0.2.4/24) windo