spring - 奇怪的行为 - websocket spring - 使用监听/通知 postgresql 向用户发送消息
问题描述
我的 spring boot websocket 设置出现了奇怪的行为。有时有效,有时无效,只是感觉很随意。我已经尝试了几种设置,但没有一个被证明是可靠的:我将最后一段代码移动到应用程序主类中的命令行运行程序中,最后一个选择是带有 @Component 注释的不同类。
我的设置如下:我使用 jdbc 驱动程序 (pgjdbc-ng) 来使用 postgres 的监听通知功能。我有一个函数和一个触发器来监听特定的 postgres 表以进行插入。如果发生任何情况,通知将通过 websocket 发送。另一个是一个角度应用程序,它使用 ng2-stompjs 来收听 /topic/notificari 的通知。我没有发布代码,因为通知没有脱离春天,角度不是问题。
亲切的问候,
这是我的 WebSocketConfiguration
Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/queue", "/user", "/notificari");
registry.setApplicationDestinationPrefixes("/app");
registry.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket").setAllowedOrigins("*")
.setHandshakeHandler(new CustomHandshakeHandler());
}
我正在使用类 ListenNotify 和 JDBC 驱动程序 pgjdbc-ng 连接到 postgresql 数据库并使用监听通知功能
public class ListenNotify {
private BlockingQueue queue = new ArrayBlockingQueue(20);
PGConnection connection;
public ListenNotify() {
PGNotificationListener listener = new PGNotificationListener() {
@Override
public void notification(int processId, String channelName, String payload) {
queue.add(payload);
}
};
try {
PGDataSource dataSource = new PGDataSource();
dataSource.setHost("localhost");
dataSource.setDatabase("db");
dataSource.setPort(5432);
dataSource.setUser("user");
dataSource.setPassword("pass");
connection = (PGConnection) dataSource.getConnection();
connection.addNotificationListener(listener);
Statement statement = connection.createStatement();
statement.execute("LISTEN n_event");
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public BlockingQueue getQueue() {
return queue;
}
}
最后,这是实例化 ListenNotify 对象并侦听 postgres 中可能触发必须使用 websocket 发送的通知的事件的代码。
@Component
public class InstantaNotificari {
@Autowired
SimpMessagingTemplate template;
@EventListener(ApplicationReadyEvent.class)
public void runn() {
System.out.println("invocare met");
ListenNotify ln = new ListenNotify();
BlockingQueue queue = ln.getQueue();
System.out.println("the que ies "+ queue);
while (true) {
try {
String msg = (String) queue.take();
System.out.println("msg " + msg);
template.convertAndSend("/topic/notificari", msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
解决方案
我没有使用 Spring,所以我无法测试您的代码。这是我测试过的版本。我认为这总结了差异 -
- 更改为尝试使用资源块。这将在销毁类时关闭连接。
- 将您的 while(true) 移动到侦听器上的 try 块中,以便 try 块内的行永远不会超出执行范围。
- while(true) 是阻塞的,所以它需要在另一个线程上。
ListenNotify extends Thread
我确信还有其他实施方式,欢迎对我的任何假设进行更正。
我测试过的运行代码在这个答案JMS Websocket 延迟交付中。
推荐阅读
- r - 函数从字面上接受一个参数而不是参数的值
- php - 将列创建日期和订单号添加到 WooCommerce 我的帐户订单
- bash - 将 perf 输出通过管道传输到文件中
- elasticsearch - Elasticsearch 中的复合同义词
- linux - 在所有 udev 规则通过并且设备完全初始化后运行脚本
- sql - 从多对多关系获取整个列表
- javascript - 发布路线不返回任何内容
- regex - Regex to catch comma-separated decimal numbers not inside latex command
- css - 在 React 中使用过渡覆盖导航栏
- node.js - 部署后:带有 Office365 和 SSLv3 的节点 IMAP MailListener 错误:140059098205512:error:1408F10B:SSL