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包:
其次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;
}
简单的消息推送就完成了,全是干货,粘贴即用,需要深入研究其他需求的可以看看官方的具体调用方法