目的:
實現Tornado主動推送數據到前端
過程:
1、Layui 中Websocket的 js代碼
//此時的table只是爲了渲染表格
table.render({
elem: '#current_time_msg' // table標籤的ID
, data: []
, id: 'current_msg' // 爲了表格重載能找到這表格
, cols: [[
{field: 'ID', title: 'NO'}
, {field: 'MsgType', title: '類型', templet: '#MsgTypeTpl'}
, {field: 'CardNum', title: '卡號'}
, {field: 'UserName', title: '人員'}
, {field: 'DeptName', title: '部門'}
, {field: 'ControlerName', title: '地點'}
, {field: 'DoorName', title: '門名稱'}
, {field: 'EventTime', title: '時間'}
]]
, page: {theme: '#1E9FFF'}
,limit:150 //一頁顯示150條數據
,limits:[150] // 分頁只設置150,否則爲10,20,30....條
});
//需要實時後端推送數據給前端
var ip = window.location.href;
ip = ip.substring(7, ip.lastIndexOf(':'));
var ws = null;
var websocket = null;
//判斷當前瀏覽器是否支持WebSocket
if ('WebSocket' in window) {
//連接後端websocket
ws = new WebSocket('ws://' + ip + ':8977/ws/time_news');
} else {
layer.msg('Dont support websocket')
}
//連接發生錯誤的回調方法
ws.onerror = function () {
layer.msg('Error')
};
//連接成功建立的回調方法
ws.onopen = function () {
layer.msg('Open')
};
//接收到消息的回調方法
ws.onmessage = function (event) {
// websocket只能傳str類型,否則在瀏覽器的console中WS選項卡里請求攔截的data爲空
console.log(typeof (JSON.parse(event.data)), JSON.parse(event.data));
var obj = JSON.parse(event.data);
table.reload('current_msg', {
elem: '#current_time_msg'
, data: JSON.parse(event.data)
, page: {theme: '#1E9FFF'}
,limit:150
,limits:[150]
});
};
// 連接關閉的回調方法
ws.onclose = function () {
layer.msg('Close')
};
//監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket連接,防止連接還沒斷開就關閉窗口,server端會拋異常
window.onbeforeunload = function () {
ws.close()
};
//關閉連接
function closeWebSocket() {
ws.close();
window.clearInterval(intervalId)
}
//發送消息
function send() {
var message = document.getElementById('current_time_msg').value;
ws.send(message);
}
2、Tornado Websocket代碼
①、定義Websocket類
class WSTimeNewsHandler(WebSocketHandler):
# 用於多用戶連接
users = set()
def open(self):
print('WebSocket opened!', self)
self.users.add(self)
def on_message(self, message):
print(message)
for user in self.users:
user.write_message(message)
#自定義發送數據方法
@classmethod
def update_data(self, message):
for user in self.users:
user.write_message(message)
def on_close(self):
print('WebSocket closed!')
self.users.discard(self)
# 允許跨域通訊,解決403問題
def check_origin(self, origin):
return True
②、處理數據方法,用於調用 WSTimeNewsHandler.update_data()——>即Websocket發送數據的方法
#該方法是監聽MySQL數據庫表是否有新數據,以ID爲判斷基礎,有新數據則推送,無則不推送
def card_event():
print('我進入到CardEvent方法')
id_data = [0]
# 默認查詢今天時間事件
moring_time = datetime.datetime.now().strftime('%Y-%m-%d 00:00:00')
night_time = datetime.datetime.now().strftime('%Y-%m-%d 23:59:59')
with session_maker() as session:
res = session.query(func.max(BusinessEvent.EventID)).first()[0]
if res >= id_data[0]:
id_data[0] = res
print('我要進入查詢語句了')
res_data=session.query.filter(BaseEventtype).filter(
SetID,CardNum,UserName,DeptName,ControlerName,
DoorName,EventTime,EventContent).group_by(
EventTime).order_by(EventTime.desc()).all()
res = []
for i, item in enumerate(res_data):
result = {'ID': i + 1, 'MsgType': item[0], 'CardNum': item[1], 'UserName': item[2],
'DeptName': item[3],
'ControlerName': item[4], 'DoorName': item[5],
'EventTime': item[6].strftime('%Y-%m-%d %H:%M:%S'), 'EventContent': item[7]}
res.append(result)
# 把打包好的數據做分頁
res_limit_data = pagination(1, 150, len(res), res)
print(res_limit_data)
# 調用WebSocket發送數據方法
WSTimeNewsHandler.update_data(json.dumps(res_limit_data))
else:
print(res)
③、調用方法 參雜在其同一個界面的請求裏
class EventHandler(BaseHandler):
def post(self):
card_event()
#具體查庫封裝數據就不寫了,根據實際情況寫
...
④、請求地址
url_client = [
(r"/ws/time_news", WSTimeNewsHandler),
(r"/api/event", EventHandler),
]