潘志宝
2024-10-09 c0b8cf32504dd1a42780bb1ee06ae8a7b0d7b120
提交 | 用户 | 时间
e7c126 1 package com.iailab.framework.websocket.config;
H 2
3 import com.iailab.framework.mq.redis.config.IailabRedisMQConsumerAutoConfiguration;
4 import com.iailab.framework.mq.redis.core.RedisMQTemplate;
5 import com.iailab.framework.websocket.core.handler.JsonWebSocketMessageHandler;
6 import com.iailab.framework.websocket.core.listener.WebSocketMessageListener;
7 import com.iailab.framework.websocket.core.security.LoginUserHandshakeInterceptor;
8 import com.iailab.framework.websocket.core.sender.kafka.KafkaWebSocketMessageConsumer;
9 import com.iailab.framework.websocket.core.sender.kafka.KafkaWebSocketMessageSender;
10 import com.iailab.framework.websocket.core.sender.local.LocalWebSocketMessageSender;
11 import com.iailab.framework.websocket.core.sender.rabbitmq.RabbitMQWebSocketMessageConsumer;
12 import com.iailab.framework.websocket.core.sender.rabbitmq.RabbitMQWebSocketMessageSender;
13 import com.iailab.framework.websocket.core.sender.redis.RedisWebSocketMessageConsumer;
14 import com.iailab.framework.websocket.core.sender.redis.RedisWebSocketMessageSender;
15 import com.iailab.framework.websocket.core.sender.rocketmq.RocketMQWebSocketMessageConsumer;
16 import com.iailab.framework.websocket.core.sender.rocketmq.RocketMQWebSocketMessageSender;
17 import com.iailab.framework.websocket.core.session.WebSocketSessionHandlerDecorator;
18 import com.iailab.framework.websocket.core.session.WebSocketSessionManager;
19 import com.iailab.framework.websocket.core.session.WebSocketSessionManagerImpl;
20 import org.apache.rocketmq.spring.core.RocketMQTemplate;
21 import org.springframework.amqp.core.TopicExchange;
22 import org.springframework.amqp.rabbit.core.RabbitTemplate;
23 import org.springframework.beans.factory.annotation.Value;
24 import org.springframework.boot.autoconfigure.AutoConfiguration;
25 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
26 import org.springframework.boot.context.properties.EnableConfigurationProperties;
27 import org.springframework.context.annotation.Bean;
28 import org.springframework.context.annotation.Configuration;
29 import org.springframework.kafka.core.KafkaTemplate;
30 import org.springframework.web.socket.WebSocketHandler;
31 import org.springframework.web.socket.config.annotation.EnableWebSocket;
32 import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
33 import org.springframework.web.socket.server.HandshakeInterceptor;
34
35 import java.util.List;
36
37 /**
38  * WebSocket 自动配置
39  *
40  * @author xingyu4j
41  */
42 @AutoConfiguration(before = IailabRedisMQConsumerAutoConfiguration.class) // before IailabRedisMQConsumerAutoConfiguration 的原因是,需要保证 RedisWebSocketMessageConsumer 先创建,才能创建 RedisMessageListenerContainer
43 @EnableWebSocket // 开启 websocket
44 @ConditionalOnProperty(prefix = "iailab.websocket", value = "enable", matchIfMissing = true) // 允许使用 iailab.websocket.enable=false 禁用 websocket
45 @EnableConfigurationProperties(WebSocketProperties.class)
46 public class IailabWebSocketAutoConfiguration {
47
48     @Bean
49     public WebSocketConfigurer webSocketConfigurer(HandshakeInterceptor[] handshakeInterceptors,
50                                                    WebSocketHandler webSocketHandler,
51                                                    WebSocketProperties webSocketProperties) {
52         return registry -> registry
53                 // 添加 WebSocketHandler
54                 .addHandler(webSocketHandler, webSocketProperties.getPath())
55                 .addInterceptors(handshakeInterceptors)
56                 // 允许跨域,否则前端连接会直接断开
57                 .setAllowedOriginPatterns("*");
58     }
59
60     @Bean
61     public HandshakeInterceptor handshakeInterceptor() {
62         return new LoginUserHandshakeInterceptor();
63     }
64
65     @Bean
66     public WebSocketHandler webSocketHandler(WebSocketSessionManager sessionManager,
67                                              List<? extends WebSocketMessageListener<?>> messageListeners) {
68         // 1. 创建 JsonWebSocketMessageHandler 对象,处理消息
69         JsonWebSocketMessageHandler messageHandler = new JsonWebSocketMessageHandler(messageListeners);
70         // 2. 创建 WebSocketSessionHandlerDecorator 对象,处理连接
71         return new WebSocketSessionHandlerDecorator(messageHandler, sessionManager);
72     }
73
74     @Bean
75     public WebSocketSessionManager webSocketSessionManager() {
76         return new WebSocketSessionManagerImpl();
77     }
78
79     // ==================== Sender 相关 ====================
80
81     @Configuration
82     @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "local", matchIfMissing = true)
83     public class LocalWebSocketMessageSenderConfiguration {
84
85         @Bean
86         public LocalWebSocketMessageSender localWebSocketMessageSender(WebSocketSessionManager sessionManager) {
87             return new LocalWebSocketMessageSender(sessionManager);
88         }
89
90     }
91
92     @Configuration
93     @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "redis", matchIfMissing = true)
94     public class RedisWebSocketMessageSenderConfiguration {
95
96         @Bean
97         public RedisWebSocketMessageSender redisWebSocketMessageSender(WebSocketSessionManager sessionManager,
98                                                                        RedisMQTemplate redisMQTemplate) {
99             return new RedisWebSocketMessageSender(sessionManager, redisMQTemplate);
100         }
101
102         @Bean
103         public RedisWebSocketMessageConsumer redisWebSocketMessageConsumer(
104                 RedisWebSocketMessageSender redisWebSocketMessageSender) {
105             return new RedisWebSocketMessageConsumer(redisWebSocketMessageSender);
106         }
107
108     }
109
110     @Configuration
111     @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "rocketmq", matchIfMissing = true)
112     public class RocketMQWebSocketMessageSenderConfiguration {
113
114         @Bean
115         public RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender(
116                 WebSocketSessionManager sessionManager, RocketMQTemplate rocketMQTemplate,
117                 @Value("${iailab.websocket.sender-rocketmq.topic}") String topic) {
118             return new RocketMQWebSocketMessageSender(sessionManager, rocketMQTemplate, topic);
119         }
120
121         @Bean
122         public RocketMQWebSocketMessageConsumer rocketMQWebSocketMessageConsumer(
123                 RocketMQWebSocketMessageSender rocketMQWebSocketMessageSender) {
124             return new RocketMQWebSocketMessageConsumer(rocketMQWebSocketMessageSender);
125         }
126
127     }
128
129     @Configuration
130     @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "rabbitmq", matchIfMissing = true)
131     public class RabbitMQWebSocketMessageSenderConfiguration {
132
133         @Bean
134         public RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender(
135                 WebSocketSessionManager sessionManager, RabbitTemplate rabbitTemplate,
136                 TopicExchange websocketTopicExchange) {
137             return new RabbitMQWebSocketMessageSender(sessionManager, rabbitTemplate, websocketTopicExchange);
138         }
139
140         @Bean
141         public RabbitMQWebSocketMessageConsumer rabbitMQWebSocketMessageConsumer(
142                 RabbitMQWebSocketMessageSender rabbitMQWebSocketMessageSender) {
143             return new RabbitMQWebSocketMessageConsumer(rabbitMQWebSocketMessageSender);
144         }
145
146         /**
147          * 创建 Topic Exchange
148          */
149         @Bean
150         public TopicExchange websocketTopicExchange(@Value("${iailab.websocket.sender-rabbitmq.exchange}") String exchange) {
151             return new TopicExchange(exchange,
152                     true,  // durable: 是否持久化
153                     false);  // exclusive: 是否排它
154         }
155
156     }
157
158     @Configuration
159     @ConditionalOnProperty(prefix = "iailab.websocket", name = "sender-type", havingValue = "kafka", matchIfMissing = true)
160     public class KafkaWebSocketMessageSenderConfiguration {
161
162         @Bean
163         public KafkaWebSocketMessageSender kafkaWebSocketMessageSender(
164                 WebSocketSessionManager sessionManager, KafkaTemplate<Object, Object> kafkaTemplate,
165                 @Value("${iailab.websocket.sender-kafka.topic}") String topic) {
166             return new KafkaWebSocketMessageSender(sessionManager, kafkaTemplate, topic);
167         }
168
169         @Bean
170         public KafkaWebSocketMessageConsumer kafkaWebSocketMessageConsumer(
171                 KafkaWebSocketMessageSender kafkaWebSocketMessageSender) {
172             return new KafkaWebSocketMessageConsumer(kafkaWebSocketMessageSender);
173         }
174
175     }
176
177 }