Spring - 在事件上向 websocket 发送消息

val*_*0ne 3 java events spring websocket

我遇到以下情况:每次触发事件时,我需要在 websocket 上发送消息。

消息控制器.java

@Controller
public class MessageController {

    @Autowired
    private SimpMessagingTemplate template;

    @RequestMapping(path="/messages", method=POST)
    public void send(String message) {
        this.template.convertAndSend("/topic/messages", message);
    }
}
Run Code Online (Sandbox Code Playgroud)

KafkaConsumeEventHandler.java

@Component
public class KafkaConsumeEventHandler implements ApplicationListener<KafkaConsumeEvent> {

    private static final Logger LOGGER = LoggerFactory.getLogger(KafkaConsumeEventHandler.class);

    public void onApplicationEvent(final KafkaConsumeEvent event) {
        LOGGER.info("event detected: publishing...");
        LOGGER.info("message to be published: {}",event.getMessage());
        //INVOKE CONTROLLER TO SEND MESSAGE HERE
        LOGGER.info("event published to websocket.");

    }

}
Run Code Online (Sandbox Code Playgroud)

是否可以send()在事件处理程序中调用控制器的方法?有更好的方法吗?

编辑 如果我在this.template.convertAndSend("/topic/messages", message);事件处理程序内部执行(自动装配 SimMessagingTemplate),我会得到一个 nullPointerException

loc*_*s2k 6

使用可以随时调用的方法创建您自己的通信服务类。我所做的是创建一个CommService带有静态方法的类来发送

public class CommService {

  private static SimpMessagingTemplate template;

  public static void setTemplate(SimpMessagingTemplate tmplt) {
    template = tmplt;
  }

  public static void send(String message) {
    template.convertAndSend("/topic/messages", message);
  }
}
Run Code Online (Sandbox Code Playgroud)

CommService然后你可以通过以下方式初始化ContextRefreshHandler

@Component
public class ContextRefreshedHandler implements ApplicationListener<ContextRefreshedEvent> {

  private static Logger logger = LoggerFactory.getLogger(ContextRefreshedHandler.class);

  @Autowired
  private SimpMessagingTemplate template;

  @Override
  public void onApplicationEvent(ContextRefreshedEvent event) {
    try {
      //Initialize the template for web socket messages
      CommService.setTemplate(template);
    } catch (Exception ex) {
      logger.error(getClass().getName(), ex);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这将在服务器启动时初始化您的模板,然后在您需要发送您刚刚使用的消息的整个应用程序中初始化您的模板CommService.send("message");

所以你可以将你的更改MessageController为这个

@Controller
public class MessageController {

  @Autowired
  private SimpMessagingTemplate template;

  @RequestMapping(path="/messages", method=POST)
  public void send(String message) {
    CommService.send(message);
  }
}
Run Code Online (Sandbox Code Playgroud)