当前位置:   article > 正文

java消息推送怎么实现_netty-socketio+vue实现服务端推送消息到前端

vue使用socketio与java发送消息

什么是消息推送?

正常情况下一个前后端的交互过程是这样的:

  1. 用户操作界面触发前端代码
  2. 前端请求后端并提交数据
  3. 后端响应数据给前端
  4. 前端渲染结果展示给用户

大部分情况以上流程就可以解决,但有一些特殊情况下例外,比如服务器无法马上处理一个请求或服务器通过定时任务自动处理任务,并且需要在以后某个时间处理完成后通知用户处理结果(比如转账、抽奖、核对订单等)。这种时候需要服务端主动向用户推送一些内容,一般有两种做法:

  • 客户端不断的请求服务端以获取最新数据(轮询)
  • 服务端主动推送给客户端(消息通知/推送)

一般来讲,第二种会更加优雅一些,并且减少了大量的请求消耗。市场上也有很多的消息推送技术,比如websocket、socketio、netty等。本文介绍下Java springboot下的netty-socketio的实现方式。

0153ea827574918addf6d35191071955.png

socketio

一、后端

1.添加maven依赖

               com.corundumstudio.socketio            netty-socketio            1.7.18

2.添加config配置类

主要是配置下后端socket的地址和端口。

import com.corundumstudio.socketio.SocketIOServer;import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration@Slf4jpublic class SocketServerConfig {    private static int port;    @Value("${socket.port}")    public void setPort(int port) {        SocketServerConfig.port = port;    }    @Bean    public SocketIOServer socketIOServer() {        log.info("SocketIoServer启动 端口"+port);        com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();//        config.setHostname("localhost");        config.setPort(port);        SocketIOServer server = new SocketIOServer(config);        return server;    }    /**     * 用于扫描netty-socketio的注解,比如 @OnConnect、@OnEvent     */    @Bean    public SpringAnnotationScanner springAnnotationScanner() {        return new SpringAnnotationScanner(socketIOServer());    }}

3.添加消息处理类

主要是监听客户端的连接、断开、客户端发送消息等事件。在连接时存储下活动客户端以备后面推送时使用,在断开时在活动库中删除客户端。

import cn.hutool.json.JSONObject;import com.corundumstudio.socketio.AckRequest;import com.corundumstudio.socketio.SocketIOClient;import com.corundumstudio.socketio.SocketIOServer;import com.corundumstudio.socketio.annotation.OnConnect;import com.corundumstudio.socketio.annotation.OnDisconnect;import com.corundumstudio.socketio.annotation.OnEvent;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentMap;/*** @Description websocket处理器**/@Component@Slf4jpublic class MessageEventHandler {    @Autowired    private SocketIOServer server;    public static ConcurrentMap clientMap = new ConcurrentHashMap<>();    /**     * 客户端连接的时候触发     *     * @param client     */    @OnConnect    public void onConnect(SocketIOClient client) {        //存储SocketIOClient,用于发送消息        clientMap.put(client.getSessionId().toString(), client);        //回发消息        client.sendEvent("message", "welcome");        log.info("客户端["+client.getRemoteAddress()+"]连接成功");    }    /**     * 客户端关闭连接时触发     *     * @param client     */    @OnDisconnect    public void onDisconnect(SocketIOClient client) {        log.info("客户端["+client.getRemoteAddress()+"]断开连接");        clientMap.remove(client.getSessionId());    }    /**     * 客户端发来的事件     *     * @param client   客户端信息     * @param request 请求信息     * @param data     客户端发送数据     */    @OnEvent(value = "xxxEvent")    public void onEvent(SocketIOClient client, AckRequest request, JSONObject data) {        log.info("客户端发来xxxEvent消息:" + data);    }}

4.服务端给客户端发消息工具类

封装了一个服务端发送给前端的方法,注意事件是可以自定义的,但需要前端用相同事件名称接收。

import cn.hutool.json.JSONObject;import com.corundumstudio.socketio.SocketIOClient;/*** @Description websocket工具类**/public class SocketUtils {    /**     * 不同的业务自己与前端协定好,然后增加事件类型     */    public enum EventEnum {        message,//普通消息        xxx,//自定义消息    }    /**     * 发送广播消息     * @param event     * @param obj     */    public static void sendMsg(EventEnum event, JSONObject obj){        for (SocketIOClient client : MessageEventHandler.clientMap.values()) {            if (client.isChannelOpen()) {                client.sendEvent(event.name(), obj);            }        }    }}

二、前端(VUE)

1.添加封装的websocket.js(github上的一个开源项目icebob/vue-websocket)

提供一个在vue环境封装的全局调用,引入了socket.io-client依赖,将业务的vue文件中定义的监听方法统一管理。

import IO from "socket.io-client";//文档地址 https://github.com/icebob/vue-websocketexport default {  install(Vue, connection, opts) {    let socket;    if (connection != null && typeof connection === "object")      socket = connection;    else      socket = IO(connection || "", opts);    Vue.prototype.$socket = socket;    let addListeners = function() {      // console.log("addListeners xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");      if (this.$options["socket"]) {        let conf = this.$options.socket;        if (conf.namespace) {          this.$socket = IO(conf.namespace, conf.options);        }        // console.log('conf.events ', conf.events);        if (conf.events) {          let prefix = conf.prefix || "";          Object.keys(conf.events).forEach((key) => {            let func = conf.events[key].bind(this);            this.$socket.on(prefix + key, func);            conf.events[key].__binded = func;          });        }      }    };    let removeListeners = function() {      if (this.$options["socket"]) {        let conf = this.$options.socket;        if (conf.namespace) {          this.$socket.disconnect();        }        if (conf.events) {          let prefix = conf.prefix || "";          Object.keys(conf.events).forEach((key) => {            this.$socket.off(prefix + key, conf.events[key].__binded);          });        }      }    };    Vue.mixin({      [Vue.version.indexOf("2") === 0 ? "beforeCreate" : "beforeCompile"]: addListeners,      beforeDestroy: removeListeners    });  }};

2.在main.js中增加全局配置

引入封装的js,设置后端socket服务的地址和端口。

import VueWebsocket from "./utils/websocket.js";Vue.use(VueWebsocket, process.'http://localhost:8889');

3.在使用的业务模块vue文件中添加监听方法(跟created、mounted、methods同级)

  socket: {    events: {      event1(msg) {        console.log('接收到服务端event1事件信息', msg);      },      event2(msg) {        console.log('接收到服务端event2事件信息', msg);      }    }  }

注意这里的event1和event2 是可以自定义的,但需要后端与前端保持一致,只需要在方法里处理推送过来的消息即可。

总结一下,主要分为两部分:

1.后端配置服务的地址端口和推送的业务事件

2.前端配置需要连接的服务端地址端口和监听需要接收的业务事件

希望本文对你有所帮助,关注我,不定时更新实用技术干货。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/404281?site
推荐阅读
相关标签
  

闽ICP备14008679号