泛微ECOLOGY9 集成 MQTT 做定时消息推送

使用场景介绍

由于之前用表单建模搭建了一套 E-SOP文件管理系统,通过流程上传E-SOP文件附件,自动转换为 图片并保存在建模中(实现方式见泛微ECOLOGY9流程模块(建模通用)office附件上传自动转为图片并显示在流程指定附件字段中)。 然后前端用 JSP做了展示界面进行E-SOP文件图片的轮播展示。但这里有一个关键的点是如何让页面根据上线产品的变化自动更新对应的E-SOP文件图片。 一开始使用了AJAX的方式每5秒去获取信息做比对判断是否需要更新E-SOP文件图片,但随着带机量的增加,发现严重影响了OA的打开速度。所以想通过消息推送的方式来进行E-SOP文件图片的更新以减少OA服务器的压力。

实现方案

通过泛微的定时任务 触发 MQTT的 消息主题推送, 然后前端JSP中做MQTT的消息主题订阅。

环境配置

1、在\ecology\WEB-INF\prop目录下创建mqtt.properties 配置文件

mqttUrl = XXX MQTT服务器的地址
mqttPort = XXX MQTT 服务器的端口
mqttUser = XXX MQTT服务器的帐号 没有就留空
mqttPass = XXX MQTT服务器的密码 没有就留空
mqttClientId = XXX MQTT客户端的唯一ID 不指定为空就在代码中自动生成

2、在\ecology\WEB-INF\lib目录下添加org.eclipse.paho.client.mqttv3-1.2.5.jar

推送端代码及配置

MqttClientUtils.java 把 mqtt 的连接跟推送包装成工具类,方便后续调用。

import org.eclipse.paho.client.mqttv3.*;
import weaver.general.BaseBean;
import weaver.general.GCONST;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;

public class MqttClientUtils {
    private static MqttClient client;

    public static void setClient(MqttClient client) {
        MqttClientUtils.client = client;
    }

    public static MqttClient getClient() {
        return client;
    }

    public static void mqttConnect(String topic) throws IOException, MqttException {
        if(topic.isEmpty()){
            topic = "WFtopic"; //如果主题为空就用默认主题
        }
        Properties properties = new Properties();
        BufferedInputStream mqtt= new BufferedInputStream(new FileInputStream(GCONST.getRootPath()+"WEB-INF"+ File.separatorChar+"prop"+File.separatorChar+"mqtt.properties")); //从配置文件中读取MQTT的相关信息
        properties.load(mqtt);
        //mqtt服务器地址
        String mqttUrl = properties.getProperty("mqttUrl");
        //mqtt服务器端口
        String mqttPort = properties.getProperty("mqttPort");
        //mqtt服务器帐号
        String mqttUser = properties.getProperty("mqttUser");
        //mqtt服务器密码
        String mqttPass = properties.getProperty("mqttPass");
        String clientId = properties.getProperty("mqttClientId");
        if(clientId.isEmpty()){//如果客户端ID为空就指定一个
            clientId = "wfClicent"+new Date().getTime();
        }

        String broker = "tcp://"+mqttUrl+":"+mqttPort;

        MqttClient fwClient = new MqttClient(broker, clientId);
        // MQTT 连接选项
        MqttConnectOptions connOpts = new MqttConnectOptions();
        if(!mqttUser.isEmpty()) {
            connOpts.setUserName(mqttUser);
            if(!mqttPass.isEmpty()) {
                connOpts.setPassword(mqttPass.toCharArray());
            }
        }
        // 保留会话
        connOpts.setCleanSession(false);
        new BaseBean().writeLog("Connecting to broker: " + broker);
        fwClient.connect(connOpts);
        MqttClientUtils.setClient(fwClient);

    }


