• <tr id="yyy80"></tr>
  • <sup id="yyy80"></sup>
  • <tfoot id="yyy80"><noscript id="yyy80"></noscript></tfoot>
  • 99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看 ?

    基于Java的遠程數(shù)據(jù)驅動設計實現(xiàn)

    2009-12-25 08:53:48蔣仕勇
    金融經(jīng)濟 2009年11期

    蔣仕勇

    摘要:提出了在Client/Server架構下,根據(jù)數(shù)據(jù)庫的數(shù)據(jù)變化來驅動遠程客戶端應用程序的設計方案;該方案基于Java 、Socket、JNI、IPC以及Windows消息機制等技術,克服了傳統(tǒng)對數(shù)據(jù)庫定時掃描的缺點,文章最后給出了基于PowerBuilder客戶端應用程序的一個具體實現(xiàn)。

    關鍵詞:Socket IPC;JNI;Windows消息機制;Java

    1、問題的提出

    當基于集中式Client/Server架構的應用系統(tǒng)需要根據(jù)數(shù)據(jù)庫中數(shù)據(jù)的變化情況來決定是否啟動相應的處理程序時,以往采用了由應用程序定時對數(shù)據(jù)庫進行掃描的方式。這種定時的由客戶端對數(shù)據(jù)庫服務器進行掃描的方法有如下缺點:

    ①造成服務器的負荷增大,特別是當定時掃描在數(shù)據(jù)操作頻繁時進行,還造成服務器性能下降;

    ②網(wǎng)絡流量增多;

    ③定時掃描并不能實時的處理隨機出現(xiàn)的數(shù)據(jù)變化,造成處理滯后。特別是對于數(shù)據(jù)更新無規(guī)律的應用,時間間隔的設定更是困難,因為時間間隔設定過大,會降低數(shù)據(jù)的實時性,時間間隔設定過小,又增加了網(wǎng)絡負擔和服務器負荷。

    但目前主流數(shù)據(jù)庫都沒有提供當數(shù)據(jù)庫數(shù)據(jù)發(fā)生變化時及時通知客戶端應用的直接方法。

    2、解決方案的設計思想

    針對以上問題,我們提出了一種當數(shù)據(jù)庫信息發(fā)生變化時能及時通知遠程客戶端應用程序的解決方案,克服了由遠程客戶端應用程序定時掃描數(shù)據(jù)庫的弊端。該解決方案的核心思想是:利用數(shù)據(jù)庫的觸發(fā)器機制,在數(shù)據(jù)發(fā)生變化后調用存儲過程,然后在存儲過程中調用Java程序,Java程序實現(xiàn)Socket通信,在客戶端利用消息機制將數(shù)據(jù)變化的消息通知應用程序,應用程序收到消息后觸發(fā)相應事件執(zhí)行相應操作,如圖1。

    2.1數(shù)據(jù)庫的觸發(fā)機制

    大型關系數(shù)據(jù)庫都提供了觸發(fā)器(Trigger)機制,ORACLE數(shù)據(jù)庫觸發(fā)器定義了當一些數(shù)據(jù)庫相關事件發(fā)生時數(shù)據(jù)庫應采取的動作。觸發(fā)器可用于完整性控制,審計表中的數(shù)據(jù)變化或者監(jiān)控數(shù)據(jù)的變動等。觸發(fā)器體由PL/SQL代碼塊組成。

    2.2由存儲過程調用Java類訪問外部資源

    由于整個應用系統(tǒng)的整體架構是基于集中式Client/Server模式,客戶端編程語言是非Java的,Oracle數(shù)據(jù)庫中沒有提供直接訪問外部資源的機制,但提供了對Java的支持,可利用LoadJava方法,將Java程序裝載到Oracle數(shù)據(jù)庫中作為數(shù)據(jù)對象供存儲過程調用,利用Java程序訪問外部資源。

    2.3通過Java程序實現(xiàn)服務器與遠程客戶端的Socket通訊

    當數(shù)據(jù)變化達到一定條件后,Oracle通過Socket通知遠程客戶端,遠程客戶端的Socket服務程序通過JNI調用C語言的動態(tài)鏈接庫,獲取本地非Java應用程序的進程信息,利用Windows的消息機制。將Oracle的控制信息傳入非Java應用程序,由非Java應用程序響應消息,觸發(fā)相應的事件作出相應的處理,從而達到數(shù)據(jù)驅動遠程客戶端應用的目的。

    3、關鍵技術

    3.1基于Java的Socket通訊

    利用TCP/IP協(xié)議在客戶機和服務器之間建立Socket連接是網(wǎng)絡通訊的一種模式,這種通訊模式首先分別在客戶機和服務器端創(chuàng)建Socket,并建立一個可靠的Socket連接,然后雙方在這個Socket連接上進行數(shù)據(jù)交互。使用Socket進行遠程通訊的方式有3種:

    ① 字節(jié)流套接字(StreamSocket):TCP/IP協(xié)議族中TCP協(xié)議使用此類接口,它提供面向連接的 (建立虛電路 )、無差錯的、發(fā)送順序一致的、包長度不限和非重復的網(wǎng)絡信包傳輸;

    ② 數(shù)據(jù)報套接字(DatagramSocket):TCP/IP協(xié)議族中的UDP(User Datagram Protocol)協(xié)議使用此類接口,它是無連接的服務,以獨立的信包進行網(wǎng)絡傳輸,信包最大長度為 32KB,傳輸不保證順序性、可靠性和無重復性,通常用于單個報文傳輸或可靠性要求不高的場合;

    ③ 原始數(shù)據(jù)包套接字(Raw Socket):提供對網(wǎng)絡下層通信協(xié)議 (如IP協(xié)議 )的直接訪問,一般不是提供給普通用戶的。主要用于開發(fā)新的協(xié)議或用于提取協(xié)議較隱蔽的功能。

    其中字節(jié)流套接字是最常用的套接字類型。在Java語言中利用java.net包中的Socket類和ServerSocket類創(chuàng)建客戶端和服務端Socket。在服務端采用了多線程技術使得服務端的Socket能同時為多個客戶端請求服務,極大的提高了運行效率。

    3.2 JNI調用

    由于客戶端應用程序采用的開發(fā)工具不同,例如PowerBuilder、VisualBasic等,要獲取正在運行中的非Java應用程序的信息,由于Java又沒有提供諸如指針等概念,因此借助C語言來獲取應用程序的進程信息、以及利用windows的消息機制向非Java應用程序傳遞消息,來實現(xiàn)對非Java應用程序的控制,而Java調用C語言需要用到JNI接口標準。JNI(Java Native Interface)是Java與其他編程語言的集成編程接口,又稱為本地方法接口。它使運行于Java虛擬機上的Java代碼與其它語言編寫的庫和應用程序能夠互相調用。JNI允許本地方法建立、使用和更新Java對象,調用Java方法和引用Java類。JNI也允許Java代碼調用C、C++等語言編寫的程序和庫。Invocation API(JNI 的一部分)可以用來將 Java 虛擬機(JVM)嵌入到本機應用程序中,從而允許程序員從本機代碼內部調用 Java 代碼。由于在運行環(huán)境(Runtime)下,只有動態(tài)鏈接庫或者共享對象庫能夠被Java虛擬機引導,而靜態(tài)庫和壓縮庫不能在運行環(huán)境下被調用。所以在Java中調用其它編程語言生成的代碼是通過調用動態(tài)鏈接庫或者共享對象庫的方式來實現(xiàn)的,而在其它語言中調用Java對象是通過引用指向Java對象的指針來實現(xiàn)的。

    3.3 消息機制

    Windows消息提供了應用程序與應用程序之間、應用程序與Windows系統(tǒng)之間進行通訊的手段[ 3]。應用程序要實現(xiàn)的功能由消息來觸發(fā),并靠對消息的響應和處理來完成。Windows系統(tǒng)中有兩種消息隊列,一種是系統(tǒng)消息隊列,另一種是應用程序消息隊列。計算機的所有輸入設備由 Windows監(jiān)控,當一個事件發(fā)生時,Windows先將輸入的消息放入系統(tǒng)消息隊列中,然后再將輸入的消息拷貝到相應的應用程序隊列中,應用程序中的消息循環(huán)從它的消息隊列中檢索每一個消息并發(fā)送給相應的窗口函數(shù)中。一個事件的發(fā)生,到達處理它的窗口函數(shù)必須經(jīng)歷上述過程。消息隊列中消息的結構(MSG)為:

    typedef struct tagMSG{

    HWND hwnd;

    UINT message;

    WPARAM wParam;

    LPARAM lParam;

    DWORD time;

    POINT pt;

    }MSG;

    其中第一個成員變量是用以標識接收消息的窗口的窗口句柄;第二個參數(shù)便是消息標識號,如WM_PAINT;第三個和第四個參數(shù)的具體意義同message值有關,均為消息參數(shù)。前四個參數(shù)是非常重要和經(jīng)常用到的,至于后兩個參數(shù)則分別表示郵寄消息的時間和光標位置(屏幕坐標)。把消息傳送到應用程序有兩種方法:一種是由系統(tǒng)將消息“郵寄(post)”到應用程序的“消息隊列”這是“進隊消息”Win32 API有對應的函數(shù):PostMessage(),此函數(shù)不等待該消息處理完就返回;而另一種則是由系統(tǒng)在直接調用窗口函數(shù)時將消息"發(fā)送(send)"給應用程序的窗口函數(shù),屬于“不進隊消息”對應的函數(shù)是SendMessage()其必須等待該消息處理完后方可返回。

    Windows 應用程序創(chuàng)建的每個窗口都在系統(tǒng)核心注冊一個相應的窗口函數(shù),窗口函數(shù)程序代碼形式上是一個巨大的switch 語句,用以處理由消息循環(huán)發(fā)送到該窗口的消息,窗口函數(shù)由Windows 采用消息驅動的形式直接調用,而不是由應用程序顯示調用的,窗口函數(shù)處理完消息后又將控制權返回給Windows。

    4、解決方案的實現(xiàn)

    4.1 基于Java的Socket通訊服務

    public class MonitorSocketServer {

    ServerSocket s = new ServerSocket(PORT);

    try{

    while(true){

    Socket socket = s.accept();

    try{

    new ServerOneJabber(socket);

    } catch(IOException e){

    socket.close();

    }

    }

    以上是服務端Socket的創(chuàng)建過程,它主要是負責對指定的端口進行監(jiān)聽,如果有請求進來則響應,調用相應的處理類。

    4.2客戶端程序

    這是Socket客戶端的創(chuàng)建過程,它主要是與Socket服務端進行通訊。我們的應用是要根據(jù)Oracle數(shù)據(jù)庫中數(shù)據(jù)變化而進行實時的觸發(fā)通訊,因此在用戶修改了數(shù)據(jù)提交數(shù)據(jù)庫后,由數(shù)據(jù)庫觸發(fā)器直接調用Socket通知遠程服務端啟動。Oracle的觸發(fā)器是不能訪問Java代碼的,只能通過存儲過程來訪問,而存儲過程要使用Java代碼只能通過Oracle提供的工具LoadJava將客戶端MonitorSocketClient裝載到Oracle數(shù)據(jù)庫中,作為一個數(shù)據(jù)對象供Oracle調用:

    LoadJava-u scott/tiger-r-v-f c:/MonitorSocketClient.java

    4.3存儲過程調用客戶端程序

    CREATE OR REPLACE PROCEDURE Call_Monitor(ip varchar2,port varchar2,message varchar2)

    as language java

    name ' MonitorSocketClient.main(java.lang.string[])';

    接下來,Socket服務端需要根據(jù)傳入的參數(shù)對客戶端進行控制:由于Java沒有指針等概念,無法獲得我們的應用程序進程號,因此采用JNI編程,調用C++函數(shù)來獲取程序進程,操作應用程序進行相應的處理:

    public class ControlClientApplication{

    public native long getProcessInfo(String);

    public native int dealRemoteControl(String applicationName , );

    public static void main (String[ ] args){

    System.loadLibray(“ControlObject”);

    ControlObject CObject = new ControlObject;

    long ProcessId = getProcessInfo(args[ 0]);

    編譯后使用javah將ControlClientApplication.class文件編譯成為一個C++的頭文件(ControlClientApplication.h)。這個工具被設計成用來創(chuàng)建頭文件,該頭文件為在java 源代碼文件中所找到的每個native方法定義 C 風格的函數(shù)。我們用C++編寫一個實現(xiàn):

    #include “ControlClientApplication.h”

    #include

    #include

    HANDLE hProcessSnapShot = NULL;

    PROCESSENTRY32 pe32 = {0};

    int iLen;

    CString strSpace = “”;

    hProcessSnapShot = (HANDLE)CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

    pe32.dwSize = sizeof(PROCESSENTRY32);

    Process32First(hProcessSnapShot,&pe32);

    do {

    strSpace = “”;

    strAppName = pe32.szExeFile;

    for(iLen = 0; iLen<60-strAppName.GetLength(); iLen++)

    strSpace = strSpace + “”;

    strAppName = strAppName + strSpace;

    } while(Process32Next(hProcessSnapShot,&pe32));

    CloseHandle(hProcessSnapShot);

    在Powerbuilder的主界面窗口中加入刷新事件(pbvm_paint)的處理方法:

    Choose Case Messae.LongParm

    Case 0

    Case 1

    Open(w_netwatch)

    End Choose

    5、結論

    以上方法作者已在開發(fā)的財政橫向網(wǎng)信息系統(tǒng)調用財政集中支付系統(tǒng)中應用,證明是有效的。但由于采用了Windows的消息機制、動態(tài)鏈接庫,因此整個解決方案必須基于Windows平臺,跨平臺性能不佳。

    參考文獻

    1、Tom Portfolio.Java Stored Procedures Developers Guide.Oracle Corporation.1999

    2、Bruce Eckel,Thinking in Java, president, MindView, Inc.2002

    3、劉丹華,黃道君.利用套接字開發(fā)網(wǎng)絡通信程序.微機發(fā)展.2003年1月

    (作者單位:湖南省財政廳)

    尉犁县| 邵阳县| 长泰县| 民和| 祥云县| 明溪县| 利川市| 湛江市| 土默特右旗| 铜鼓县| 凉城县| 西青区| 苍山县| 东乡| 巴林左旗| 开平市| 辛集市| 九龙县| 枝江市| 宜君县| 商南县| 山阳县| 溆浦县| 四会市| 蒙山县| 犍为县| 赞皇县| 彰化县| 唐河县| 贡觉县| 津南区| 大庆市| 华阴市| 个旧市| 巴塘县| 炉霍县| 沛县| 桃园市| 新巴尔虎右旗| 资讯 | 阳城县|