ESP-iSYS平臺開發JAVA實時應用系統
實時數據庫系統作為現代信息系統的核心,是企業級應用的實時數據中樞,通過該系統,上層應用系統(如 ERP 系統),可以獲得良好的實時統計數據和實時統計信息的支撐。隨著SUPCON實時數據庫在現代企業信息化建設當中得到了越來越廣泛的應用,不但對WINDOWS平臺上主流編程語言提供了良好的支持,而且在ESP-iSYS4.0版本中為Java語言的開發提供了JRtdbc接口庫,該接口在Jdk1.5平臺上開發,其良好的面向對象設計與實現帶來了每秒訪問磁盤數據50000點以上的高性能,最大化的滿足了工業實時應用性能需求,在符合Java純面向對象的編程風格的同時,又打破了Java語言低效的束縛,以JRtdbc為橋梁,應用Java語言可以方便快速的開出各種優秀的實時應用。通過閱讀本文,讀者不僅能用JRtdbc進行java實時應用的開發,而且能夠充分體會到JRtdbc提供的簡單快速開發的優越性。
一 系統結構
整個JRtdbc的對象層次結構:
系統總體結構圖 -1
一 系統結構
整個JRtdbc的對象層次結構:
系統總體結構圖 -1
如上UML圖,實時數據庫當中的對象體系被明確的映射到了JRtdbc中,隱藏了實時數據庫的一些艱澀的概念,其中IConnectionPool為連接池,類似于jdbc的數據庫連接池,也是用JRtdbc進行開發時第一個要獲得的對象,可以通過其獲取實時數據庫連接IConnection,實時數據庫連接聚合了系統的四個核心工廠
名稱 |
功能 |
ITagFactory |
獲取位號/位號組實例。 |
IUserFactory |
添加刪除枚舉用戶/用戶組。 |
ITypeFactory |
添加刪除枚舉對象類型。 |
IRegion getRegionRoot() |
獲取對象樹根節點,遍歷實時數據庫對象樹 |
,通過工廠方法,可以得到實時數據庫的四大功能模塊,位號與位號組;用戶與用戶組;對象類型與權限體系;整個實時數據庫對象樹的訪問與操作;設計一致而且清晰,讓開發人員更容易理解與使用,下面逐一進行介紹并講解使用方法。
二 使用方法
Ø 實時數據庫連接的建立
二 使用方法
Ø 實時數據庫連接的建立
JRtdbc提供了連接池工廠PoolFactory,包含二個工廠方法:
IConnectionPool getPool() ; Œ
IConnectionPool getPool(int poolLength,int timeout) ;  |
其中工廠方法Œ用于構建默認參數配置的連接池實例,工廠方法允許用戶自定義連接池配置,參數poolLength定義為連接池連接上限,如果池中未達到上限,有新連接請求,直接新建連接放入池中返回,如已達上限,則償試重登錄其他用戶空閑連接,無空閑連接存在則進入阻塞狀態直到有連接釋放,從而保證了系統不會無限制地增加并發連接并且可以充分利用空閑連接。參數timeout定義為連接池中的連接空閑達到一個給定的毫秒數后就自動釋放連接,從而進一步節省實時數據庫連接資源。IConnectionPool 連接池接口,通過getConnection(String conStr)方法獲取一個與實時數據庫之間的連接IConnection。JRtdbc連接池經過專門設計,用戶只須獲得連接,像普通對象一樣調用,無須考慮底層連接狀態,完全由連接池托管,擺脫了像Jdbc那種獲得連接后還要時時不忘close()的那種煩惱,降低了使用復雜度。如何獲取實時數據庫連接?
//首先獲得連接池實例,能過連接字符串得到連接IConnection實例
IConnectionPool pool = PoolFactory.getPool();
IConnection conn = pool.getConnection( String conStr ) ; |
連接字符串格式:
host:192.168.0.171:5051;user=xxxxxx;password=xxxxxx;
其中各字段具體含義如下:
字段 |
含義 |
host |
為實時數據庫所在計算機的IP和端口,其中,前xxx.xxx.xxx.xxx指一個4段式IP地址,“:”后為實時數據庫的端口地址 |
user |
用戶名,有效內容為大小寫英文字母、下劃線 |
password |
密碼,有效內容為大小寫英文字母、數字、下劃線、連字符 |
如果建立連接成功,則返回一個有效的IConnection對象實例,如果在連接建立過程中存在異常情況,則拋出IOException類型的異常。
Ø 位號與位號組
位號是存儲在實時數據庫當中的數據點,對應底層控制系統的數據源,通過JRtdbc曝露給用戶的只是一個簡單的ITag對象,調用其方法即可對位號/位號組進行操作,工業現場的控制設備,在提供數值的同時,也提供了對數值質量的判斷,所以,實時數據庫中的數據是有質量碼的,通過質量碼,可以確定讀回的值是否可信、可用。在通常的應用中,驗證質量碼是缺省的,當出現錯誤質量碼的時候,位號讀取方法會拋出BadValueException異常,除了質量碼跟數值,位號值還包括了采集數據值的時間戳,因此把數值,質量碼,時間戳封裝進了一個TagValue,作為一個位號值。位號組則是以一組位號為單位的TagGroup實例,聯合讀取各位號的實時值或歷史值,以二維表的形式返回,以位號組中各位號名為列,支持以列名或者列索引獲取組內某位號的每行數據。通過位號工廠即可獲取位號與位號組對象,ITagFactory提供如下工廠方法:
名稱 |
功能 |
getTag(String name) |
獲取位號實例。 |
getTagGroup(String[] names) |
獲取位號組實例。 |
getTagGroup(String regex) |
獲取位號組實例。 |
(一) 讀位號實時值
通過位號工廠ITagFactory的getTag(tagNameStr)方法來獲得實際的位號實例。該方法將根據位號的具體屬性,返回虛位號或實位號的實體,而JRtdbc使用者并不需要關系其細節。具體的方法如下:
ITag t = conn.getTagFactory().getTag( tagName ) ; |
通過ITag實例,可以完成讀取實時值的操作。雖然每個位號均有其原生的數據類型,但ESP-iSYS在讀取時做了安全的類型轉換,也就是說,對于一個int類型的位號,仍然可以采用readFloat或readString方法,來獲得浮點值或字符串值。ITag接口提供了針對不同數據類型的方法,如下:
方法 |
功能 |
readBoolean |
讀取boolean類型的值 |
readDouble |
讀取double類型的值 |
readFloat |
讀取float類型的值 |
readInt |
讀取int類型的值 |
readLong |
讀取long類型的值 |
readShort |
讀取short類型的值 |
readString |
讀取String類型的值 |
這些方法均會返回實時數據庫中位號的最新值,通過TagValue位號值封裝類的getTimeStamp方法,可以獲取到該位號值對應的時間戳。典型的使用代碼如下:
ITag t = conn.getTagFactory().getTag( tagName ) ;
TagValue v = t.readValue() ;
Date timeStamp = v.getTimeStamp() ;
SimpleDateFormat sft = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss " );
String timeString = sft.format( timeStamp); |
如果兩種數據類型間不能正確轉換時,readXXXX方法將會拋出TypeCastFailedException異常。
(二) 寫位號實時值
寫實時值的方法和讀取實時值是對應的,寫位號同樣可以采用不同的類型寫入,其列表如下:
方法 |
功能 |
writeBoolean |
寫boolean類型的值 |
writeDouble |
寫double類型的值 |
writeFloat |
寫float類型的值 |
writeInt |
寫int類型的值 |
writeLong |
寫long類型的值 |
writeShort |
寫short類型的值 |
writeString |
寫String類型的值 |
而JRtdbc會自動為該寫操作分配時間戳和打上正確的質量碼。
(三) 讀位號歷史數據
通過ITag實例,可以完成讀取實時數據庫內存與磁盤歷史數據 ITag接口提供了如下方法:
(三) 讀位號歷史數據
通過ITag實例,可以完成讀取實時數據庫內存與磁盤歷史數據 ITag接口提供了如下方法:
方法 |
功能 |
readAllMemHisValue() |
讀取全部內存歷史值 |
readMemHisPointValue(Date p) |
讀取某時刻磁盤歷史值 |
readMemHisValue(Date b,Date e) |
讀取某個時間段的內存歷史值 |
readMemHisValue(Date b,Date e,long i) |
采樣讀取某個時間段的內存歷史值 |
readDiskHisPointValue(Date p) |
讀取某時刻磁盤歷史值 |
readDiskHisValue(Date b,Date e) |
讀取某個時間段的磁盤歷史值 |
readDiskHisValue(Date b,Date e,long i) |
采樣讀取某個時間段的磁盤歷史值 |
readHisValue(Date b,Date e,long i) |
自動區分內存或磁盤歷史 |
采樣,即為以一定的時間間隔去讀位號值,如果某時刻無值存在,以NULL填充,因此采樣讀歷史數據,讀出來的是一個以相等時間間隔的值序列。不采樣純粹讀出時間條件范圍內的所有位號值,典型的讀位號歷史值的代碼如下:
ITag t = tf.getTag(“TT3502”) ;
//讀取全部內存歷史
ArrayList<TagValue> vs = t.readAllMemHisValue() ;
//讀取時間段的磁盤歷史,begin,end 起始與結束時間,inter采樣間隔,無值時以NULL填充進容器。
ArrayList<TagValue> vs = t.readDiskHisValue( begin,end,inter) |
(四) 讀取位號組值
讀位號組的接口方法與單個位號是一樣的,統一接口,易于使用,首先以一組位號名為參數,通過位號工廠得到位號組對象,調用讀取方法,與單個位號不同的只是位號組返回的是以位號名為列的二維表TagDataTable形式的結構,與Jdbc的Record類似,可以遍歷表中的所有行,通過位號名或者列索引獲得組內某個位號的值,因此Java開發人員可以像處理Jdbc的Record一樣處理位號組返回的數據,典型的使用代碼如下:
String[] names = {“TT3501”,”TT3502”,”TT3503”}
ITagFactory tf = conn.getTagFactory() ;
ITagGroup tgrp = tf.getTagGroup(names) ;
//讀實時值
TagDataRow r = tgrp.readValue() ;
TagValue v = r.getValue(“TT3501”) ;
//讀歷史值
TagDataTable t = tgrp.readDiskHisValue(begin,end,interval);
For(TagDataRow row : t.getRows()){
TagValue v = row.getValue(0);//以索引獲得
System.out.println( v.getTimeStamp() ) ;//打印獲取時間。
} |
通過JRtdbc操作實時數據庫位號與位號組是如此的方便與直觀,用戶完全感覺不到正在操作的是深奧的實時數據庫。
Ø 用戶與用戶組
登錄實時數據庫的用戶,以一個用戶對象IUser存儲在實時數據內部,當然還有其隸屬的用戶組IUserGroup,用戶也可以在權限范圍內增加刪除用戶,為用戶分配權限,分配用戶組,所有操作類似于平常操作系統的用戶用戶組結構,從系統UML圖可以看出,IUser與IUserGroup派生于IUserBase,IUserBase抽取出了公共的對權限訪問列表操作的方法。通過IConnection獲得IUserFacotry用戶工廠,該工廠提供了如下工廠方法:
方法 |
功能 |
addUser(UserAttribute attr) |
添加用戶 |
addUserGroup(UserGroupAttribute attr) |
添加用戶組 |
delUser( String name ) |
刪除用戶 |
delUserGroup(String name) |
刪除用戶組 |
getUsers() |
枚舉用戶 |
getUserGroups() |
枚舉用戶組 |
(一) 添加刪除枚舉用戶/用戶組
添加用戶/用戶組一般操作相當簡單,取得連接后,得到用戶工廠,建立用戶或用戶組屬性對象,調用工廠方法addUser與addUserGroup即可,刪除用戶/用戶組只須以名稱為參數調用delUser/delUserGroup方法,典型代碼如下:
IUserFacotry uf = conn.getUserFacotry() ;
//添加用戶
IUser u = uf.addUser( new UserAttribute(“TESTUSER”)) ;
Boolean b = uf.delUser(“TESTUSER”) ; //刪除用戶
//添加用戶組
IUserGroup grp = uf.addUserGroup( new UserGroup(“admin”)) ;
Boolean b = uf.delUserGroup(“admin”);//刪除用戶組
//枚舉用戶用戶組
ArrayList<IUser> users = uf.getUsers() ;
ArrayList<IUserGroup> grps = uf.getGroups() ; |
(二) 驗證用戶權限
實時數據庫有完整的安全機制,每個對象類型都有一系列的權限項存在,只有在權限允許的情況下,用戶才能對實時數據庫中的對象進行操作,IUser接口提供了簡單的接口來驗證用戶是否具有操作實時數據庫對象的權限,比如用戶是否有權刪除一個位號,刪除位號這個權限項被定義在位號對象類型內,典型代碼如下:
IUser u = new User(conn,”admin”) ;
String path = “.\水化車間\TT3502”;//某車間下的一個位號
String right = “刪除位號” ;
Boolean b = u. authenticate(path,right) ;
If( b ) { ……} else { System.out.println(“用戶無權限刪除該位號”);} |
(三) 用戶/用戶組權限訪問列表
用戶/用戶組擁有一個允許訪問列表和一個拒絕訪問列表,這二個列表描述的是在對象類型當中定義的權限項是否具有,JRtdbc使用者可以通過IUser與IUserGroup提供的接口獲得訪問列表ArrayList<ACEHeader>,ACEHeader類封裝了對象路徑與之對應的權限名稱,并支持增加或刪除列表項,下面以IUser為例,給出典型代碼:
IUser u = new User(conn,”admin”) ;
String path = “.\水化車間\TT3502”;//某車間下的一個位號
String right = “刪除位號” ;
Boolean b = u. removeACE(path,right) ;//刪除了用戶對位號的刪除權限
IUser u2 = new User(conn,”test”) ;
Boolean b = u2.addACE(path,right) ;//用戶具有了刪除權限
//枚舉
ArrayList<ACEHeader> aces = u.getACList() ;
ArrayList<ACEHeader> dcls = u.getDCList() ; |
Ø 對象類型與權限體系
實時數據據庫當中的對象都有其對應的對象類型,例如,位號就是一個對象樹上的特殊類型。對象類型都派生于IElementType,該接口提供了如添加自定義屬性描述、添加權限項等功能。類型工廠ITypeFactory提供了下列工廠方法:
名稱 |
功能 |
addType(ElementTypeAttribute attr) |
添加對象類型 |
delType(String typename) |
刪除對象類型 |
getTypes() |
枚舉對象類型 |
獲取連接,得到類型工廠后,即可添加刪除對象類型,
(一) 添加刪除對象類型
在實時數據中添加對象類型非常的簡單,比如在實時數據庫當中添加一種報表這樣的一種類型,可先獲得類型工廠,然后建立新類型的屬性對象TypeAttribute其中只有類型名必須指定,調用addType添加,刪除類型只須調用delType,并以對象類型名稱為參數,典型代碼如下:
ITypeFactory typef = conn.getTypeFacotry() ;
TypeAttribute attr = new TypeAttribute(“報表”) ;
IElementType type = Typef.addType( attr ) ;//添加對象類型。
Boolean b = typef.delType(“報表”) ;//刪除對象類型
ArrayList<IElementType> types = typef.getTypes() ;//枚舉 |
(二) 添加自定義屬性描述
在實時數據庫當中,可以為實時數據庫對象添加自定義屬性,存儲在對象屬性ElementAttribute的Hashtable中,實時數據庫為驗證自定義添加的屬性正確性,用戶必須提供自定義屬性的描述信息,為簡化操作,JRtdbc把描述信息抽象成TypeBase,具體描述類派生于此基類,提供了自定義屬性的相關約束條,如最大值,最小值,值類型等,目前支持三種自定義類型的添加,Int32Type整型,DoubleType浮點型和StringType字符串型。比如現有report1這么一個報表對象,用戶要為其添加一個名為path的路徑屬性,值為C:\report,則首先應該獲取報表對象類型對象,在類型對象當中添加這個自定義屬性的描述信息,如自定義屬性名應該為path,類型為String,最大長度為100等信息,這樣才能正確的為具體報表對象添加進這個自定義屬性,典型代碼如下:
StringType t = new StringType( path,true,”c:\report”) ;
t.setMaxLength(100);
Boolean b = type.addAttribute( t ) ; |
(三) 添加權限項
實時數據庫中每種對象類型都有其權限項列表,比如報表這個對象類型,它有完全控制、讀報表,寫報表、添加報表、刪除報表等權限項,用戶可以通過接口對權限項進行添加或刪除,首先新建一個權限屬性對象,設置權限項名稱等信息,獲得對象類型對象,調用addRight添加即可,刪除操作直接以權限名為參數,調用delRight即可,典型代碼如下:
RightAttribute attr = new RightAttribute(“報表完全控制”) ;
Boolean b = type.addRight( attr ) ;//添加權限項
Boolean b = type.delRight( rightName ) ;//刪除權限項 |
Ø 對象樹的訪問與操作
為簡化在ESP-iSYS上進行Java開發,ESP-iSYS內部以企業資源樹的形式來組織對象,位號、報表、區域、流程圖等都是樹上的對象,其中區域里面可以有對象也可以包含子區域,就像企業里面的組織結構,比如一個部門里有許多對象,也有許多車間,車間里又有位號之類的對象可能還有二級車間,這里部門和車間或二級車間在實時數據庫里就表示為區域對象。對象樹上的所有對象都派生于IElement,使得開發人員可以統一對待所有對象,對象屬性有預定義屬性和自定義屬性,預定義屬性以成員變量的形式存于對象實例中,自定義屬性存放于Hashtable中,須先以TypeBase在對象類型中添加自定義屬性描述后,才能為對象正確添加自定義屬性,目前支持浮點型、整型、字符串型三種類型,如圖:
可以通過IConnection方法getRegionRoot()獲取對象樹的根區域節點IRegion,從而完全遍歷與訪問各類對象。
(一) 添加對象
連接建立后,可通過IConnection的getRegionRoot方法獲得對象樹根結點,遍歷到欲添加對象的區域節點,然后以對象屬性ElementAttribute為參數,對象屬性封裝類已提供了大部份默認值,用戶可只對必要字段進行賦值即可構建屬性對象,避免了對大串屬性一一賦值的煩瑣,簡化開發,再調用addElement(ElementAttribute attr)方法添加對象,相同方法添加位號或其它對象,典型代碼如下:
IRegion root = conn.getRegionRoot() ;
RealTagAttribute realTagAttr = new RealTagAttribute(“TT”);
ITag t = root.addTag( realTagAttr ) ;添加位號
//IElement e = root.addElement(ElementAttribute attr) ; |
(二) 添加自定義屬性
遍歷對象樹獲取對象實例,調用getElementAttribute方法獲取對象屬性,調用addCustAttrbute(name,value)添加自定義屬性,如在對象類型屬性內未添加自定義屬性描述,或者與描述信息不符,則拋出InValidAtrributeException,典型代碼如下:
ITagFactory tf = conn.getTagFactory() ;
ITag t = tf.getTag( “TT3502” ) ;
ElementAttribute ta = t.getElementAttribute() ;
Ta.addCustAttr(“CustAttr”,”CustAttrValue”) ; |
Ø 異常處理模塊
JRtdbc有一套完整的異常體系,所有JRtdbc自有的異常全部派生于RtdbcException,含義明確,對拋出原因一目了然,并且大部份定義為未檢異常,因為這些異常拋出后,用戶無力恢復,未檢異常不用讓用戶必須Try,Catch,這樣減少代碼量,降低開發復雜度。具體如下:
名稱 |
含義 |
RtdbException |
實時數據庫異常基類 |
BadValueException |
位號值質量碼異常,讀到壞值時拋出 |
InValidPackageException |
包解析錯誤時拋出 |
InValidAttributeException |
添加自定義屬性時,屬性無效時拋出 三 實例展示 下面是一個使用JRtdbc開發的一個讀取位號實時值與歷史值的完整示例,緊湊簡短的幾句Java代碼即可讀取到工業自動化領域當中的實時信息。 四 總結 以上詳細介紹了ESP-iSYS平臺Java接口的架構與使用步驟,“一個連接,四個工廠”通過短短的數行Java代碼即能揭開實時數據庫的神秘面紗,讓開發人員暢游整個實時數據庫,Java愛好者們可以盡情享受用Java快速開發實時應用所帶來的樂趣。浙江中控軟件技術有限公司在今后會不斷的對其進行維護和升級,并對開發者提供良好的技術支持,共同努力在J2EE平臺上開發出更多更優秀的實時應用。 |
文章版權歸西部工控xbgk所有,未經許可不得轉載。
下一篇:實時數據庫性能指標概述