All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.herodotus.engine.message.websocket.configuration.WebSocketMessageBrokerConfiguration Maven / Gradle / Ivy

/*
 * Copyright (c) 2020-2030 郑庚伟 ZHENGGENGWEI (码匠君) ([email protected] & www.herodotus.cn)
 *
 * Dante Engine licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.herodotus.engine.message.websocket.configuration;

import cn.herodotus.engine.message.core.constants.MessageConstants;
import cn.herodotus.engine.message.websocket.interceptor.WebSocketAuthenticationHandshakeInterceptor;
import cn.herodotus.engine.message.websocket.interceptor.WebSocketChannelInterceptor;
import cn.herodotus.engine.message.websocket.interceptor.WebSocketPrincipalHandshakeHandler;
import cn.herodotus.engine.message.websocket.properties.WebSocketProperties;
import jakarta.annotation.PostConstruct;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.session.Session;
import org.springframework.session.web.socket.config.annotation.AbstractSessionWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;

/**
 * 

Description: WebSocketMessageBrokerConfigurer

* * @author : gengwei.zheng * @date : 2022/12/4 19:19 */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties({WebSocketProperties.class}) @EnableScheduling @EnableWebSocketMessageBroker public class WebSocketMessageBrokerConfiguration extends AbstractSessionWebSocketMessageBrokerConfigurer { private static final Logger log = LoggerFactory.getLogger(WebSocketMessageBrokerConfiguration.class); private final WebSocketProperties webSocketProperties; private final WebSocketChannelInterceptor webSocketChannelInterceptor; private final WebSocketPrincipalHandshakeHandler webSocketPrincipalHandshakeHandler; private final WebSocketAuthenticationHandshakeInterceptor webSocketAuthenticationHandshakeInterceptor; public WebSocketMessageBrokerConfiguration(WebSocketProperties webSocketProperties, WebSocketAuthenticationHandshakeInterceptor webSocketAuthenticationHandshakeInterceptor) { this.webSocketProperties = webSocketProperties; this.webSocketChannelInterceptor = new WebSocketChannelInterceptor(); this.webSocketPrincipalHandshakeHandler = new WebSocketPrincipalHandshakeHandler(); this.webSocketAuthenticationHandshakeInterceptor = webSocketAuthenticationHandshakeInterceptor; } @PostConstruct public void postConstruct() { log.debug("[Herodotus] |- SDK [WebSocket Message Broker] Auto Configure."); } /** * 添加 Stomp Endpoint,创建配置客户端尝试连接地址,并对外暴露该接口,这样就可以通过websocket连接上服务 * * @param registry {@link StompEndpointRegistry} */ @Override protected void configureStompEndpoints(StompEndpointRegistry registry) { /* * 1. 将 /serviceName/stomp路径注册为Stomp的端点, * 用户连接了这个端点后就可以进行websocket通讯,支持socketJs * 2. setAllowedOriginPatterns("*")表示可以跨域 * 3. withSockJS()表示支持socktJS访问 * 4. 添加自定义拦截器,这个拦截器是上一个demo自己定义的获取httpsession的拦截器 */ registry.addEndpoint(webSocketProperties.getEndpoint()) .setAllowedOrigins("*") .addInterceptors(webSocketAuthenticationHandshakeInterceptor) .setHandshakeHandler(webSocketPrincipalHandshakeHandler) .withSockJS(); registry.addEndpoint(webSocketProperties.getEndpoint()) .setAllowedOrigins("*") .addInterceptors(webSocketAuthenticationHandshakeInterceptor) .setHandshakeHandler(webSocketPrincipalHandshakeHandler); } /** * 配置消息代理 * * @param registry {@link MessageBrokerRegistry} */ @Override public void configureMessageBroker(MessageBrokerRegistry registry) { /* * enableStompBrokerRelay 配置外部的STOMP服务,需要安装额外的支持 比如rabbitmq或activemq * 1. 配置代理域,可以配置多个,此段代码配置代理目的地的前缀为 /topicTest 或者 /userTest * 我们就可以在配置的域上向客户端推送消息 * 3. 可以通过 setRelayHost 配置代理监听的host,默认为localhost * 4. 可以通过 setRelayPort 配置代理监听的端口,默认为61613 * 5. 可以通过 setClientLogin 和 setClientPasscode 配置账号和密码 * 6. setxxx这种设置方法是可选的,根据业务需要自行配置,也可以使用默认配置 */ // registry.enableStompBrokerRelay("/topicTest", "/userTest") // .setRelayHost("rabbit.someotherserver") // .setRelayPort(62623); // .setClientLogin("username") // .setClientPasscode("password"); // 自定义调度器,用于控制心跳线程 ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); // 线程池线程数,心跳连接开线程 taskScheduler.setPoolSize(1); // 线程名前缀 taskScheduler.setThreadNamePrefix("herodotus-websocket-heartbeat-thread-"); // 初始化 taskScheduler.initialize(); /* * spring 内置broker对象 广播式应配置一个/topic消息代理,点对点应配置一个/user消息代理, * 1. 配置代理域,可以配置多个,此段代码配置代理目的地的前缀为 /topicTest 或者 /userTest 我们就可以在配置的域上向客户端推送消息 * 2. 进行心跳设置,第一值表示server最小能保证发的心跳间隔毫秒数, 第二个值代码server希望client发的心跳间隔毫秒数 * 3. 可以配置心跳线程调度器 setHeartbeatValue这个不能单独设置,不然不起作用,要配合setTaskScheduler才可以生效 * 调度器我们可以自己写一个,也可以自己使用默认的调度器 new DefaultManagedTaskScheduler() */ registry.enableSimpleBroker(MessageConstants.WEBSOCKET_CHANNEL_PROXY_BROADCAST, MessageConstants.WEBSOCKET_CHANNEL_PROXY_PERSONAL) .setHeartbeatValue(new long[]{10000, 10000}) .setTaskScheduler(taskScheduler); /* * 全局使用的消息前缀(客户端订阅路径上会体现出来) * "/app" 为配置应用服务器的地址前缀,表示所有以/app 开头的客户端消息或请求 * 都会路由到带有@MessageMapping 注解的方法中 */ String[] applicationDestinationPrefixes = webSocketProperties.getApplicationPrefixes(); if (ArrayUtils.isNotEmpty(applicationDestinationPrefixes)) { registry.setApplicationDestinationPrefixes(applicationDestinationPrefixes); } /* * 点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是/user/ * 1. 配置一对一消息前缀, 客户端接收一对一消息需要配置的前缀 如“'/user/'+userid + '/message'”, * 是客户端订阅一对一消息的地址 stompClient.subscribe js方法调用的地址 * 2. 使用@SendToUser发送私信的规则不是这个参数设定,在框架内部是用UserDestinationMessageHandler处理, * 而不是 AnnotationMethodMessageHandler 或 SimpleBrokerMessageHandler * or StompBrokerRelayMessageHandler,是在@SendToUser的URL前加“user+sessionId"组成 */ if (StringUtils.isNotBlank(webSocketProperties.getUserDestinationPrefix())) { registry.setUserDestinationPrefix(webSocketProperties.getUserDestinationPrefix()); } /* * 自定义路径分割符 * 注释掉的这段代码添加的分割符为. 分割是类级别的@messageMapping和方法级别的@messageMapping的路径 * 例如类注解路径为 “topic”,方法注解路径为“hello”,那么客户端JS stompClient.send 方法调用的路径为“/app/topic.hello” * 注释掉此段代码后,类注解路径“/topic”,方法注解路径“/hello”,JS调用的路径为“/app/topic/hello” */ //registry.setPathMatcher(new AntPathMatcher(".")); } /** * 配置发送与接收的消息参数,可以指定消息字节大小,缓存大小,发送超时时间 * * @param registration {@link WebSocketTransportRegistration} */ @Override public void configureWebSocketTransport(WebSocketTransportRegistration registration) { /* * 1. setMessageSizeLimit 设置消息缓存的字节数大小 字节 * 2. setSendBufferSizeLimit 设置websocket会话时,缓存的大小 字节 * 3. setSendTimeLimit 设置消息发送会话超时时间,毫秒 */ registration.setMessageSizeLimit(10240) .setSendBufferSizeLimit(10240) .setSendTimeLimit(10000); super.configureWebSocketTransport(registration); } /** * 采用自定义拦截器,获取connect时候传递的参数 * 设置输入消息通道的线程数,默认线程为1,可以自己自定义线程数,最大线程数,线程存活时间 * * @param registration {@link ChannelRegistration} */ @Override public void configureClientInboundChannel(ChannelRegistration registration) { /* * 配置消息线程池 * 1. corePoolSize 配置核心线程池,当线程数小于此配置时,不管线程中有无空闲的线程,都会产生新线程处理任务 * 2. maxPoolSize 配置线程池最大数,当线程池数等于此配置时,不会产生新线程 * 3. keepAliveSeconds 线程池维护线程所允许的空闲时间,单位秒 */ registration.taskExecutor() .corePoolSize(10) .maxPoolSize(20) .keepAliveSeconds(60); /* * 添加stomp自定义拦截器,可以根据业务做一些处理 * 消息拦截器,实现ChannelInterceptor接口 */ registration.interceptors(webSocketChannelInterceptor); super.configureClientInboundChannel(registration); } /** * 设置输出消息通道的线程数,默认线程为1,可以自己自定义线程数,最大线程数,线程存活时间 * * @param registration {@link ChannelRegistration} */ @Override public void configureClientOutboundChannel(ChannelRegistration registration) { registration.taskExecutor().corePoolSize(10) .maxPoolSize(20) .keepAliveSeconds(60); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy