1. 程式人生 > >Oracle資料庫觸發器如何呼叫Java程式實現Openfire訊息推送

Oracle資料庫觸發器如何呼叫Java程式實現Openfire訊息推送

寫在前面,要想實現整個過程的成功執行請先準備以下檔案:

1. 登陸Openfire服務端以及Spark客戶端相關程式(openfire_4_0_1.exe、spark_2_7_6.exe)

2. 連線Openfire和Oracle相關的jar包(presence.jar、smack.jar、smackx-debug.jar、smackx.jar、ojdbc.jar) 

Step1:安裝Openfire服務端並配置資料庫連線,配置參考《Openfire伺服器安裝與配置教程

Step2:在Eclipse等IDE開發工具中編寫Java Application程式並匯入smack的3個jar包

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.MessageEventManager;

/**
 * Openfire服務端傳送訊息到指定客戶端賬號
 * 
 * @author xiaolj
 * @date 2016-01-05
 */
public class SendMsgFunc {

  public static void main(String args[]) {

       //引數1:openfire服務端建立的賬號(傳送訊息前請先用Spark客戶端登入10000賬號)
       //引數2:需要傳送的訊息內容
       int status = sendImMessage("10000", "主減裝配一線裝置異常,請及時處理!【反饋人:張三;聯絡電話:13883638681】");
       System.err.println(status);
  }

  /**
   * 根據返回狀態確認是否傳送成功
   */
   public static int sendImMessage(String userid, String content) {
   
        System.out.println("開始執行訊息推送");
        String ip = "127.0.0.1";//服務裡IP或伺服器對應主機名
        String port = "5222";// 客戶端PID預設都是5222
        String domain = "server-pc";//伺服器主機名或IP地址
        String adminid = "admin";//固定不變發起人(openfire伺服器預設最高階許可權賬戶)
        String pwd = "admin";//固定不變(openfire伺服器預設最高階許可權賬戶密碼)
        int on_line = 0;// 是否線上

        try {

            // 判斷使用者是否線上:--若出現error設定外掛線上狀態任何許可權訪問
            String url = "http://127.0.0.1:9090/plugins/presence/status?jid="+ userid + "@server-pc&type=xml";
            on_line = judgUserOnline(url);

            // 建立連線傳送客戶端訊息
            XMPPConnection con = new XMPPConnection(ip, Integer.parseInt(port));
            con.login(adminid, pwd);
            Chat chat = con.createChat(userid + "@" + domain);
            Message msg = chat.createMessage();
            msg.setSubject("系統通知訊息");
            msg.setBody(content);
            MessageEventManager.addNotificationsRequests(msg, true, true, true, true);
            chat.sendMessage(msg);
            System.err.println("執行訊息推送結束");
            // 關閉連線
            con.close();
        } catch (Exception e) {
            System.err.println("執行訊息推送錯誤");
            System.out.println("〖integration〗傳送訊息到OpenFire錯誤。");
            e.printStackTrace();
            return 3;
       }
       return on_line;
   }

   /********** 【判斷當前使用者是否線上】 ***********/
   public static int judgUserOnline(String url) {

       // 預設不線上
       int onLineState = 0;
       try {
           URL oUrl = new URL(url);
           URLConnection oConn = oUrl.openConnection();
           InputStream inputStream = oConn.getInputStream();
           if (oConn != null) {

             // 讀取返回值:openfire伺服器需先安裝外掛並指定任意許可權,重啟伺服器
             BufferedReader oIn = new BufferedReader(new InputStreamReader(inputStream));
             if (null != oIn) {
                String strFlag = oIn.readLine();
                oIn.close();
                if (strFlag.indexOf("type=\"error\"") >= 0) {// 訪問許可權不足:openfire使用者不存在
                   onLineState = -1;
                } else if (strFlag.indexOf("type=\"unavailable\"") >= 0) {// 使用者不線上
                   onLineState = 0;
                } else if (strFlag.indexOf("priority") >= 0 || strFlag.indexOf("id=\"") >= 0) {// 表示使用者線上
                   onLineState = 1;
                } else {
                   onLineState = 2; // 伺服器發生異常
                }
             }
          }
      } catch (Exception e) {
          System.err.println("執行訊息推送驗證錯誤");
          e.printStackTrace();
          return 4;
      }
      System.err.println("執行訊息推送驗證結束");
      return onLineState;
   }
}

