Spring Boot WebSocket Обмен сообщениями и данными в реальном времени

WebSocket

Во-первых, достичь цели

  • 1. Онлайн-чат, чат обслуживания клиентов, чат
  • 2. Отображение бизнес-данных в режиме реального времени, автоматическое обновление

Во-вторых, отрабатывайте шаги

Ниже приведен к достижению:业务数据实时展示,自动更新

1. Введение в Maven

<dependency>  
   <groupId>org.springframework.boot</groupId>  
   <artifactId>spring-boot-starter-websocket</artifactId>  
</dependency> 

2. Создайте файл конфигурации

WebSocketConfig

/**
 * 开启WebSocket支持
 * @author zhengkai
 */
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3. Создайте сервер

@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

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

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this);
        sendMessage("连接成功");
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        log.info("有一连接关闭!");
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param queryType 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String queryType) {
        log.info("收到信息:" + queryType);

        //群发消息
        for (WebSocketServer item : webSocketSet) {
            item.sendMessage("hello");
        }
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(Object message) {
        try {
            this.session.getBasicRemote().sendText(JSON.toJSONString(message));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 实现服务器主动群发消息
     */
    public static void sendInfo(Object message) {
        for (WebSocketServer item : webSocketSet) {
            item.sendMessage(message);
        }
    }
}

4. Ведущий конец, инициирующий веб-сокет запроса

  <script> 
    var socket;  
    if(typeof(WebSocket) == "undefined") {  
        console.log("您的浏览器不支持WebSocket");  
    }else{  
        console.log("您的浏览器支持WebSocket");  
        	//实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接  
            socket = new WebSocket("ws://localhost:8080/webscoket");
            //打开事件  
            socket.onopen = function() {  
                console.log("Socket 已打开");  
                //socket.send("这是来自客户端的消息" + location.href + new Date());  
            };  
            //获得消息事件  
            socket.onmessage = function(msg) {  
                console.log(msg.data);  
                //发现消息进入    开始处理前端触发逻辑
            };  
            //关闭事件  
            socket.onclose = function() {  
                console.log("Socket已关闭");  
            };  
            //发生了错误事件  
            socket.onerror = function() {  
                alert("Socket发生了错误");  
                //此时可以尝试刷新页面
            } 
    }
    </script> 

В-третьих, проблемы, возникающие на практике.

1. Websocket дистанционный инициирующий запрос, но не может подключать WebSocket

  • Ошибка 1: перехвачено разрешениями, такими как Spring Security Решение: отмените разрешения или разрешите доступ
// spring security
.antMatchers(
    "/websocket"
    )
.permitAll()

  • Ошибка 2: запрошенный адрес веб-сокета неверен
@ServerEndpoint(value = "/websocket")

对应的地址是:ws://localhost:8080/webscoket
  • Ошибка 3: перехват АОП
@Pointcut("execution(public * com.xxx.xxx.controller..*(..))")
public void webLog() {
}

Решение

// 排除拦截
@Pointcut("execution(public * com.xxx.xxx.controller..*(..)) && !execution(public * com.xxx.xxx.controller.xxx*(..))")
public void webLog() {
}

2. В WebSocketServer нельзя внедрить Bean и нельзя использовать @Autowired.

То есть, если вы используете @Autowired напрямую следующим образом, будет сообщено об ошибке

@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {
    @Autowired
    ChartDataService chartDataService;
}

В Webbocket, потому что Springboot + Websocket создает Websocketserver (соответствующий объекту @serverencepoint antaution) для каждого клиентского соединения, операция впрыска компонентов бобов будет пропущена напрямую, поэтому глобальная переменная (то есть фасоль, который вам нужен ввод), является вручную вводят.

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    // 在这里注入你需要的bean
    @Autowired
    public void setMessageService(ChartDataService chartDataService) {
        WebSocketServer.chartDataService = chartDataService;
        // ...
    }
}

используйте инъецированный боб

@ServerEndpoint(value = "/websocket")
@Component
public class WebSocketServer {

    public static ChartDataService chartDataService;

Этот метод практиковался и эффективен

Другие решения:stackoverflow.com/questions/2…

  • 1. Используйте @Inject
@ServerEndpoint("/ws")
public class MyWebSocket {   
    @Inject
    private ObjectMapper objectMapper;
}
  • 2. Использование SpringConfigurator
@ServerEndpoint(value = "/ws", configurator = SpringConfigurator.class)
  • 3. Используйте @PostConstruct
@PostConstruct
public void init(){
    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}

После практики вышеперечисленные три способа для меня недействительны

Ссылка на ссылку:blog.CSDN.net/Mo show game/…