SpringCloud (if the microservice version is taken as an example) integrates WebSocket to implement message push between front and back ends

Scenes

SpringBoot+Vue integrates WebSocket to implement front-end and back-end message push:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/114392573

If you follow the microservice version to teach you how to build an environment locally and run the front-end and back-end projects:

https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/109363303

In the above, the process of using WebSocket on the basis of SpringBoot+Vue and the process of building a project with SpringCloud (Ruoyi microservice version) are introduced, if you use WebSocket in SpringCloud.

Note:

Blog:
https://blog.csdn.net/badao_liumang_qizhi
Follow the public
account Domineering
programmers Get programming-related e-books, tutorial pushes and free downloads.

achieve

First, add the WebSocket dependency under the service that needs to integrate WebSocket

        <!-- WebSocket-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

Here is placed under the timed task service

 

Then create a new config directory under the project package path, and create a new WebSocketConfig configuration class in this directory

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return  new ServerEndpointExporter();
    }
}

Then create a new websocket directory under the package, and create a new WebSocketClient client entity class in this directory to store the connected session uri

import javax.websocket.Session;

public class WebSocketClient {
    // 与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //连接的uri
    private String uri;

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }
}

Then create a new WebSocketService service class in this directory

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/websocket/{userName}")
@Component
public class WebSocketService {

    private static final Logger log = LoggerFactory.getLogger(WebSocketService.class);

    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
    private static ConcurrentHashMap<String, WebSocketClient> webSocketMap = new ConcurrentHashMap<>();


    /**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
    private Session session;
    /**接收userName*/
    private String userName="";
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session, @PathParam("userName") String userName) {
        if(!webSocketMap.containsKey(userName))
        {
            addOnlineCount(); // 在线数 +1
        }
        this.session = session;
        this.userName= userName;
        WebSocketClient client = new WebSocketClient();
        client.setSession(session);
        client.setUri(session.getRequestURI().toString());
        webSocketMap.put(userName, client);

        log.info("----------------------------------------------------------------------------");
        log.info("用户连接:"+userName+",当前在线人数为:" + getOnlineCount());
        try {
            sendMessage("来自后台的反馈:连接成功");
        } catch (IOException e) {
            log.error("用户:"+userName+",网络异常!!!!!!");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(webSocketMap.containsKey(userName)){
            webSocketMap.remove(userName);
            if(webSocketMap.size()>0)
            {
                //从set中删除
                subOnlineCount();
            }
        }
        log.info("----------------------------------------------------------------------------");
        log.info(userName+"用户退出,当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("收到用户消息:"+userName+",报文:"+message);
        //可以群发消息
        //消息保存到数据库、redis
        if(StringUtils.isNotBlank(message)){

        }
    }

    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("用户错误:"+this.userName+",原因:"+error.getMessage());
        error.printStackTrace();
    }

    /**
     * 连接服务器成功后主动推送
     */
    public void sendMessage(String message) throws IOException {
        synchronized (session){
            this.session.getBasicRemote().sendText(message);
        }
    }

    /**
     * 向指定客户端发送消息
     * @param userName
     * @param message
     */
    public static void sendMessage(String userName,String message){
        try {
            WebSocketClient webSocketClient = webSocketMap.get(userName);
            if(webSocketClient!=null){
                webSocketClient.getSession().getBasicRemote().sendText(message);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }


    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketService.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketService.onlineCount--;
    }

    public static void setOnlineCount(int onlineCount) {
        WebSocketService.onlineCount = onlineCount;
    }


    public static ConcurrentHashMap<String, WebSocketClient> getWebSocketMap() {
        return webSocketMap;
    }

    public static void setWebSocketMap(ConcurrentHashMap<String, WebSocketClient> webSocketMap) {
        WebSocketService.webSocketMap = webSocketMap;
    }

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}

Note that the WebSocketClient introduced here is newly created above

Find the configuration file of the gateway, here is to use Nacos as the configuration center. Let go of the websocket path for permission authentication

Here is the addition below ignore-whites at the end of ruoyi-gateway-dev.xml

    - /schedule/websocket/**

 

Here is to put the websocket under the service of the timed task, the route of this service is also in the configuration file of the gateway

 

Then for simplification and demonstration, here we directly call the service of the port under the timed task service without going through the gateway when using the websocket connection.

In order to test the push, you need to use the websocket client test tool, which can be solved by yourself, or use the following tool

https://download.csdn.net/download/BADAO_LIUMANG_QIZHI/15630118

Here, 9203 is used directly as the address of the specific timed task service, not the port of the gateway, and then the connected address is

ws://localhost:9203/websocket/badao

Badao is the UserName parameter passed. After entering the address, click Connect, you can see that the connection is successful

 

And click send data

 

It will also be received in the background.

Then create a test interface in the background

@RestController
@RequestMapping("/schedule/websocket")
public class WebSocketTestController {

    @GetMapping("/push")
    public void push(SysJobLog sysJobLog)
    {
        WebSocketService.sendMessage("badao","badao");
    }
}

After calling this interface, the client will also receive the sent data

 

Here is the use of client tools to test websocket, and then the front-end Vue integration websocket is the same as the integration process of the blog above.

Guess you like

Origin blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/114480731