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

问题描述 投票:19回答:2

我尝试通过Websocket使用Spring。我以this tutorial开始调查。

在我的副客户端中,我有类似的东西可以初始化与服务器的连接:

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方法,但是客户端没有任何反应。有什么建议么 ?谢谢。

spring sockjs spring-websocket
2个回答
36
投票

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

0
投票

如@Boris the Spider所建议的,安排定期任务的一种更好的方法是使用Spring计划机制(请参阅this guide

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

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

@Component
public class ScheduledTasks {

    @Autowired
    private SimpMessagingTemplate template;

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

并将@EnableScheduling标记添加到您的Application类。

© www.soinside.com 2019 - 2024. All rights reserved.