Step3:將Java程式以及執行過程中的jar包load到Oracle資料庫

    3.1)  將呼叫openfire相關jar包匯入Oracle資料庫:

loadjava -r -f -o -user 使用者/密碼@IP:埠/例項名 D:\smack.jar
loadjava -r -f -o -user 使用者/密碼@IP:埠/例項名 D:\smackx.jar
loadjava -r -f -o -user 使用者/密碼@IP:埠/例項名 D:\smackx-debug.jar

    3.2)  在Oracle中新建一個SQL視窗建立Java source程式然後將以上Java程式碼拷貝其中並編譯(原始檔名自定義)

create or replace and compile java source named "OpenfireClient_Func" as
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.MessageEventManager;

/**
 * Openfire服務端傳送訊息到指定客戶端賬號
 * 
 * @author xiaolj
 * @date 2016-01-05
 */
public class SendMsgFunc {

  public static void main(String args[]) {

       //引數1:openfire服務端建立的賬號(傳送訊息前請先用Spark客戶端登入10000賬號)
       //引數2:需要傳送的訊息內容
       int status = sendImMessage("10000", "主減裝配一線裝置異常,請及時處理!【反饋人:張三;聯絡電話:13883638681】");
       System.err.println(status);
  }

  /**
   * 根據返回狀態確認是否傳送成功
   */
   public static int sendImMessage(String userid, String content) {
   
        System.out.println("開始執行訊息推送");
        String ip = "127.0.0.1";//服務裡IP或伺服器對應主機名
        String port = "5222";// 客戶端PID預設都是5222
        String domain = "server-pc";//伺服器主機名或IP地址
        String adminid = "admin";//固定不變發起人(openfire伺服器預設最高階許可權賬戶)
        String pwd = "admin";//固定不變(openfire伺服器預設最高階許可權賬戶密碼)
        int on_line = 0;// 是否線上

        try {

            // 判斷使用者是否線上:--若出現error設定外掛線上狀態任何許可權訪問
            String url = "http://127.0.0.1:9090/plugins/presence/status?jid="+ userid + "@server-pc&type=xml";
            on_line = judgUserOnline(url);

            // 建立連線傳送客戶端訊息
            XMPPConnection con = new XMPPConnection(ip, Integer.parseInt(port));
            con.login(adminid, pwd);
            Chat chat = con.createChat(userid + "@" + domain);
            Message msg = chat.createMessage();
            msg.setSubject("系統通知訊息");
            msg.setBody(content);
            MessageEventManager.addNotificationsRequests(msg, true, true, true, true);
            chat.sendMessage(msg);
            System.err.println("執行訊息推送結束");
            // 關閉連線
            con.close();
        } catch (Exception e) {
            System.err.println("執行訊息推送錯誤");
            System.out.println("〖integration〗傳送訊息到OpenFire錯誤。");
            e.printStackTrace();
            return 3;
       }
       return on_line;
   }

   /********** 【判斷當前使用者是否線上】 ***********/
   public static int judgUserOnline(String url) {

       // 預設不線上
       int onLineState = 0;
       try {
           URL oUrl = new URL(url);
           URLConnection oConn = oUrl.openConnection();
           InputStream inputStream = oConn.getInputStream();
           if (oConn != null) {

             // 讀取返回值:openfire伺服器需先安裝外掛並指定任意許可權,重啟伺服器
             BufferedReader oIn = new BufferedReader(new InputStreamReader(inputStream));
             if (null != oIn) {
                String strFlag = oIn.readLine();
                oIn.close();
                if (strFlag.indexOf("type=\"error\"") >= 0) {// 訪問許可權不足:openfire使用者不存在
                   onLineState = -1;
                } else if (strFlag.indexOf("type=\"unavailable\"") >= 0) {// 使用者不線上
                   onLineState = 0;
                } else if (strFlag.indexOf("priority") >= 0 || strFlag.indexOf("id=\"") >= 0) {// 表示使用者線上
                   onLineState = 1;
                } else {
                   onLineState = 2; // 伺服器發生異常
                }
             }
          }
      } catch (Exception e) {
          System.err.println("執行訊息推送驗證錯誤");
          e.printStackTrace();
          return 4;
      }
      System.err.println("執行訊息推送驗證結束");
      return onLineState;
   }
}

