最近公司的一个办公APP,采用cordova+framework7+spark的混合移动开发。需要在同事添加日志、点赞时可以通知到相关同事,然后就用了cordova-plugin-local-notification插件加spark的websocket技术,优点是实时性强,缺点可能就是耗电等问题吧。
cordova-plugin-local-notification插件
spark
framework7
这里简单记录一下,效果如下图。
前端js代码:(采用了sea.js模块化,这里就只上关键代码了)
var notification = null; //提示框
var heartflag = false; //是否心跳
var webSocket = null;
var tryTime = 0; //重连次数
var pushInfoId = 0; 记录ID
//初始化插件
User.prototype.initNotification = function() {
notification = {
init : function () {
try {
cordova.plugins.notification.local.un('clear', notification.ignore);
cordova.plugins.notification.local.on('clear', notification.ignore);
cordova.plugins.notification.local.un('click', notification.success);
cordova.plugins.notification.local.on('click', notification.success);
} catch (err) {
console.log("发生异常了。" + err);
}
},
success: function(n , eopts){
console.log("click"+n.id);
},
ignore: function(n, eopts){
console.log("clear"+n.id);
}
};
return notification.init();
};
//消息推送
User.prototype.messagePush = function(data) {
var info = data.split(";")
if(info.length==2){
pushInfoId++;
cordova.plugins.notification.local.schedule({
id: pushInfoId,
title: info[0],
text: info[1],
foreground: true
});
}
}
//websocket
User.prototype.initSocket = function(userId) {
var self = this;
if (!window.WebSocket) {
F7.alert("您的手机不支持websocket");
return false;
}
webSocket = new WebSocket("wss://192.168.31.242/echo/"+userId);
// 收到服务端消息
webSocket.onmessage = function (msg) {
if(msg.data == "&"){
//alert("心跳检测");
}else{
//alert(getNowFormatDate()+" 收到消息 : "+msg.data+"
");
self.messagePush(msg.data);
}
};
// 异常
webSocket.onerror = function (event) {
heartflag = false;
console.log(getNowFormatDate()+" 异常");
};
// 建立连接
webSocket.onopen = function (event) {
heartflag = true;
setInterval( function heart() {
if (heartflag){
webSocket.send("&");
}
}, 30*1000)
console.log(getNowFormatDate()+" 建立连接成功");
tryTime = 0;
};
// 断线重连
webSocket.onclose = function () {
heartflag = false;
// 重试10次,每次之间间隔10秒
if (tryTime < 10) {
setTimeout(function () {
webSocket = null;
tryTime++;
self.initSocket(userId);
console.log( getNowFormatDate()+" 第"+tryTime+"次重连
");
}, 10*1000);
} else {
console.log("重连失败.");
}
};
}
function getNowFormatDate() {
var date = new Date();
var seperator1 = "-";
var seperator2 = ":";
var month = date.getMonth() + 1;
var strDate = date.getDate();
if (month >= 1 && month <= 9) {
month = "0" + month;
}
if (strDate >= 0 && strDate <= 9) {
strDate = "0" + strDate;
}
var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+ " " + date.getHours() + seperator2 + date.getMinutes()
+ seperator2 + date.getSeconds();
return currentdate;
}
后代java代码 ( 因为后台用了spark的secure安全策略,使用https协议,所以websocket的地址用了wss)
Spark.webSocket("/echo/*", EchoWebSocket.class); //路径为echo/*的访问可进入到这里,开启websocket服务
Spark.init();
EchoWebSocket.class
package com.kthw.tasktrace.web;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.kthw.tasktrace.config.TaskTraceBeanConfiguration;
import com.kthw.tasktrace.mapper.UserMapper;
import com.kthw.tasktrace.model.UserInfo;
@WebSocket
public class EchoWebSocket {
//因为项目用了spring框架,直接从Context得到的mapper
static AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
TaskTraceBeanConfiguration.class);
private static UserMapper userMapper = applicationContext.getBean("userMapper",
UserMapper.class);
// Store sessions if you want to, for example, broadcast a message to all users
private static final Queue sessions = new ConcurrentLinkedQueue<>();
@OnWebSocketConnect
public void connected(Session session) {
sessions.add(session);
System.out.println("add: " + session.getRemoteAddress().getHostName()); // Print message
}
@OnWebSocketClose
public void closed(Session session, int statusCode, String reason) {
sessions.remove(session);
System.out.println("remove: " + session.getLocalAddress().getHostName()); // Print message
}
@OnWebSocketMessage
public void message(Session session, String message) throws IOException {
System.out.println("Got: " + message); // Print message
session.getRemote().sendString(message); // and send it back
}
//这是自己写的方法,用来在其他地方调用
//url格式为 wss://192.168.31.242/echo/userid
public static void sendMsgToUser(String info) throws IOException{
UserInfo user = userMapper.getUserById("dj");
//这里试了试可以正常调用mapper
for(Session s :sessions){
String url = s.getUpgradeRequest().getRequestURI().toString(); //访问的地址
... ...
//可以获取url,通过string处理,可得到userid
... ...
//通过自己的逻辑,发送给不同的人
... ...
s.getRemote().sendString(info); // and send it back
}
}
}
}