vue +signalR 实现服务端到客户端消息发送
系列
源码地址:https://github.com/QQ2287991080/SignalRServerAndVueClientDemo
上一篇博客实现是了消息的实时通信,这一篇博客主要讲如何从中心服务内部向客户端发送消息。
先看下最终效果:
在core应用程序里加一个控制器TestController
注入控制器中的IHubContext实例,并且添加方法
[Route("api/[controller]/[action]")] [ApiController] public class TestController : ControllerBase { private readonly IHubContext<ChatHub> _hubContext; public TestController(IHubContext<ChatHub> hubContext) { _hubContext = hubContext; } [HttpGet] public async Task<int> Get() { await _hubContext.Clients.All.SendAsync("ReceiveMessage", "系统通知", $"北京时间{DateTime.Now}"); return 0; } }
然后启用路由和控制器
//启用控制器 services.AddControllers();
app.UseEndpoints(endpoints => { //终结点设置路由默认 endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); endpoints.MapRazorPages(); endpoints.MapHub<ChatHub>("/chathub"); });
哎呀忘记配置跨域了
//配置跨域 services.AddCors(c => c.AddPolicy("AllowAll", p => { p.AllowAnyOrigin(); p.AllowAnyMethod(); p.AllowAnyHeader(); }) );
//配置跨域别把中间件的位置放错了哦 app.UseCors("AllowAll");
这里为啥要配置跨域呢,因为之前signalr的连接时连接客户端的,它们基于底层的通信协议(这太高深了 ,俺也不懂),而现在我们通过浏览器发送请求获取系统通知的话,就会存在跨域的情况,所以需要配置
因为现在需要发送请求,所以我安装个axios
npm install axios
然后在mian.js配置下。
import axios from 'axios' Vue.prototype.$http = axios
更新一下上次写的home.vue里的代码
<template> <div class="home"> <h1>前端演示SignalR</h1> <input v-model="user" type="text" /> <input v-model="message" type="text" /> <button @click="sendAll">发送全部</button> <button @click="sendOwn">对自己发送</button> <button @click="sendClient">系统发送消息</button> <div> <ul v-for="(item ,index) in messages" v-bind:key="index +'itemMessage'"> <li>{{item.user}} says {{item.message}}</li> </ul> </div> </div> </template> <script> // @ is an alias to /src import HelloWorld from "@/components/HelloWorld.vue"; import * as signalR from "@aspnet/signalr"; export default { name: "Home", components: { HelloWorld }, data() { return { user: "", //用户 message: "", //消息 connection: "", //signalr连接 messages: [] //返回消息 }; }, methods: { //给全部发送消息 sendAll: function() { this.connection .invoke("SendMessage", this.user, this.message) .catch(function(err) { return console.error(err); }); }, //只给自己发送消息 sendOwn: function() { this.connection .invoke("SendMessageCaller", this.message) .catch(function(err) { return console.error(err); }); }, //系统发送消息 sendClient: function() { this.$http.get("http://localhost:13989/api/test/get").then(resp => { console.log(resp); }); } }, created: function() { let thisVue = this; this.connection = new signalR.HubConnectionBuilder() .withUrl("http://localhost:13989/chathub", { skipNegotiation: true, transport: signalR.HttpTransportType.WebSockets }) .configureLogging(signalR.LogLevel.Information) .build(); this.connection.on("ReceiveMessage", function(user, message) { thisVue.messages.push({ user, message }); console.log({ user, message }); }); this.connection.on("ReceiveCaller", function(message) { let user = "自己"; //这里为了push不报错,我就弄了一个默认值。 thisVue.messages.push({ user, message }); console.log({ user, message }); }); this.connection.start(); } }; </script>
这样的话,就能开篇那个效果了。
这里说几个注意的点,添加控制器之后一定要启用他,还有路由也要配置,否则你用postman的也是请求不到的,然后就是跨域配置,这些都是实现这个功能不能缺少的配置。
源码地址:https://github.com/QQ2287991080/SignalRServerAndVueClientDemo