react+springboot 结合websocket实现即时通信

react前端界面使用websoket:

(注意:不能在生命周期函数内调用websocket)

在用户登录的时候调用:

const ws = new WebSocket('ws://192.168.1.118:8080//productWebSocket/001');    //切记需要用ws或者wss,不能使用http

        ws.onopen = function (e) {

          console.log('连接上 ws 服务端了');

        }

        ws.onmessage = (msg)=> { 

            console.log('接收服务端发过来的消息: %o', msg); 


        }; 

        ws.onclose = function (e) {

            console.log('ws 连接关闭了');

            console.log(e);

        }

前端代码就这么简单;onopen的回调函数,标识与服务器成功连接,onmassage回调函数为后端服务器推送过来的消息


java代码部分:

首先引入jar包:

org.springframework.boot

spring-boot-starter-websocket


其次websocket工具类  WebSocketConfig和MyEndpointConfigure


import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**

* 开启WebSocket支持

* @author zhengkai.blog.csdn.net

*/

@Configuration

public class WebSocketConfig {

@Bean

    public ServerEndpointExporter serverEndpointExporter() {

return new ServerEndpointExporter();

}

@Bean

    public MyEndpointConfigure newConfigure() {

return new MyEndpointConfigure();

}

}

-------------------------------------------------------------------------------------------------------------------------------------------------------

import javax.websocket.server.ServerEndpointConfig;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.BeanFactory;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

/**

* @Author:JCccc

* @Description:

* @Date: created in 15:56 2019/5/13

*/

public class MyEndpointConfigureextends ServerEndpointConfig.Configuratorimplements ApplicationContextAware {

private static volatile BeanFactorycontext;

@Override

    public T getEndpointInstance(Class clazz)throws InstantiationException {

return context.getBean(clazz);

}

@Override

    public void setApplicationContext(ApplicationContext applicationContext)throws BeansException {

MyEndpointConfigure.context = applicationContext;

}

}




再次逻辑层的service创建ProductWebSocket

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import java.util.concurrent.CopyOnWriteArraySet;

import java.util.concurrent.atomic.AtomicInteger;

import javax.websocket.OnClose;

import javax.websocket.OnError;

import javax.websocket.OnMessage;

import javax.websocket.OnOpen;

import javax.websocket.Session;

import javax.websocket.server.PathParam;

import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

import road.system.config.MyEndpointConfigure;

/**

* @Author:JCccc

* @Description:

* @Date: created in 15:56 2019/5/13

*/

@Component

@ServerEndpoint(value ="/productWebSocket/{userId}", configurator = MyEndpointConfigure.class)

public class ProductWebSocket {

// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。

    private static final AtomicIntegerOnlineCount =new AtomicInteger(0);

// concurrent包的线程安全Set,用来存放每个客户端对应的ProductWebSocket对象。

    private static CopyOnWriteArraySetwebSocketSet =new CopyOnWriteArraySet();

// 与某个客户端的连接会话,需要通过它来给客户端发送数据

    private Sessionsession;

private Loggerlog = LoggerFactory.getLogger(ProductWebSocket.class);

/**

* 连接建立成功调用的方法

*/

    @OnOpen

    public void onOpen(@PathParam("userId")String userId, Session session) {

log.info("新客户端连入,用户id:" + userId);

this.session = session;

webSocketSet.add(this);// 加入set中

        addOnlineCount();// 在线数加1

        if(userId!=null) {

List totalPushMsgs =new ArrayList();

totalPushMsgs.add(userId+"连接成功-"+"-当前在线人数为:"+getOnlineCount());

if(totalPushMsgs !=null && !totalPushMsgs.isEmpty()) {

totalPushMsgs.forEach(e -> sendMessage(e));

}

}

}

/**

* 连接关闭调用的方法

*/

    @OnClose

    public void onClose() {

log.info("一个客户端关闭连接");

webSocketSet.remove(this);// 从set中删除

        subOnlineCount();// 在线数减1

    }

/**

* 收到客户端消息后调用的方法

*

    * @param message

    *            客户端发送过来的消息

*/

    @OnMessage

    public void onMessage(String message, Session session) {

log.info("用户发送过来的消息为:"+message);

}

/**

* 发生错误时调用

*/

    @OnError

    public void onError(Session session, Throwable error) {

log.error("websocket出现错误");

error.printStackTrace();

}

public void sendMessage(String message) {

try {

this.session.getBasicRemote().sendText(message);

log.info("推送消息成功,消息为:" + message);

}catch (IOException e) {

e.printStackTrace();

}

}

/**

* 群发自定义消息

*/

    public static void sendInfo(String message)throws IOException {

for (ProductWebSocket productWebSocket :webSocketSet) {

productWebSocket.sendMessage(message);

}

}

public static synchronized int getOnlineCount() {

return OnlineCount.get();

}

public static synchronized void addOnlineCount() {

OnlineCount.incrementAndGet();// 在线数+1

    }

public static synchronized void subOnlineCount() {

OnlineCount.decrementAndGet();// 在线数-1

    }

}


最后,在controllerceng调用类的方法

我这里是后端给前端推送消息,所以代码调用了  sendInfo 这个方法

@RequestMapping("/push")

@ResponseBody

public JSONObject pushToWeb( String message)throws IOException {

message ="发送消息";

System.out.println("开始发送消息");

ProductWebSocket.sendInfo(message);

JSONObject json =new JSONObject();

json.put("code","200");

return json;

}


简单的消息推送就完成了,全是干货,粘贴即用,需要深入研究其他需求的可以看看官方的具体调用方法

你可能感兴趣的:(react+springboot 结合websocket实现即时通信)