zoukankan      html  css  js  c++  java
  • Signalr实现消息推送

    一、前言

        大多数系统里面好像都有获取消息的功能,但这些消息来源都不是实时的,比如你开两个浏览器,用两个不同的账号登录,用一个账号给另外一个账号发送消息,然而并不会实时收到消息,必须要自己手动F5刷新一下页面才会显示自己的消息,这样感觉用户体验不太好。之前看了Learning hard关于Signalr的文章,刚好自己项目中有用到获取实时消息的功能,然而我们项目中就是用js代码setinterval方法进行1秒刷新读取数据的,这样严重给服务器端添加负担,影响系统性能!所以自己稍微研究了一下,下面是自己的一些理解,如果有不对的地方,请大家加以斧正!

    二、实现原理

    下面谈一下自己对Signalr的理解,Signalr可以进行远程分布式实时通信,都是使用远程代理来实现,其中有两大内部对象,第一个是Persisten Connection,用于客户端和服务器端的持久连接,第二个是Hub(集线器)对象,主要用于信息交互,将服务器端的数据推送(push)至客户端,大致原理如下:

    1、客户端建立与服务器端的连接

    2、客户端调用服务器端的方法

    3、服务器端通过客户端发送的请求,响应数据,再将数据推送至客户端

    三、Signalr实现消息推送

          具体操作实现如下:

          1、创建一个应用程序,我这里创建的是MVC应用程序

          2、引用相关组件,右键引用》选择管理Nuget程序包

          3、搜索Signalr,如图所示:

                                     

                  点击安装,在应用程序的Scripts文件夹里面会自动生成两个js文件,如图所示:

                                      

           4、添加集成器类

                                   

           5、注册signalr/hubs,在Startup.cs里面添加如下代码

                                  

           6、新建控制器MessageController,然后在控制器里面新建两个视图方法SendMessage和ReceiveMessage,为了让效果看起来更直观,一个页面用于发送消息,一个页面用于接收消息,如图所示:

                                 

           7、在我们刚刚新建的集成器类MyHub类里面添加代码:

               (特别说明一下,这里的InsertMsg方法主要是将客户端发送的消息信息保存到数据库里面,便于消息读取,为了快速创建数据库表,我采用的code first方法来创建的,至于你想用什么方式创建表,那都是可以的。)

                

    namespace Signalr.Models 
    {
        [HubName("MyHub")]
        public class MyHub : Hub
        {
            MessageDbContext _db = new MessageDbContext();
            public void Send(string title, string message)
            {
                this.InsertMsg(title, message);
                // 调用所有客户端的sendMessage方法
                Clients.All.sendMessage(message);
            }
    
            private void InsertMsg(string title, string message)
            {
                Message msg = new Message();
                msg.Title = title;
                msg.MsgContent = message;
                _db.Messages.Add(msg);
                _db.SaveChanges();
            }
        }
    }

    表结构如图所示:

                           

            8、控制器MessageController后台代码

    public class MessageController : Controller
        {
          private MessageDbContext _db = new MessageDbContext();
            public ActionResult SendMessage()
            {
                return View();
            }
    
            public ActionResult ReceiveMessage()
            {
                return View();
            }
    
            [HttpPost]
            public JsonResult MsgCount()  
            {
                var count = this._db.Messages.Where(p=>p.IsRead==0).Count();
              return Json(new {count=count},JsonRequestBehavior.AllowGet);
            }
        }

            9、前端页面代码(SendMessage.cshtml)

    @{
        ViewBag.Title = "发送消息";
    }
    <title>发送消息</title>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            // 引用自动生成的集线器代理
            var chat = $.connection.MyHub;
            // 定义服务器端调用的客户端sendMessage来显示新消息
            chat.client.sendMessage = function (title, message) {
                // 向页面发送接收的消息
                sendMsg();
            };
            // 集成器连接开始
            $.connection.hub.start().done(function () {
                sendMsg();
                // 服务连接完成,给发送按钮注册单击事件
                $('#sendmessage').click(function () {
                    // 调用服务器端集线器的Send方法
                    chat.server.send($("#title").val(), $('#message').val());
                });
            });
        });
    
        function sendMsg() {
            var options = {
                url: '/Message/MsgCount',
                type: 'post',
                success: function (data) {
                    $("#count").html(data.count);
                }
            };
            $.ajax(options);
        }
    </script>
    
    
    <h2>
        发送消息
    </h2>
    <div>
        <label>我的消息:</label>
        <span style=" color:red; font-size:30px;" id="count"></span></div>
    <p>
        <div>
            标题:
            <input type="text" id="title" />
        </div>
        <br /><br />
        <div>
            内容:
            <textarea id="message" rows="4" cols="30"></textarea>
        </div>
        <br /><br />
        <div>
            <input type="button" id="sendmessage" value="发送" />
        </div>
    </p>

             10、前端页面代码(ReceiveMessage.cshtml)

    @{
        ViewBag.Title = "接受消息";
    }
    <title>接受消息</title>
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
        $(function () {
            // 引用自动生成的集线器代理
            var chat = $.connection.MyHub;
            // 定义服务器端调用的客户端sendMessage来显示新消息
            chat.client.sendMessage = function (title, message) {
                // 向页面发送接收的消息
                MsgCount();
                var html = "<div>标题:" + title + "消息内容:" + message + "</div>";
                $("#msgcontent").after(html);
            };
            // 集成器连接开始
            $.connection.hub.start().done(function () {
                MsgCount();
            });
        });
        function MsgCount() {
            var options = {
                url: '/Message/MsgCount',
                type: 'post',
                async:false,
                data: { title: $("#title").val(), msgcontent: $("#sendmessage").val() },
                success: function (data) {
                    $("#count").html(data.count);
                }
            };
            $.ajax(options);
        }
    </script>
    
    
    <h2>
        接收消息
    </h2>
    
    <div>
        <label>我的消息:</label>
        <span style=" color: red; font-size: 30px;  margin-right:10px;" id="count"></span><br />
        <br />
        <div id="msgcontent"></div>
    </div>

     好了,大功告成,可能你有点疑问的是这个js文件引用地方在哪里

    不防我们运行页面,按F12查看一下,它会自动在这里生成一个js文件,我们只要在页面中引用这个路径即可

    四、页面效果(见证奇迹的时刻到了,哈哈哈~~~)

          为了让页面效果更为直观,我这里用IE打开SendMessage.cshtml页面,用Google打开ReceiveMessage.cshtml页面。

    权责申明

    作者:SportSky 出处: http://www.cnblogs.com/sportsky/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧

  • 相关阅读:
    SpringBoot配置文件加载位置及顺序
    linux之开通FTP服务(喂饭级)
    linux之chmod授权
    mysql动态查询上周的数据
    hibernate解读之session--基于最新稳定版5.2.12
    阿里java开发手册中命名规约解读之DO/BO/DTO/VO/AO
    JSP最常用的五种内置对象(out,request,response,session,application)
    JSP执行过程分析
    web.xml解析
    MVC脚手架(一)之javabean+jsp+servlet+jdbc
  • 原文地址:https://www.cnblogs.com/sportsky/p/5580682.html
Copyright © 2011-2022 走看看