refactor: 目录结构优化

This commit is contained in:
ray
2024-08-30 08:18:53 +08:00
parent 7795c4d538
commit 95ef5dfd1f
215 changed files with 581 additions and 727 deletions

View File

@@ -0,0 +1,108 @@
package com.youlai.boot.config;
import cn.hutool.core.util.StrUtil;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import com.youlai.system.common.constant.SecurityConstants;
import com.youlai.boot.module.system.event.UserConnectionEvent;
import com.youlai.system.service.WebsocketService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
/**
* WebSocket 自动配置类
*
* @author haoxr
* @since 2.4.0
*/
// 启用WebSocket消息代理功能和配置STOMP协议实现实时双向通信和消息传递
@EnableWebSocketMessageBroker
@Configuration
@Slf4j
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
private final ApplicationEventPublisher eventPublisher;
public WebSocketConfig(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
/**
* 注册一个端点,客户端通过这个端点进行连接
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry
// 注册 /ws 的端点
.addEndpoint("/ws")
// 允许跨域
.setAllowedOriginPatterns("*");
}
/**
* 配置消息代理
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 客户端发送消息的请求前缀
registry.setApplicationDestinationPrefixes("/app");
// 客户端订阅消息的请求前缀topic一般用于广播推送queue用于点对点推送
registry.enableSimpleBroker("/topic", "/queue");
// 服务端通知客户端的前缀可以不设置默认为user
registry.setUserDestinationPrefix("/user");
}
/**
* 配置客户端入站通道拦截器
* <p>
* 添加 ChannelInterceptor 拦截器,用于在消息发送前,从请求头中获取 token 并解析出用户信息(username),用于点对点发送消息给指定用户
*
* @param registration 通道注册器
*/
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(@NotNull Message<?> message, @NotNull MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (accessor != null) {
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String bearerToken = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);
if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith("Bearer ")) {
bearerToken = bearerToken.substring(SecurityConstants.JWT_TOKEN_PREFIX.length());
String username = JWTUtil.parseToken(bearerToken).getPayloads().getStr(JWTPayload.SUBJECT);
if (StrUtil.isNotBlank(username)) {
accessor.setUser(() -> username);
eventPublisher.publishEvent(new UserConnectionEvent(this, username, true));
}
}
} else if (StompCommand.DISCONNECT.equals(accessor.getCommand())) {
if (accessor.getUser() != null) {
String username = accessor.getUser().getName();
eventPublisher.publishEvent(new UserConnectionEvent(this, username, false));
}
}
}
return ChannelInterceptor.super.preSend(message, channel);
}
});
}
}