Как отправить сообщение клиенту через веб-сокет с помощью Spring

Я пытаюсь использовать Spring с веб-сокетом. Я начал свое исследование с этого руководства.

В моем стороннем клиенте у меня есть что-то подобное для инициализации соединения с сервером:

function connect() {
    var socket = new SockJS('/myphotos/form');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function(frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function(greeting){
            showGreeting(JSON.parse(greeting.body).content);
        });
    });
}

Он отлично работает, в моем контроллере я могу выполнять свой процесс в следующем классе:

@Controller
@RequestMapping("/")
public class PhotoController {

    @MessageMapping("/form")
    @SendTo("/topic/greetings")
    public Greeting validate(AddPhotosForm addPhotosForm) {
        return new Greeting("Hello world !");
    }
}

Теперь то, что я хочу сделать, это иметь поток, отправляющий сообщение клиенту, прослушивающему «/topic/greeting». Я написал свой класс Runnable следующим образом:

public class FireGreeting implements Runnable {

    private PhotoController listener;

    public FireGreeting(PhotoController listener) {
        this.listener = listener;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep( 2000 );
                listener.fireGreeting();
            } catch ( InterruptedException e ) {
                e.printStackTrace();
            }
        }   
    }
}

И завершил мой контроллер следующим образом:

@Controller
@RequestMapping("/")
public class PhotoController {

    @MessageMapping("/form")
    @SendTo("/topic/greetings")
    public Greeting validate(AddPhotosForm addPhotosForm) {

        // added this part
        FireGreeting r = new FireGreeting( this );
        new Thread(r).start();

        return new Greeting("Hello world !");
    }

    // added this method
    @SendTo("/topic/greetings")
    public Greeting fireGreeting() {
        System.out.println("Fire");
        return new Greeting("Fire");
    }
}

Метод PhotoController.fireGreeting вызывается так, как я хочу, но на стороне клиента ничего не происходит. Какие-либо предложения ? Спасибо.


person cheb1k4    schedule 31.01.2015    source источник
comment
Прочтите 21.4.5 Отправка сообщений из учебника Spring Websocket. Это, конечно, не так, как вы это делаете. Также подумайте о том, чтобы прочитать о Spring планировании. механизм вместо использования необработанных потоков (неправильно).   -  person Boris the Spider    schedule 31.01.2015
comment
Спасибо за ссылку, это именно то, что я хочу сделать. О потоке, который я использую, очевидно, я не буду использовать его в финальном состоянии своего приложения. У меня есть длинный процесс на стороне сервера, который будет отправлять информацию клиенту, чтобы сообщить ему, какие шаги уже сделаны.   -  person cheb1k4    schedule 31.01.2015


Ответы (2)


Я смог решить свою проблему благодаря @Boris the Spider. Правильное решение - сделать что-то вроде этого:

@Controller
@RequestMapping("/")
public class PhotoController {

    @Autowired
    private SimpMessagingTemplate template;

    @MessageMapping("/form")
    @SendTo("/topic/greetings")
    public Greeting validate(AddPhotosForm addPhotosForm) {

        FireGreeting r = new FireGreeting( this );
        new Thread(r).start();

        return new Greeting("Hello world !");
    }

    public void fireGreeting() {
        System.out.println("Fire");
        this.template.convertAndSend("/topic/greetings", new Greeting("Fire"));
    }
}
person cheb1k4    schedule 31.01.2015
comment
Какой класс MessageChannel используется с внедренным SimpMessagingTemplate? - person clD; 22.12.2020

Как предложил @Boris the Spider, лучший способ планировать периодические задачи — использовать механизмы планирования Spring (см. это руководство).

Ради разделения проблем я бы также отделил код, связанный с расписанием, от кода контроллера.

В вашем случае вы можете использовать такой класс:

@Component
public class ScheduledTasks {

    @Autowired
    private SimpMessagingTemplate template;

    @Scheduled(fixedRate = 2000)
    public void fireGreeting() {
        this.template.convertAndSend("/topic/greetings", new Greeting("Fire"));
    }
}

И добавьте тег @EnableScheduling в свой класс приложения.

person mfilippo    schedule 09.10.2019