vue前后台分离,websocket实现消息提示

环境:前台vue,后台springboot,根据用户需求指定用户,页面显示提示图标闪烁,点击图标弹出后台推送消息,消息接口采用websocket协议

实现效果:

 

后台:

配置项:WebSocketConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import javax.annotation.Resource;

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Resource
    private MyHandler myHandler;

    // 启动 websocket 线程
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//        System.out.println("+++++++++++");
        registry.addHandler(myHandler, "/myHandler").addInterceptors(new WebSocketInterceptor()).setAllowedOrigins("*");// 接收前台url请求,这地方很重要
    }


}

握手拦截器:WebSocketInterceptor

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;

import javax.servlet.http.HttpSession;
import java.util.Map;

public class WebSocketInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler, Map<String, Object> map) throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
            HttpSession session = serverHttpRequest.getServletRequest().getSession(true);

//            System.out.println("握手拦截器^^^^^^^^^^^^");
//            System.out.println("username = " + serverHttpRequest.getServletRequest().getParameter("username")); // 请求参数

            if (session != null) {
                map.put("userId", serverHttpRequest.getServletRequest().getParameter("username")); // 设置处理器id
            }
        }

        return true;
    }

    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
//        System.out.println("握手之后^^^^^^^^^^^^");

    }


}
处理器:MyHandler
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Service
public class MyHandler extends TextWebSocketHandler {

    //在线用户列表
    private static final Map<String, WebSocketSession> users;
    //用户标识
    private static final String CLIENT_ID = "userId";

    static {
        users = new HashMap<>();
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("成功建立连接");
        String userId = getClientId(session);
//        System.out.println(userId);
        if (userId != null) {
            users.put(userId, session);
            session.sendMessage(new TextMessage("成功建立socket连接"));
//            System.out.println(userId);
//            System.out.println(session);
        }
    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        // ...
//        System.out.println(message.getPayload());
//
//        WebSocketMessage message1 = new TextMessage("server:"+message);
//        try {
//            session.sendMessage(message1);
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    /**
     * 发送信息给指定用户
     * @param clientId
     * @param message
     * @return
     */
    public boolean sendMessageToUser(String clientId, TextMessage message) {
        if (users.get(clientId) == null) return false;
        WebSocketSession session = users.get(clientId);
//        System.out.println("sendMessage:" + session);
        if (!session.isOpen()) return false;
        try {
            session.sendMessage(message);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 广播信息
     * @param message
     * @return
     */
    public boolean sendMessageToAllUsers(TextMessage message) {
        boolean allSendSuccess = true;
        Set<String> clientIds = users.keySet();
        WebSocketSession session = null;
        for (String clientId : clientIds) {
            try {
                session = users.get(clientId);
                if (session.isOpen()) {
                    session.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
                allSendSuccess = false;
            }
        }

        return  allSendSuccess;
    }


    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        System.out.println("连接出错");
        users.remove(getClientId(session));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("连接已关闭:" + status);
        users.remove(getClientId(session));
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 获取用户标识
     * @param session
     * @return
     */
    private String getClientId(WebSocketSession session) {
        try {
            String clientId = (String) session.getAttributes().get(CLIENT_ID);
            return clientId;
        } catch (Exception e) {
            return null;
        }
    }

}

推送线程:PushServer

import org.apache.logging.log4j.core.config.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;

import java.util.Timer;
import java.util.TimerTask;

@Component//被spring容器管理
@Order(1)//如果多个自定义ApplicationRunner,用来标明执行顺序
public class PushServer implements ApplicationRunner {

    @Autowired
    MyHandler handler;

    @Override
    public void run(ApplicationArguments applicationArguments) throws Exception{
        System.out.println("-------------->" + "启动消息推送~");

        TimerHandle();
    }

    public static void TimerHandle(){

        //定时任务
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("------定时任务--------");

                // 根据业务需求,向前台发送提示消息
            }
            // 每10秒钟计算一次
        }, 0, 1000*10);

        //阻塞队列
//        Runnable run = new Runnable() {
//
//            @Override
//            public void run() {
//                while(true){
//
//                }
//            }
//        };
//        Thread newThread = new Thread(run);
//        newThread.start();
    }

}

前台:

