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