Интеграция WebSockets JSR 356 Spring @ServerEndpoint

Проблема: bean-компоненты @Autowired в классе @ServerEndpoint имеют значение null

Как я могу убедиться, что этот класс WebSocketController ниже будет внедрен с помощью bean-компонентов, то есть как я могу сделать его управляемым Spring? Я могу подключиться к веб-сокету, чтобы он работал, но gameService всегда имеет значение null внутри экземпляра класса WebSocketController, поэтому я думаю, что он каким-то образом создан tomcat, а не Spring.

Я использую весеннюю загрузку. Мне просто нужно выяснить, как внедрить bean-компоненты в этот класс контроллера веб-сокета.

Класс WebSocketController

@Component
@ServerEndpoint("/sock")
public class WebSocketController {

    @Autowired
    private GameService gameService;

    private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());

    @OnMessage
    public void handleMessage(Session session, String message) throws IOException {

        session.getBasicRemote().sendText(
                "Reversed: " + new StringBuilder(message).reverse());
    }

    @OnOpen
    public void onOpen(Session session) {
        clients.add(session);
        System.out.println("New client @"+session.getId());
        if (gameService == null) System.out.println("game service null");
    }

    @OnClose
    public void onClose(Session session) {
        clients.remove(session);
        System.out.println("Client disconnected @" + session.getId());
    }
}

Интерфейс и реализация GameService

public interface GameService {
    List<Character> getCharacters();
}

@Service
public class GameServiceMockImpl implements GameService {

    @Override
    public List<Character> getCharacters() {
        List<Character> list = new ArrayList<>();
        list.add(new Character("aaa","1.png",100));
        list.add(new Character("aaa","2.jpg",100));
        list.add(new Character("aaa","3.jpg",100));
        return list;
    }
}

Класс приложения

@SpringBootApplication
public class App  {

    public static void main(String args[]){
        SpringApplication.run(App.class,args);
    }

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

}

РЕДАКТИРОВАТЬ:

Использование Spring 4 WebSockets вообще не работает, я даже не могу подключиться через браузер.

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(myHandler(), "/myHandler");
    }

    @Bean
    public WebSocketHandler myHandler() {
        return new MyHandler();
    }

}


public class MyHandler extends TextWebSocketHandler {

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        System.out.println(message.getPayload());
    }

}

person Greyshack    schedule 12.12.2015    source источник


Ответы (2)


Вы пытаетесь интегрировать Spring и Java WebSocket API. Класс, аннотированный @Component, регистрируется в bean-компоненте Spring, и его экземпляр управляется Spring, но если класс аннотируется @ServerEndpoint, он регистрируется в конечной точке WebSocket на стороне сервера, и каждый раз, когда WebSocket соответствующей конечной точки подключается к серверу, его экземпляр создается и управляется реализацией JWA. Мы не можем использовать обе аннотации вместе.

Либо вы можете использовать инъекцию CDI (ваш сервер также должен поддерживать)

@ServerEndpoint("/sock")
public class WebSocketController {

    @Inject
    private GameService gameService;

Или посмотрите этот документ , Spring 4 поддерживает WebSocket

person Pulkit    schedule 13.12.2015
comment
Спасибо за ответы. Я бы предпочел использовать Spring 4 WebSocket, и я хочу использовать «прямой подход» без SockJS и тому подобного. Поэтому я создал TextWebSocketHandler и WebSocketConfigurer. Но это не работает. Не могу подключиться из браузера. В консоли говорится, что он сопоставил данный URL-адрес с текстовым обработчиком, но все еще не может подключиться. Я добавил код в основной пост. - person Greyshack; 13.12.2015
comment
Мне пришлось разрешить подключения из других источников, и это работает. Итак, в конце концов, я использую веб-сокеты Spring 4. - person Greyshack; 13.12.2015
comment
Но только для тестов. В итоге все будет на сервере - person Greyshack; 13.12.2015

Может эта статья поможет:

https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support

Вы можете использовать зависимость (с весенней версией> 4)

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
</dependency>

А потом просто

@ServerEndpoint(value = "/echo", configurator = SpringConfigurator.class)
public class WebSocketEndpoint {

    @Inject
    private BroadcastService broadcaster;
person lanwen    schedule 11.07.2016
comment
Легко и приятно. Это то, что заставило меня работать! - person LordOfThePigs; 22.03.2017
comment
Не могли бы вы кратко объяснить этот код. Пожалуйста! Я не понимаю, как использовать этот фрагмент кода. - person susan097; 01.08.2018
comment
@Sushant Вы можете прочитать статью spring .io/blog/2013/05/23/ - там все пояснения в лучшем виде - person lanwen; 02.08.2018