Springboot集成WebSocket

WebSocket是一種網絡通訊協議,熟悉計算機網絡的人都知道,通常咱們採用的http請求,都是請求/響應的模式,即客戶端發起請求,服務端從而對客戶端的請求作出相應的響應,然而服務端通常都不能主動的往客戶端發消息,WebSocket正好解決這一問題,本文采用springboot集成WebSocket;web

(1)在pom.xml中加入依賴:spring

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
複製代碼

(2)建立一個WebSocketConfig類,在其中寫入後端

@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
    return new ServerEndpointExporter();
   }
}
複製代碼

(3)建立一個SocketServer類,在其中寫入:springboot

@ServerEndpoint(value = "/socketServer/{productId}/{mapId}")
@Component
@Slf4j
public class SocketServer {

private static final String ADMIN_USER = "server-admin";
private Session session;
private static Map<String,Session> sessionPool = new HashMap<String,Session>();
private static Map<String,String> sessionIds = new HashMap<String,String>();

private MonitorService monitorService;

private DeviceService deviceService;

private String handshake;

private String getMapId;

public static String productCopyId;
public static String mapCopyId;


private static ApplicationContext applicationContext;

public static void setApplicationContext(ApplicationContext context){
	applicationContext = context;
}

/**
 * 用戶鏈接時觸發
 * @param productId productId
 * @param mapId mapId
 * @param session session
 */
@OnOpen
public void open(Session session, @PathParam(value="productId")String productId, @PathParam(value="mapId")String mapId)throws Exception{
	log.info("{{}}握手成功{{}}",productId,mapId);
	this.session = session;
	handshake = productId;
	getMapId = mapId;
	productCopyId = productId;
	mapCopyId = mapId;
	sessionPool.put(productId, session);
	sessionIds.put(session.getId(), productId);

	sendMessage(handshake,handshake);
}

/**
 * 收到信息時觸發
 * @param message message
 */
@OnMessage
public void onMessage(String message){

	log.info("發送人:"+sessionIds.get(session.getId())+"內容:"+message);

}

/**
 * 鏈接關閉觸發
 */
@OnClose
public void onClose(){
	sessionPool.remove(sessionIds.get(session.getId()));
	sessionIds.remove(session.getId());
}

/**
 * 發生錯誤時觸發
 * @param session session
 * @param error error
 */
@OnError
public void onError(Session session, Throwable error) {
	error.printStackTrace();
}

/**
 *信息發送的方法
 * @param message message
 * @param clientId clientId
 */
public synchronized static void sendMessage(String message,String clientId) throws Exception{
	log.info("sendMessage方法被調用");
	Session s = sessionPool.get(clientId);
	if(s!=null){
		try {
			log.info("{{}}sendMessage發送的消息爲{{}}",clientId ,message);
			s.getBasicRemote().sendText(message);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

/**
 * 獲取當前鏈接數
 * @return int
 */
public synchronized static int getOnlineNum(){
	if(sessionIds.values().contains(ADMIN_USER)) {

		return sessionPool.size()-1;
	}
	return sessionPool.size();
}

/**
 * 獲取在線用戶名以逗號隔開
 * @return String
 */
public synchronized static String getOnlineUsers(){
	StringBuffer clientIds = new StringBuffer();
	for (String key : sessionIds.keySet()) {
		if (!ADMIN_USER.equals(sessionIds.get(key)))
		{
			clientIds.append(sessionIds.get(key)+",");
		}
	}
	return clientIds.toString();
}

/**
 * 信息羣發
 * @param msg
 */
public synchronized static void sendAll(String msg) throws Exception{
	for (String key : sessionIds.keySet()) {
		if (!ADMIN_USER.equals(sessionIds.get(key)))
		{
			sendMessage(msg, sessionIds.get(key));
		}
	}
}

/**
 * 多我的發送給指定的幾個用戶
 * @param msg
 * @param clientIds  用戶
 */

public synchronized static void SendMany(String msg,String [] clientIds) throws Exception{
	log.info("SendMany方法被調用");
	for (String clientId : clientIds) {
		sendMessage(msg, clientId);
	}

  }
}
複製代碼

至此,後端的工做基本完成了;websocket

推廣一下,若是在springboot中的SocketServer類想要加載Service類,它是加載不到的,因此須要在該類中加入如下代碼:網絡

private static ApplicationContext applicationContext;

public static void setApplicationContext(ApplicationContext context){
	applicationContext = context;
}
複製代碼

用以加載springboot中的Bean類;session

而後用如下代碼加載該Beanapp

deviceService = applicationContext.getBean(DeviceService.class);
複製代碼

最後,須要在啓動類中加入如下代碼,才能加載到Beansocket

ConfigurableApplicationContext applicationContext = SpringApplication.run(DemoApplication.class, args);
複製代碼

其中DemoApplication爲啓動類的類名,至此就能夠了;(備註:若是本文侵權,請聯繫做者刪除)spring-boot

相關文章
相關標籤/搜索