獨立開發(fā)者的低代碼-建立自己的JAVA程序框架(java開源低代碼開發(fā)平臺)
如果你長期從事信息管理系統(tǒng)的獨立開發(fā),可能會發(fā)現(xiàn)客戶的需求大多以增刪改查為主,除了數(shù)據(jù)表的內(nèi)容不同以外其他基本相同,將共性代碼封裝到框架能減少重復(fù)勞動;瀏覽器端代碼和服務(wù)器端代碼交織,調(diào)式不便,效率低下,通過將瀏覽器端的常用組件封裝為JAVA對象,做到大部份需求僅僅靠寫JAVA代碼就能滿足,降低調(diào)式難度,提高開發(fā)效率。
一、獨立開發(fā)者建議不采用流行框架的原因
JAVA程序開發(fā)框架可以降低JAVA程序開發(fā)難度,這是程序開發(fā)界的共識,因此,Hibernate、Strus、Spring等各種框架十分流行。但這些框架主要是為分工很細的大公司考慮,在靈活性、可擴展性方面考慮很多,對獨立開發(fā)者來說太繁雜了。我用JAVA編寫程序已有15年,但仍然沒有使用這些框架,原因之一就是這些框架繞的彎太多,讓人覺得頭暈。
Hibernate是一個開源的Java數(shù)據(jù)庫訪問框架,其操作一個數(shù)據(jù)表的步驟分為5步:一是建立與數(shù)據(jù)庫表中一行數(shù)據(jù)對應(yīng)的JAVA Bean形式的持久化對象類(稱為POJO);二是建立描述持久化對象和數(shù)據(jù)表之間映射關(guān)系的Hibernate配置文件;三是設(shè)置Hibernate本身的配置文件;四是根據(jù)配置文件初始化Hibernate會話的工廠類,進而得到Hibernate會話對象;五是由Hibernate會話對象得到持久化對象(對應(yīng)于數(shù)據(jù)庫表中的行),通過操作這些持久化對象,就可以操作數(shù)據(jù)庫表中的數(shù)據(jù)??梢奌ibernate真的很麻煩。
Strus也是這樣,其Xml配置文件繞來繞去,難以維護。Spring的依賴注入,面向切面的編程,給人的感覺就象是恨不能將所有的JAVA類及其構(gòu)造參數(shù)都移到xml配置文件中去。這些框架給我的感覺是功能強大但有90%的功能我用不上,配置靈活但內(nèi)容全放在和JAVA程序風(fēng)格大不相同的xml文件中。Java程序員為什么怕寫JAVA程序而熱衷于寫xml,真是令人費解。
二、獨立開發(fā)者如何建立自己的JAVA開發(fā)框架
由于數(shù)據(jù)分析應(yīng)用的業(yè)務(wù)需求主要是數(shù)據(jù)處理和數(shù)據(jù)查詢,因此我建立框架的目標是:盡可能只利用JAVA語言和SQL語言,直接實現(xiàn)全部數(shù)據(jù)處理業(yè)務(wù)需求。讓Html、CSS、JavaScript、Xml、jsp等這些普遍認為開發(fā)JAVA應(yīng)用程序必須掌握的技術(shù)離我們遠些吧!雖然開發(fā)一個實用穩(wěn)定的JAVA三層結(jié)構(gòu)應(yīng)用程序開發(fā)框架是一項難度較大的工作,但我通過先建立一個最簡單的應(yīng)用框架開始,在實際項目開發(fā)應(yīng)用中發(fā)現(xiàn)大多數(shù)項目都要用到的功能,就逐步往框架中添加,保證了該框架的對象和對象的方法都是實際開發(fā)工作中最需要的,從而保證了框架的實用性;框架在長期的項目應(yīng)用中,得到持續(xù)不斷的改進,保證了框架的可靠性。
該框架的設(shè)計思路是:利用JAVA面向?qū)ο蟮奶匦裕瑢tml、CSS、JavaScript、Xml等封裝在框架層,由對JAVA程序開發(fā)技術(shù)了解深入的程序員進行開發(fā)完善,力求“辛苦我一個,幸福千萬人”,使應(yīng)用層程序員從紛繁復(fù)雜的技術(shù)細節(jié)中解脫出來,專注于用JAVA語言來實現(xiàn)業(yè)務(wù)需求,再加上現(xiàn)在流行的JAVA集成開發(fā)環(huán)境“自動代碼完成“、“代碼重構(gòu)”等高級功能的輔助,使編寫應(yīng)用程序成為輕松愉快的工作。
在該框架設(shè)計過程中,為盡可能簡化應(yīng)用層難度,采取了一系列措施:一是以數(shù)據(jù)為中心,能從數(shù)據(jù)庫獲取的信息,就不需要應(yīng)用層程序員來設(shè)置。一些以JAVA對象為中心的框架,往往在xml配置文件中來設(shè)置主鍵、非空字段、字段類型等信息,增加了程序設(shè)計難度。而本框架直接從數(shù)據(jù)庫中獲得數(shù)據(jù)表的主鍵、非空字段、字段類型等信息,自動將其用于數(shù)據(jù)輸入校驗,不需要寫任何額外的程序。二是盡量減少完成一個功能所涉及的文件數(shù)量,盡可能做到一個應(yīng)用功能對應(yīng)一個JAVA程序文件。目前多數(shù)流行框架使用MVC設(shè)計模式,控制器一般由框架提供,完成一個數(shù)據(jù)應(yīng)用功能還需要用JAVA做模型、用JSP作視圖、如果采用O/R映射還需要建立一個JAVA實體Bean來放數(shù)據(jù)。而本框架一般在一個JAVA程序文件中完成這些工作,在單個業(yè)務(wù)需求變化時,涉及修改的程序代碼集中在一個文件中,減輕了維護工作量。三是URL映射簡單直接。流行框架通常存在一個配置URL和實際JAVA類對應(yīng)關(guān)系的xml映射文件,瀏覽器請求的URL經(jīng)過xml映射文件重定向后,變得對應(yīng)關(guān)系不清晰了,在發(fā)現(xiàn)網(wǎng)頁顯示錯誤時,不易直接找出引發(fā)錯誤的JAVA程序文件。本框架URL直接和JAVA程序文件一一對應(yīng),如:在瀏覽器地址欄輸入“http://127.0.0.1:8080/test/com.coyizz.pfc.userBean.class”后回車,如果網(wǎng)頁出現(xiàn)錯誤,就立即知道是test應(yīng)用項目下的JAVA類com.coyizz.pfc.userBean存在問題。
三、JAVA開發(fā)框架主要類介紹
(一)數(shù)據(jù)訪問對象Sql和DataStore
數(shù)據(jù)應(yīng)用的關(guān)鍵就是要查詢和處理數(shù)據(jù),直接用JAVA的JDBC數(shù)據(jù)訪問接口提供的功能主要適用于底層數(shù)據(jù)操作,在應(yīng)用層使用存在使用麻煩、中文字符集不能很好的處理等問題,業(yè)界推崇的DAO模式,要求應(yīng)用程序應(yīng)將數(shù)據(jù)庫訪問操作封裝在一個對象中。我將常用的數(shù)據(jù)庫訪問分為兩類:一類不涉及數(shù)據(jù)的輸入和顯示,相關(guān)功能封裝到Sql對象中;另一類涉及數(shù)據(jù)的輸入和顯示,相關(guān)功能封裝到DataStore對象中。DataStore對象內(nèi)部也需要用Sql對象進行基本的數(shù)據(jù)處理。
Sql對象實現(xiàn)了Sql查詢腳本的解析,以便在基本sql查詢腳本基礎(chǔ)上添加擴展查詢條件,并解決了數(shù)據(jù)庫訪問的字符集問題。
例A:已知用戶編碼查詢用戶名稱
String s = Sql.getResultString(“select name from usera where code = ‘0001’”, 1, AppConnItems.getConn());
例B:查詢?nèi)坑脩裘Q
Sql sql = new Sql(“select name from usera”);
Resultset rs = sql.getResultSet();
例C:在上例基礎(chǔ)上限制只能查詢單位代碼(dwdm)為‘1010’的用戶名稱
sql.setLimitWhere(“swdm=’1010’”);
rs = sql.getResultSet();
DataStore仿照PowerBuilder中的DataStore對象開發(fā)了Java版的DataStore對象,實現(xiàn)了復(fù)雜的數(shù)據(jù)訪問功能,和Hibernet等數(shù)據(jù)持久化方案比,不需要實體Bean來容納數(shù)據(jù),減少了JAVA類的的數(shù)量,增加了數(shù)據(jù)處理的靈活性;不需要配置xml文件,降低了開發(fā)難度,提高工作效率。能生成網(wǎng)頁顯示表格或表單所需的Html對象。除能方便地處理數(shù)字、字符、編碼字段外,還能處理文件、圖片、超鏈接等字段。
例A:查詢?nèi)坑脩裘Q和編碼
DataStore ds = DataStore(“dsMain”, “select name,code,fj from usera”, AppConnItems.getConn());
ds.retrieve();
例B:取得結(jié)查詢結(jié)果的第一行數(shù)據(jù)中的編碼數(shù)據(jù)或原文數(shù)據(jù)
String s = ds.getItemStr(1, “code”); // 取得編碼
s = ds.getItemStr(1, “code”); // 取得原文
例C:將查詢結(jié)果第三行數(shù)據(jù)中的“名稱”(name)字段設(shè)置“張三”并保存到數(shù)據(jù)庫
ds.setItem(3, “name”, “張三”);
ds.update();
例D:取得查詢結(jié)果的顯示用Html表格對象
HtmlTable ht = ds.getHtmlTable();
例E:取得查詢結(jié)果的行數(shù)
int rowCnt = ds.getRowCount();
例F:取得查詢結(jié)果的列數(shù)
int colCnt = ds.getColCount();
例G:刪除第1行
ds.deleteRow(1);
例H:在最后添加1行:
ds.insertRow(0);
例I:設(shè)置附件列(fj)為文件附件, 存放在Web應(yīng)用目錄的xxFj子目錄下,附件最大限制為20M。
ds.setColIsFileLink("fj", "xxFj", "", 20000000, true);
例J:設(shè)置附件列(fj)為圖片, 存放在Web應(yīng)用目錄的img子目錄下,擴展名只能為jpg或gif,附件最大限制為4M,圖片寬度為200,高不設(shè)置。
ds.setColIsImg(“fj”, “img”, “gif,jpg”, 4000000, 200, 0, true);
從以上例子來看,該數(shù)據(jù)訪問對象和PowerBuilder的DataStore十分相象,使原來的PowerBuilder程序員能較快地轉(zhuǎn)向JAVA程序的開發(fā)上來。
DataStore對象還有其他一些強大的功能:比如dsAdd方法可完成兩個DataStore中的數(shù)據(jù)迭加或追加,setZzjgLimit方法可根據(jù)用戶權(quán)限限制數(shù)據(jù)操作范圍,通過DataStore的一些構(gòu)造方法,可實現(xiàn)多個DataStore數(shù)據(jù)的內(nèi)聯(lián)或外聯(lián)。SetHoldData方法可使數(shù)據(jù)在網(wǎng)頁之間保持,validCheck方法可根據(jù)數(shù)據(jù)表的相關(guān)信息,對當前存放在DataStore對象中的數(shù)據(jù),進行數(shù)據(jù)類型、非空、主鍵重復(fù)等有效性檢查。GetSelectedRowsDs可取得用戶在瀏覽器上選中的數(shù)據(jù)行,GetDeletedRowsDs可取得用戶在瀏覽器上刪除的數(shù)據(jù)行。Sort可對DataStore對象中的數(shù)據(jù)按多列進行排序,fillSumRow可對指定多列數(shù)據(jù)求和??傊珼ataStore對象涵蓋了數(shù)據(jù)應(yīng)用開發(fā)中所需的大多數(shù)功能。
(二) HzBean對象
HzBean對象是響應(yīng)瀏覽器請求,顯示網(wǎng)頁的主要對象。每個需要在網(wǎng)頁上顯示的對象,都要直接或間接地繼承該對象,并且對象名一定要以“Bean”結(jié)尾。在瀏覽器端要調(diào)用HzBean對象的后代,可以十分直觀地在Web應(yīng)用URL后跟java類名即可,如“http://127.0.0.1:8080/test/com.coyizz.pfc.userBean.class”,顯示網(wǎng)頁和Java類文件對應(yīng)關(guān)系清晰,方便查找程序問題,不像Strus那樣,經(jīng)過xml配置文件的映射后,往往不知道網(wǎng)頁是那個Java類文件產(chǎn)生的了。
HzBean對象封裝了常用的數(shù)據(jù)處理事件,比如onShowMain是顯示主界面,onShoForm是顯示表單,onSave是保存表格數(shù)據(jù),onSubmit是提交數(shù)據(jù)等;HzBean還實現(xiàn)了權(quán)限控制功能:比如用setCanReadOnly(true)方法就可封鎖全部添加、修改、刪除數(shù)據(jù)請求,即使用戶直接通過url調(diào)用也無法改動數(shù)據(jù)。
HzBean可完成網(wǎng)頁間的數(shù)據(jù)的保持。通過getHoldParmStr(“name”)可以在取得url傳遞過來的name參數(shù)同時,將其保存到session變量中。
HzBean實現(xiàn)了多個數(shù)據(jù)訪問對象的事務(wù)處理,每個Bean對象中使用的數(shù)據(jù)庫連接全部記錄在一個connItems對象中,在HzBean處理數(shù)據(jù)更新的方法后,若捕獲到SQL異常,則在每個數(shù)據(jù)連接上進行回滾。
(三) SimpleTableDsBean和ComplexTableDsBean對象
這兩個對象利用HzBean、DataStore對象,實現(xiàn)了數(shù)據(jù)表的增加、刪除、修改、輸入數(shù)據(jù)有效性檢查、通用查詢和排序、數(shù)據(jù)表可選列打印輸出功能。其中SimpleTableDsBean一般用于記錄數(shù)在50條以下的數(shù)據(jù)表列數(shù)較少的數(shù)據(jù)表,而ComplexTableDsBean記錄數(shù)在50條以上列數(shù)較多的數(shù)據(jù)表。ComplexTableDsBean還適合處理比較復(fù)雜的數(shù)據(jù),如關(guān)聯(lián)數(shù)據(jù)列等。在最簡情況下,只要以下幾行代碼,就可實現(xiàn)數(shù)據(jù)表的增、刪、改、查、打:
public class TestBean extends ComplexTableDsBean {
public void onInit() {
regDs(new DataStore("dsMain", "select * from usera", getConnItem()));
}
}
在瀏覽器的地址欄輸入“http://127.0.0.1:8080/zhfz/com.coyizz.test.TestBean.calss”就可運行程序。
(四) Html*對象
在需要控制瀏覽器端的顯示細節(jié)時,大多數(shù)框架是用DrameWave等工具來設(shè)計jsp網(wǎng)頁來滿足需求,但jsp文件通常是一個Html、jsp標簽、java代碼混合的大雜繪,無法通過編譯器進行語法檢查,因此,本框架用以Html開始命名的一批對象封裝了常用的Html元素,如HtmlA封裝了“A”標簽,HtmlTable封裝了“TABLE”標簽。這些對象都繼承于HtmlElement,都用add方法來在本標欠內(nèi)添加其它Html標簽。比如要發(fā)送給瀏覽器內(nèi)容為:“<b ></b>”則對應(yīng)的Java代碼為“new HtmlB()”,如果要發(fā)送給瀏覽器內(nèi)容為:“<b ><font>Hellow</font></b>”則對應(yīng)的Java代碼為“new HtmlB().add(new HtmlFont(“Hellow”))”。一般情況下Html元素對象是屬于底層對象,只在需要精細控制顯示細節(jié)時才使用。這些Html元素要顯示在網(wǎng)頁上的方法是在HzBean后代對象中的onShowMain方法或onShowForm等方法中,用addSheet, addBar等方法顯示。這樣一來,用強類型的Java對象代替了弱類型的Html標簽,一切都在Java的控制之中。
當然,有時某些復(fù)雜的表格或只有Front和DrameWave才能寫好的頁面,可先用Front和DrameWave寫好純靜態(tài)的Html頁面,并在需要插入動態(tài)數(shù)據(jù)的地方預(yù)留標簽,在HzBean的后代對象中,用getHtmlFromFile方法將文件讀到內(nèi)存后,將動態(tài)數(shù)據(jù)插入其中,完成靜態(tài)頁面和動態(tài)數(shù)據(jù)的組合。
(五) DbConns對象
提供了通過JDBC驅(qū)動或應(yīng)用服務(wù)器數(shù)據(jù)庫連接池連接數(shù)據(jù)庫的方法,目前可連接Tomcat數(shù)據(jù)連接池、Oracle、Sybase Adaptive Server Anywhere、PostgreSQL數(shù)據(jù)庫。