react前端界面使用websoket:
(注意:不能在生命周期函數(shù)內調用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('接收服務端發(fā)過來的消息:?%o',?msg);?
????????};?
????????ws.onclose?=?function?(e)?{
????????????console.log('ws?連接關閉了');
????????????console.log(e);
????????}
前端代碼就這么簡單烤宙;onopen的回調函數(shù)钠糊,標識與服務器成功連接撵摆,onmassage回調函數(shù)為后端服務器推送過來的消息
java代碼部分:
首先引入jar包:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
其次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創(chuàng)建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 {
// 靜態(tài)變量剂跟,用來記錄當前在線連接數(shù)。應該把它設計成線程安全的象缀。
? ? private static final AtomicIntegerOnlineCount =new AtomicInteger(0);
// concurrent包的線程安全Set跪削,用來存放每個客戶端對應的ProductWebSocket對象。
? ? private static CopyOnWriteArraySetwebSocketSet =new CopyOnWriteArraySet();
// 與某個客戶端的連接會話陵刹,需要通過它來給客戶端發(fā)送數(shù)據(jù)
? ? 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();// 在線數(shù)加1
? ? ? ? if(userId!=null) {
List totalPushMsgs =new ArrayList();
totalPushMsgs.add(userId+"連接成功-"+"-當前在線人數(shù)為:"+getOnlineCount());
if(totalPushMsgs !=null && !totalPushMsgs.isEmpty()) {
totalPushMsgs.forEach(e -> sendMessage(e));
}
}
}
/**
* 連接關閉調用的方法
*/
? ? @OnClose
? ? public void onClose() {
log.info("一個客戶端關閉連接");
webSocketSet.remove(this);// 從set中刪除
? ? ? ? subOnlineCount();// 在線數(shù)減1
? ? }
/**
* 收到客戶端消息后調用的方法
*
? ? * @param message
? ? *? ? ? ? ? ? 客戶端發(fā)送過來的消息
*/
? ? @OnMessage
? ? public void onMessage(String message, Session session) {
log.info("用戶發(fā)送過來的消息為:"+message);
}
/**
* 發(fā)生錯誤時調用
*/
? ? @OnError
? ? public void onError(Session session, Throwable error) {
log.error("websocket出現(xiàn)錯誤");
error.printStackTrace();
}
public void sendMessage(String message) {
try {
this.session.getBasicRemote().sendText(message);
log.info("推送消息成功,消息為:" + message);
}catch (IOException e) {
e.printStackTrace();
}
}
/**
* 群發(fā)自定義消息
*/
? ? 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();// 在線數(shù)+1
? ? }
public static synchronized void subOnlineCount() {
OnlineCount.decrementAndGet();// 在線數(shù)-1
? ? }
}
最后衰琐,在controllerceng調用類的方法
我這里是后端給前端推送消息也糊,所以代碼調用了 ?sendInfo 這個方法
@RequestMapping("/push")
@ResponseBody
public JSONObject pushToWeb( String message)throws IOException {
message ="發(fā)送消息";
System.out.println("開始發(fā)送消息");
ProductWebSocket.sendInfo(message);
JSONObject json =new JSONObject();
json.put("code","200");
return json;
}
簡單的消息推送就完成了,全是干貨羡宙,粘貼即用狸剃,需要深入研究其他需求的可以看看官方的具體調用方法