SpringBoot使用WebSocket


WebSocket 介紹

WebSocket 是一種建立在TCP之上的協議,主要用於解決服務器和客戶端雙向通話問題,具體可以參考 阮一峰WebSocket教程

Java Web項目使用WebSocket

JSR356 中對Java WebSocket API 有詳細的規定,包含客戶端API和服務端API,在使用java編寫客戶端時,利用注解是比較方便的方式,在類上添加@ClientEndpoint, 在不同的方法上添加@OnOpen @OnClose @OnError @OnMessage來處理不同的事件。

使用JAVA更多應用場景是提供WebSocket服務,同樣也是通過注解的方式可以快速實現,在類上添加@ServerEndpoint,如

@ServerEndpoint("/game/{gameType}")
public class GameServer {

  @OnOpen
  public open () {...}
  
  @OnClose
  public close() {...}

  @OnMessage
  public message() {...}

  @OnError
  public error() {...}
}

通過上述的編碼,可以獲得一個地址類似 ws[s]😕/ip:port/game/type1 的WebSocket服務,要想獲取gameType的值,可以使用@PathParam 注解

@OnMessage
public message(@PathParam("gameType") String gameType) {...}

Spring 中使用WebSocket

Java Web 最常用的框架自然是Spring莫屬,在Spring中可以直接使用Java WebSocket API來提供服務,如果使用內置的web容器,需要做的僅僅是需要在配置文件中添加

    /**
	 * The bean shown in the preceding example registers any @ServerEndpoint
	 * annotated beans with the underlying WebSocket container. When deployed to a
	 * standalone servlet container, this role is performed by a servlet container
	 * initializer, and the ServerEndpointExporter bean is not required.
	 * 
	 * @return
	 */
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}

Spring 對WebSocket 也提供了一定的封裝支持,可以參考Spring 的官網說明, 其實也比較簡單,下面是我參考官網寫的一段代碼

package com.iflytek.research.storage.config;

import javax.annotation.Resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import com.iflytek.research.storage.repository.FileObjectRepository;
import com.iflytek.research.storage.repository.UserRepository;
import com.iflytek.research.storage.websocket.SearchHandler;

/**
 * 開啟WebSocket支持
 * 參考:https://docs.spring.io/spring/docs/5.1.2.RELEASE/spring-framework-reference/web.html#websocket
 * 
 * @author ljgeng
 */
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
	
	@Resource
	FileObjectRepository fileObjectRepository;
	
	@Resource
	UserRepository userRepository;
	
	@Override
	public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
		registry.addHandler(new SearchHandler(fileObjectRepository,userRepository), "/api/search/**/").setAllowedOrigins("*");
	}
	

	/**
	 * The bean shown in the preceding example registers any @ServerEndpoint
	 * annotated beans with the underlying WebSocket container. When deployed to a
	 * standalone servlet container, this role is performed by a servlet container
	 * initializer, and the ServerEndpointExporter bean is not required.
	 * 
	 * @return
	 */
	@Bean
	public ServerEndpointExporter serverEndpointExporter() {
		return new ServerEndpointExporter();
	}
	
}

Spring Security 和 WebSocket

我的項目是使用SpringBoot 搭建的,同時引入了Spring Security 來做安全管理,在發布WebSocket服務並不用過多處理,在上述的SearchHandler中,它繼承了TextWebSocketHandler,在重新實現handleTextMessage方式時,其中有一個參數WebSocketSession就包含了用戶信息

public class SearchHandler extends TextWebSocketHandler {
	
	private final FileObjectRepository fileObjectRepository;
	private final UserRepository userRepository;
	
	public SearchHandler(FileObjectRepository fileObjectRepository,UserRepository userRepository) {
		this.fileObjectRepository = fileObjectRepository;
		this.userRepository = userRepository;
	}

	@Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        // 當前用戶賬號
        Principal  principal = session.getPrincipal();
        String username = principal.getName();
        ...
    }
    ...
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM