spring 如何使用Spring通过websocket向客户端发送消息

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28250719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:20:32  来源:igfitidea点击:

How to send message to client through websocket using Spring

springsockjsspring-websocket

提问by cheb1k4

I try to use Spring with websocket. I started my investigation with this tutorial.

我尝试将 Spring 与 websocket 一起使用。我从本教程开始我的调查。

In my side client I have something like that to initialize the connection to the server :

在我的侧面客户端中,我有类似的东西来初始化与服务器的连接:

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);
        });
    });
}

It works great, in my controller I'm able to do my process in the following class :

它工作得很好,在我的控制器中,我可以在以下课程中完成我的过程:

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

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

Now what I want to do it's having a thread sending a message to the client listening on “/topic/greeting”. I wrote my Runnable class like this :

现在我想做的是让一个线程向客户端发送一条消息,监听“/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();
            }
        }   
    }
}

And completed my controller like that :

并像这样完成了我的控制器:

@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");
    }
}

The method PhotoController.fireGreeting is called as I want but nothing happened on the client side. Any suggestions ? Thank you.

PhotoController.fireGreeting 方法按照我的意愿被调用,但在客户端什么也没发生。有什么建议 ?谢谢你。

回答by cheb1k4

I was able to solve my problem thanks to @Boris the Spider. The correct solution is to do something like that :

感谢@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"));
    }
}

回答by mfilippo

A better way to schedule periodic tasks is, as suggested by @Boris the Spider, to use Spring scheduling mechanisms (see this guide).

正如@Boris the Spider 所建议的那样,调度周期性任务的更好方法是使用 Spring 调度机制(请参阅本指南)。

For the sake of Separation of Concerns, I would also separate scheduled-related code from controller code.

为了关注点分离,我还将与调度相关的代码与控制器代码分开。

In your case you could use a class like this one:

在您的情况下,您可以使用这样的类:

@Component
public class ScheduledTasks {

    @Autowired
    private SimpMessagingTemplate template;

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

And add the @EnableSchedulingtag to your Application class.

并将@EnableScheduling标签添加到您的应用程序类。