    public static void publish(String topic, String pushMessage){
        MqttMessage message = new MqttMessage();
        message.setQos(0);
        message.setRetained(false);
        message.setPayload(pushMessage.getBytes());
        try{
            MqttClientUtils.getClient().publish(topic,message);
        } catch(Exception e){
            new BaseBean().writeLog("mqtt发送消息异常:" ,e);
        }
    }


}

定时推送代码

import com.MqttClientUtils;
import org.eclipse.paho.client.mqttv3.*;
import weaver.conn.RecordSet;
import weaver.interfaces.schedule.BaseCronJob;
import java.io.*;


public class MQTTPUSH extends BaseCronJob {
    @Override
    public void execute() {
        RecordSet rs = new RecordSet();
        String sql = "获取推送消息";
        rs.execute(sql);
        while (rs.next()) {
            String message = rs.getString("message"); //推送内容
            String center = rs.getString("center"); //工作中心
            String line = rs.getString("line"); //生产线

            try {//由于我这边要根据不同的工作中心和生产线推送不同的内容,所以推送主题定义为动态的,在主题前缀上加上工作中心和生产线做为一个主题。
                MqttClientUtils.mqttConnect("soppush"+center+line);
                MqttClientUtils.publish("soppush"+center+line,message);

            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (MqttException e) {
                throw new RuntimeException(e);
            }

        }


    }
}

将以上编译好的文件放到 ecology/classbean/com/下面

任务计划配置如下图

在这里插入图片描述
每5秒推送一次主题消息

前端MQTT订阅主题实现

<script src="../resources/jquery.js"></script>
<script src="../resources/swiper.min.js"></script> 
<script src="../resources/mqttws31.min.js"></script> 
<script>
 function getQueryVariable(variable)
 {
     var query = window.location.href.split('?')[1];
     var vars = query.split("&");
     for (var i=0;i<vars.length;i++) {
         var pair = vars[i].split("=");
         if(pair[0] == variable){return pair[1];}
     }
     return(false);
 }
var center=getQueryVariable("center");
var line=getQueryVariable("line");
var oldmessage = "";
//-------MQTT---------------	
var hostname = 'MQTT地址', 
    port = 8083, //js中MQTT走的是ws协议,所以在EMQX中用 ws的端口
    clientId = 'sop'+center+line+new Date().getTime(), //由于同条线有多台设备,防止ID冲突,所以加上了时间搓
    timeout = 5,
    keepAlive = 60,
    cleanSession = true,
    ssl = false,
    topic = 'soppush'+center+line;
client = new Paho.MQTT.Client(hostname, port, clientId);
 //建立客户端实例  
 var options = {
     invocationContext: {
         host: hostname,
         port: port,
         path: client.path,
         clientId: clientId
     },
     timeout: timeout,
     keepAliveInterval: keepAlive,
     cleanSession: cleanSession,
     useSSL: ssl,
     // userName: userName,  
     // password: password,  
     onSuccess: onConnect,
     onFailure: function (e) {
         console.log(e);
     }
 };
client.connect(options);
//连接服务器并注册连接成功处理事件  
function onConnect() {
    console.log("onConnected");
    client.subscribe(topic);
}
client.onConnectionLost = onConnectionLost;

//注册连接断开处理事件  
client.onMessageArrived = onMessageArrived;

//注册消息接收处理事件  
function onConnectionLost(responseObject) {
    console.log(responseObject);
    if (responseObject.errorCode !== 0) {
        console.log("onConnectionLost:" + responseObject.errorMessage);
        console.log("连接已断开");
    }
}
 
function onMessageArrived(message) {
	if (oldmessage == "" ){
	oldmessage = message.payloadString
}else if((oldmessage != "" && oldmessage != message.payloadString) ){
	window.location.reload(); //如果获取到的信息跟原来的不一致,就重新刷新页面
}
   console.log("收到消息:" + message.payloadString);
}	

</script>

最终效果

推送端和订阅端都连上EMQX,推送端推送信息到对应的主题中。订阅端获取对应主题中的信息。
在这里插入图片描述
在这里插入图片描述

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东枫落定

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值