Rails WebSocket介绍
那道卡了一个学期的生产者消费者问题,今夏开工,和小新讨论了半天怎么怎么折腾,然后踩到了不少坑。
需要用到Java+Rails+JavaScript,题目要求,不得不用。Java用于生产者消费者模型,剩下的用于前端显示。
最初的设计是轮询,换句话说,类似于Java写入数据库,然后刷新定时刷新读写,一遍遍去查找更新,这样当然是可行的,但是——好Low。
现在我们有了一个更好的解决方案,用WebSocket实现动态的、即时的更新。当然当初知识一个小想法,WebSockeet对我还很抽象,所以咨询了一下用过的小伙伴小新,得知差不多一个意思,查了各种资料,开工。
WebSocket的原理性介绍:https://github.com/abbshr/abbshr.github.io/issues/22
简单的来说是在运输层用TCP来进行通讯,而不是用HTTP协议,这很好理解嘛,跟Socket差不多一个意思(本来以为这辈子都不会用Socket因为不搞桌面开发)。
所以依旧的被切成三段,前端<->Rails,Rails<->Java,因为目前Java部分我还不是很懂,虽然复制黏贴了HTTP请求的代码,但具体怎么写的看不懂,就不做说明了。
参考一下一篇教程:WebSocket on Rails 4 and Ruby 2
可以结合Wiki来看,因为光看他的有点不明不白,光看Wiki也不太明白。(Example需要Bootstrap2,需要自行引入)。
摸索了两天,总算觉得自己懂了点什么,记录一下。
安装
不用说,先在GemFile
里加上gem websocket-rails
,然后bundle
一下。
接下来运行rails g websocket_rails:install
,进行WebSocket的安装。
接着在config/environments/development.rb
里加入config.middleware.delete Rack::Lock
移除这个中间件。
所有的准备步骤就做完了。
Controller
class ChatController < WebsocketRails::BaseController
def initialize_session
# perform application setup here
controller_store[:message_count] = 0
end
end
看这个实例,非常简单的一个Example,需要注意的是它的父类是:WebsocketRails::BaseController
,而一般是ApplicationController
,这两个是不一样的,用做WebSocket的Controller是没法作为普通Controller进行访问的。
controller_store
之后进行解释。
那我们也别多说了,根据他的实例接着创建:
def new_message
_message = {:message => 'this is a message'}
send_message :new_message, _message
end
这里可能还无法理解,send_message
是一个内置的函数,它与broadcast_message
相对应,是用于给自己发送对象的,而broadcast_message
是广播,给所有连接者。
接下来我们顺势讲Event Router,你就能懂发生了什么了。
Event Router
在config里找到event.rb,加入
subscribe :new_message, :to => ChatController, :with_method => :new_message
跟路由的语法很像,后面是Contrller以其对应的方法,那么前面自然是接下来我们要与前端向连的部分,叫做:new_message
,而刚刚在Controller里,也就是这么一个东西。
JavaScript
很快的我们可以来到前端了,很简单的Demo即将结束。
我们先链接服务器:var dispatcher = new WebSocketRails('localhost:3000/websocket');
,注意,在application.js
中,websocket对应的JS一定要先引入,否则会没有该类。
是否连通,我们可以测试一下:
dispatcher.on_open = function(data) {
console.log('Connection has been established: ', data);
// You can trigger new server events inside this callback if you wish.
}
这段代码在连接上之后立即执行,data由WebSocket提供,不用管。
测试通过之后我们可以接着来了。
dispatcher.bind('new_message', function(data) {
console.log('Daso:', data.message);
});
new_message
,也就是刚才:new_message
的部分,绑定一个事件,传入的是Object。
但是绑定不够,我们需要用trigger
触发:
$('#hello').click(function(){
dispatcher.trigger('new_message');
});
很简单的触发过程。
普通的Controller
普通的Controller建立,使用按钮,你就能感受到了。
从前端发送消息
力的作用是相互的,Event Router也是一个桥梁,前端调用trigger('event_name', {})
就能把数据传到后端,使用message[:xxx]
来访问。当然没有实验过/w\是看源代码感受到的。
从一般的Controller中数据
如果我们需要从HTTP协议获取数据,那么肯定会用到普通的Controller。
这里我们需要用到一个名叫Channels的东西,不复杂,甚至不需要你在Event Router里多写东西。
普通的Controller里加上一句
WebsocketRails[:channel_name].trigger(:event_name, object_to_send)
接下来在js里新建Channels
var channel = dispatcher.subscribe('channel_name');
// You can also pass an object to the subscription event
// var channel = dispatcher.subscribe({channel: 'channel_name', foo: 'bar'});
// bind to a channel event
channel.bind('event_name', function(data) {
console.log('channel event received: ' + data);
});
触发同dispatcher,但需要注意的是,Channel的event只能由Channel触发,同理。
Data Store
Data Store有两种,上面我们或许已经见识过了——controller_store
和connection_store
。
connection_store
类似于Session
,是一个连接公用的数据。而controller_store
针对个体的不同Controller数据就不能互通了,这是他们俩最大的区别,一般我们用Session比较多,同理。
结束
剩下的,Wiki依旧不能丢,这么说起来WebSocket也不难的样子~
植入部分
如果您觉得文章不错,可以通过赞助支持我。
如果您不希望打赏,也可以通过关闭广告屏蔽插件的形式帮助网站运作。
大神,我在集成这个,socket连接的时候总是报500错误
大神我的rails是5.1.4,按照你的步骤来的,但是就是连接不上
this._conn = new WebSocket(this.url);这个地方报错 ,500
我是哪里没有注意到吗,请帮帮忙,谢谢