Step4:編寫Oracle函式(觸發器只需呼叫該函式執行Java程式,函式名自定義,java name必須是Java程式存在的類.方法(引數型別一致)

create or replace function openfire_notice_func(f_user varchar2, f_msg varchar2) return number
as
language java name 'SendMsgFunc.sendImMessage(java.lang.String, java.lang.String) return int';

Step5:這一步很關鍵,否則訊息不能傳送成功(Oracle許可權機制,訊息傳送需要Socket以及檔案讀取,因此需要給Oracle使用者進行授權)

請用sys登入資料庫為使用者授權執行【SQL命令】:

exec sys.dbms_java.grant_permission('大寫使用者名稱','SYS:java.net.SocketPermission', '127.0.0.1:9090', 'connect,resolve' );
exec sys.dbms_java.grant_permission('大寫使用者名稱','SYS:java.net.SocketPermission', '127.0.0.1:5222', 'connect,resolve' );
exec sys.dbms_java.grant_permission('大寫使用者名稱','SYS:java.lang.RuntimePermission', 'getClassLoader', '' );
exec sys.dbms_java.grant_permission('大寫使用者名稱','SYS:java.io.FilePermission', 'D:\DBHOME_1\JAVAVM\lib\security\cacerts', 'read' );
exec sys.dbms_java.grant_permission('大寫使用者名稱','SYS:java.io.FilePermission','<<ALL FILE>>','read,write,execute,delete');

如果未對使用者進行授權,就會丟擲如下異常:


Step6:編寫Oracle觸發器程式

-- 觸發器呼叫Java程式執行訊息傳送
create or replace trigger trigger_ofuser 
after insert or update on ofuser for each row

declare

  --定義變數
  MESSAGE_STATUS number;     -- 訊息傳送成功返回值狀態
  MESSAGE_INFO varchar2(50); -- 待發送的訊息內容

begin

  dbms_output.put_line('開始執行觸發器');

  --RAISE_APPLICATION_ERROR(-20000, '模擬一個錯誤程式碼,程式將終止');

  -- 一、插入操作,
  if inserting then

      --1、插入使用者記錄(略)
      --insert into ofuser values(...);

      --2、傳送訊息根據返回狀態記錄通知使用者是否接收到通知,歷史跟蹤,判斷當前使用者傳送訊息是否成功
      MESSAGE_INFO :='測試訊息傳送【測試人:'||:new.username||'】';
      begin
        select openfire_notice_func(:new.username, MESSAGE_INFO) into MESSAGE_STATUS from dual;
        if (MESSAGE_STATUS = -1) then
             dbms_output.put_line('通知已成功(使用者未註冊客戶端)');
        elsif (MESSAGE_STATUS = 0) then
             dbms_output.put_line('通知傳送成功(使用者不線上)');
        elsif (MESSAGE_STATUS = 1) then
             dbms_output.put_line('通知傳送成功(使用者已接收通知)');
        elsif (MESSAGE_STATUS = 2) then
             dbms_output.put_line('通知傳送失敗(伺服器發生異常,請稍後重試)');
        else
             dbms_output.put_line('通知傳送失敗(伺服器發生訊息異常,請聯絡系統管理員)');
        end if;
      end;
   end if;

  --二、更新操作
  if updating then
      update ofuser t set t.plainpassword = '123456' where t.username = :new.username;
  end if;
 
end trigger_ofuser;

Step7:編寫測試視窗進行測試


以上Oracle如何呼叫Java程式執行訊息傳送教程,若有疑問可以聯絡博主。

宣告:以上教程為博主原創,若需轉載請註明出處,謝謝。