  created(){
    this.connectWebsocket();
  },
  methods: {
      connectWebsocket() {
        let websocket;
        if (typeof WebSocket === "undefined") {
          console.log("您的浏览器不支持WebSocket");
          return;
        } else {
        if(localStorage.getItem('username') != undefined)
        {
          let url = 'ws://localhost:8889/myHandler?username=' + localStorage.getItem('username');

          // 打开一个websocket
          websocket = new WebSocket(url);
          // 建立连接
          websocket.onopen = () => {
            // 发送数据
            websocket.send("发送数据");
            console.log("websocket发送数据中");
          };
          // 客户端接收服务端返回的数据
          websocket.onmessage = evt => {
            console.log("websocket返回的数据:", evt.data);
          };
          // 发生错误时
          websocket.onerror = evt => {
            console.log("websocket错误:", evt);
          };
          // 关闭连接
          websocket.onclose = evt => {
            console.log("websocket关闭:", evt);
          };
        }

      }
    }
  }

PS:参考了很多博客实现这个,本想填上url,但是因为事情耽搁,时间太久了,忘记了,在此表示歉意~

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 可以使用 websocket后端进行实时通信。要在 Java 中实现 websocket,可以使用 Java API for WebSocket(JSR 356)。 要在 Vue 中使用 websocket,可以使用第三方库,例如 vue-socket.io。 示例代码: Java 服务端: ```java import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/websocket") public class WebSocketServer { @OnOpen public void onOpen(Session session) { System.out.println("Open a new session: " + session.getId()); } @OnMessage public void onMessage(String message, Session session) { System.out.println("Receive a message: " + message); } @OnClose public void onClose(Session session) { System.out.println("Close a session: " + session.getId()); } } ``` Vue 客户端: ```javascript import Vue from 'vue'; import VueSocketIO from 'vue-socket.io'; Vue.use(new VueSocketIO({ debug: true, connection: 'http://localhost:8080/websocket', })); new Vue({ el: '#app', data: { message: '', }, methods: { sendMessage() { this.$socket.emit('send message', this.message); this.message = ''; }, }, }); ``` 在这个示例中,Java 服务端会监听 `/websocket` 路径,Vue 客户端会连接到这个路径。当 Vue 客户端调用 `sendMessage` 方法时,会向服务端发送 `send message` 事件,服务端会收到并打印消息。 ### 回答2: 使用WebSocket可以实现实时消息推送功能。下面是使用Java和Vue实现后台消息推送的简单流程: 1. 后台Java实现: 首先,需要创建一个WebSocket处理器类,可以使用Java中的WebSocket API或开源库(如Spring WebSocket)来简化实现。 在WebSocket处理器类中,需要定义连接建立、断开和接收消息等方法,并添加注解以映射监听的消息路径,并处理相应的业务逻辑。 2. 前端Vue实现: 在Vue中,可以使用WebSocket对象来与后台建立连接,并监听消息的到达。 需要在Vue的钩子函数中创建WebSocket对象,并注册回调函数处理后台发送的消息。 当收到消息时,可以将其展示在前端页面的相应位置。 3. 后台推送消息: 在后台的相关业务逻辑中,可以通过WebSocket的连接向前端发送消息。 可以在需要推送消息的地方,通过获取对应的WebSocket连接,并使用WebSocket对象的send方法将消息发送至前端。 需要注意的是,WebSocket是基于TCP协议的全双工通信协议,所以需要确保后台服务器和前端浏览器都支持WebSocket。 以上是一个简单的实现示例,实际项目中还需要根据具体需求进行扩展和优化。希望能帮到你! ### 回答3: 要使用WebSocket实现后台消息推送,需要进行以下步骤: 1. 在后台使用Java语言创建WebSocket服务器。可以使用Java内置的WebSocket API或者第三方库,如Tomcat的WebSocket实现等。具体方式可以通过搜索相关教程了解。 2. 在Vue前端应用中,使用WebSocket连接到后台服务器。可以使用Vue插件,如vue-native-websocket或者自己编写相关逻辑。具体方式可以通过搜索相关教程了解。 3. 后台服务器接收Vue前端应用的WebSocket连接请求,并处理连接逻辑。 4. 在后台服务器向Vue前端应用发送消息时,通过WebSocket向已连接的Vue客户端发送消息后台服务器可以根据消息类型和接收者,选择性地发送消息给指定的客户端。 5. Vue前端应用接收到后台服务器发送的消息后,进行逻辑处理,如显示消息内容或者执行其他相应操作。 需要注意以下几点: 1. 后台服务器需要保持WebSocket连接的活跃性,以便随时向前端应用发送消息。可以使用定时任务或者其他方式来检测和维持连接。 2. Vue前端应用需要在合适的时机关闭WebSocket连接,以释放资源。可以在Vue组件的生命周期钩子函数中处理关闭连接的逻辑。 总之,通过WebSocket实现后台消息推送,涉及到后台服务器的建立和维护,以及前端应用的连接和消息处理。可以根据实际需求选择合适的技术和工具,完成消息推送功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_bill

老板大气!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值