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程序執行消息發送教程,若有疑問可以聯繫博主。

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章