/** * Config event listener data changed listener. * * @return the data changed listener */ @Bean @ConditionalOnMissingBean(WebsocketDataChangedListener.class) public DataChangedListener websocketDataChangedListener(){ // 这里初始化 WebSocket 通道数据变更监听 returnnew WebsocketDataChangedListener(); }
/** * Websocket collector websocket collector. * * @return the websocket collector */ @Bean @ConditionalOnMissingBean(WebsocketCollector.class) public WebsocketCollector websocketCollector(){ // 实例化 WebSocket Server returnnew WebsocketCollector(); }
/** * Server endpoint exporter server endpoint exporter. * * @return the server endpoint exporter */ @Bean @ConditionalOnMissingBean(ServerEndpointExporter.class) public ServerEndpointExporter serverEndpointExporter(){ returnnew ServerEndpointExporter(); } }
上面的代码声明了 WebSocket 相关的 Bean 的配置,soul admin 启动之后容器中注册了这些 Bean 之后,soul admin 同时也是 WebSocket Server 的角色,其中 WebSocket Server 相关的定义在类 WebsocketCollector 中:
@Slf4j @ServerEndpoint("/websocket")// 采用注解 @ServerEndPoint("/websocket") 配置 WebSocket Server 通讯的路径 publicclassWebsocketCollector{
/** * Instantiates a new Data changed event. * * @param groupKey the group key * @param type the type * @param source the source */ publicDataChangedEvent(final ConfigGroupEnum groupKey, final DataEventTypeEnum type, final List<?> source){ super(source); this.eventType = type; this.groupKey = groupKey; }
/** * Gets event type. * * @return the event type */ DataEventTypeEnum getEventType(){ return eventType; }
@Override public List<?> getSource() { return (List<?>) super.getSource(); }
/** * Gets group key. * * @return the group key */ public ConfigGroupEnum getGroupKey(){ returnthis.groupKey; }
}
在 soul admin 的插件, Selector, Rule 等等信息的操作后台代码中可以看到发送 DataEventType 事件, 结合上述的功能链, 就可以通过 WebSocket 完成由 WebSocket Server 到连接到 WebSocket Server 的客户端之间的配置信息推送。
WebSocket 客户端
Soul WebSocket 客户端相关的配置是通过 Spring Boot Starter : soul-spring-boot-starter-sync-data-websocket 实现的:
/** * Websocket sync data service. * * @param websocketConfig the websocket config * @param pluginSubscriber the plugin subscriber * @param metaSubscribers the meta subscribers * @param authSubscribers the auth subscribers * @return the sync data service */ // 创建 websocket 客户端, 可以支持多个服务端连接方式 @Bean public SyncDataService websocketSyncDataService(final ObjectProvider<WebsocketConfig> websocketConfig, final ObjectProvider<PluginDataSubscriber> pluginSubscriber, final ObjectProvider<List<MetaDataSubscriber>> metaSubscribers, final ObjectProvider<List<AuthDataSubscriber>> authSubscribers){ log.info("you use websocket sync soul data......."); returnnew WebsocketSyncDataService(websocketConfig.getIfAvailable(WebsocketConfig::new), pluginSubscriber.getIfAvailable(), metaSubscribers.getIfAvailable(Collections::emptyList), authSubscribers.getIfAvailable(Collections::emptyList)); }
/** * Config websocket config. * * @return the websocket config */ // 读取用户配置的 websocket urls, 支持配置多个 soul admin url @Bean @ConfigurationProperties(prefix = "soul.sync.websocket") public WebsocketConfig websocketConfig(){ returnnew WebsocketConfig(); } } @Data publicclassWebsocketConfig{ /** * if have more soul admin url,please config like this. * 127.0.0.1:8888,127.0.0.1:8889 */ private String urls; }