场景


SpringBoot+Vue整合WebSocket实现前后端消息推送:


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


若依微服务版手把手教你本地搭建环境并运行前后端项目:


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


在上面介绍了在SpringBoot+Vue的基础上使用WebSocket的过程以及使用SpringCloud(若依微服务版)搭建项目的基础上,如果在SpringCloud中使用WebSocket的过程。


实现


首先在需用集成WebSocket的服务下面添加WebSocket的依赖


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

这里是放在定时任务服务下面


 SpringCloud(若依微服务版为例)集成WebSocket实现前后端的消息推送_java


然后在项目包路径下新建config目录,在此目录下新建WebSocketConfig配置类



import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configurationpublic class WebSocketConfig {     @Bean    public ServerEndpointExporter serverEndpointExporter(){        return  new ServerEndpointExporter();    }}

然后在包下新建websocket目录,在此目录下新建WebSocketClient客户端实体类用来存储连接的会话个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;    }}

然后还在此目录下新建WebSocketService服务类



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}")@Componentpublic 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;    } }

注意这里引入的WebSocketClient是上面新建的


找到网关的配置文件,这里是使用Nacos作为配置中心。将websocket的路径放开权限认证


这里是在ruoyi-gateway-dev.xml最后面的ignore-whites下面添加



    - /schedule/websocket/**



这里是将websocket放在定时任务这个服务下面,这个服务的路由也在网关的配置文件中


 SpringCloud(若依微服务版为例)集成WebSocket实现前后端的消息推送_java_02




然后为了简单化以及演示,这里直接在使用websocket的连接时直接不走网关,直接调用定时任务服务下的端口的服务


为了进行推送的测试,需要使用websocket客户端的测试工具,具体可自行解决,或者使用下面的工具


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


这里直接使用9203是具体定时任务服务的地址,而不是网关的端口,然后连接的地址为


ws://localhost:9203/websocket/badao


其中badao是传递的UserName参数,输入地址后点击连接,可以看到连接成功


 SpringCloud(若依微服务版为例)集成WebSocket实现前后端的消息推送_java_03

并且点击发送数据


SpringCloud(若依微服务版为例)集成WebSocket实现前后端的消息推送_java_04


后台也会收到。


然后在后台新建一个测试的接口



@RestController@RequestMapping("/schedule/websocket")public class WebSocketTestController {     @GetMapping("/push")    public void push(SysJobLog sysJobLog)    {        WebSocketService.sendMessage("badao","badao");    }}

调用此接口后,客户端也会收到发送的数据

SpringCloud(若依微服务版为例)集成WebSocket实现前后端的消息推送_java_05

这里是使用客户端工具来测试websocket,然后前端Vue集成websocket和上面的博客的集成流程一样。