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' );(IP地址是openfire服务器IP)
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:\Oracle目录\PRODUCT\11.2.0\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程序执行消息发送教程,若有疑问可以联系博主。

声明:以上教程为博主原创,若需转载请注明出处,谢谢。

时间: 2024-10-01 23:05:30

Oracle触发器如何调用Java实现Openfire消息发送的相关文章

在ORACLE触发器里调用JAVA程序

因为项目需要,有一个已经写好的Java程序,想要在Oracle某个表的触发器中调用,以使得每次数据更新时,调用这个JAVA程序,来修改后台某个数据. 现将过程记录如下: 1.编写JAVA程序 [java] view plain copy public class Main { public static void modify(String statTime) { String datas = "/var/spool/cron/oracle"; File data = new File

Oracle触发器反向调用Java程序

导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了, 1.操作系统需要拥有支持loadjava命令的jdk. 2.加载jlha.jar包,到oracle数据库中. 操作过程:在dos环境下,输入命令: loadjava -r -f -o -user usscares/[email protected] jlha.jar 注意:jar包要在1.4的环境下编译,项目右键 properties java compiler

Oracle数据库中调用Java类开发存储过程、函数的方法

Oracle数据库中调用Java类开发存储过程.函数的方法 时间:2014年12月24日  浏览:5538次 oracle数据库的开发非常灵活,不仅支持最基本的SQL,而且还提供了独有的PL/SQL,除此之外,还可以用时下最流行的编程语言Java来做开发.随着对oracle的了解越来越多,越来越禁不住oracle的诱惑,oracle技术真的是一门很有趣的学问.之前,我在博客中总结了挺多有关SQL.PL/SQL的,但是对于oracle数据库中Java类的调用却没有总结,也是因为之前不太会,这会儿总

oracle触发器调用java程序

1.创建java程序:接收存储过程传递的参数,发送socket通信. create or replace and compilejava source named jym as import java.io.BufferedReader; import java.io.InputStream; importjava.io.InputStreamReader; import java.io.OutputStream; import java.io.StringWriter; importjava.

oracle调用java方法的例子(下面所有代码都是在sql/plus中写)

在Oracle中调用Java程序,注意:java方法必须是static类型的,如果想在JAVA中使用system.out/err输出log. 需要在oracle 中执行"call dbms_java.set_output(5000);".一.helloWord1 编写JAVA程序,也是在SQL/PLUS中写,并执行. create or replace and compile Javasource named hello as public     class   Hello    {

《oracle每天一练》触发器不能调用或间接调用COMMIT,ROLLBACK等DCL语句

触发器不能调用或间接调用COMMIT,ROLLBACK等DCL语句 在触发器中不能运行 ddl语句和commit,rollback语句 ddl语句:DDL语句用语定义和管理数据库中的对象,如Create,Alter,Drop,truncate等:DDL操作是隐性提交的!         操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger DML(Data Manipulation Language)数据操纵语言命令使用户能够查询数据库以及操作已有数

Oracle调用Java类开发的存储过程、函数的方法

oracle调用java类的基本步骤 1. 编写java代码,后续可以直接使用java代码,class文件或者jar包 2. 将写好的java代码导入到oracle数据库中,有两种方法:一种是使用loadjava命令:另一种是在编写PL/SQL的时候编写 3. 编写存储过程.函数 来封装java代码,以实现后面对java功能的调用 4. 调用写好的存储过程和oracle函数 loadjava命令介绍 有关loadJava的各个参数的意思,可以使用:loadjava -help 命令来获得详细帮助

Oracle触发器实例(网搜)

触发器使用教程和命名规范 目  录触发器使用教程和命名规范 11,触发器简介 12,触发器示例 23,触发器语法和功能 34,例一:行级触发器之一 45,例二:行级触发器之二 46,例三:INSTEAD OF触发器 67,例四:语句级触发器之一 88,例五:语句级触发器之二 99,例六:用包封装触发器代码 1010,触发器命名规范 11 1,触发器简介触发器(Trigger)是数据库对象的一种,编码方式类似存储过程,与某张表(Table)相关联,当有DML语句对表进行操作时,可以引起触发器的执行

oracle 触发器的实例(转)

触发器使用教程和命名规范 目  录触发器使用教程和命名规范 11,触发器简介 12,触发器示例 23,触发器语法和功能 34,例一:行级触发器之一 45,例二:行级触发器之二 46,例三:INSTEAD OF触发器 67,例四:语句级触发器之一 88,例五:语句级触发器之二 99,例六:用包封装触发器代码 1010,触发器命名规范 11 1,触发器简介触发器(Trigger)是数据库对象的一种,编码方式类似存储过程,与某张表(Table)相关联,当有DML语句对表进行操作时,可以引起触发器的执行