如何使用 Spring 通过 websocket 向客户端发送消息
How to send message to client through websocket using Spring
我尝试将 Spring 与 websocket 一起使用。我从 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);
});
});
}
效果很好,在我的控制器中,我可以按以下方式执行我的过程 class :
@Controller
@RequestMapping("/")
public class PhotoController {
@MessageMapping("/form")
@SendTo("/topic/greetings")
public Greeting validate(AddPhotosForm addPhotosForm) {
return new Greeting("Hello world !");
}
}
现在我要做的是让一个线程向监听“/topic/greeting”的客户端发送消息。我这样写我的 Runnable class :
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如我所愿被调用,但客户端没有任何反应。
有什么建议么 ?谢谢。
感谢@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"));
}
}
根据 @Boris the Spider 的建议,安排周期性任务的更好方法是使用 Spring 调度机制(参见 this guide)。
为了关注点分离,我也会将与调度相关的代码与控制器代码分开。
在您的情况下,您可以使用像这样的 class:
@Component
public class ScheduledTasks {
@Autowired
private SimpMessagingTemplate template;
@Scheduled(fixedRate = 2000)
public void fireGreeting() {
this.template.convertAndSend("/topic/greetings", new Greeting("Fire"));
}
}
并将 @EnableScheduling
标签添加到您的应用程序 class。
我尝试将 Spring 与 websocket 一起使用。我从 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);
});
});
}
效果很好,在我的控制器中,我可以按以下方式执行我的过程 class :
@Controller
@RequestMapping("/")
public class PhotoController {
@MessageMapping("/form")
@SendTo("/topic/greetings")
public Greeting validate(AddPhotosForm addPhotosForm) {
return new Greeting("Hello world !");
}
}
现在我要做的是让一个线程向监听“/topic/greeting”的客户端发送消息。我这样写我的 Runnable class :
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如我所愿被调用,但客户端没有任何反应。 有什么建议么 ?谢谢。
感谢@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"));
}
}
根据 @Boris the Spider 的建议,安排周期性任务的更好方法是使用 Spring 调度机制(参见 this guide)。
为了关注点分离,我也会将与调度相关的代码与控制器代码分开。
在您的情况下,您可以使用像这样的 class:
@Component
public class ScheduledTasks {
@Autowired
private SimpMessagingTemplate template;
@Scheduled(fixedRate = 2000)
public void fireGreeting() {
this.template.convertAndSend("/topic/greetings", new Greeting("Fire"));
}
}
并将 @EnableScheduling
标签添加到您的应用程序 class。