refactor: 包结构优化,websocket 重构
This commit is contained in:
@@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.SystemConstants;
|
||||
import com.youlai.system.base.security.model.SysUserDetails;
|
||||
import com.youlai.system.core.security.model.SysUserDetails;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.youlai.system.base.mybatisplus.config;
|
||||
package com.youlai.system.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.youlai.system.base.mybatisplus.handler.MyDataPermissionHandler;
|
||||
import com.youlai.system.base.mybatisplus.handler.MyMetaObjectHandler;
|
||||
import com.youlai.system.core.mybatis.handler.MyDataPermissionHandler;
|
||||
import com.youlai.system.core.mybatis.handler.MyMetaObjectHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
@@ -19,7 +19,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
public class MybatisPlusConfig {
|
||||
public class MybatisConfig {
|
||||
|
||||
/**
|
||||
* 分页插件和数据权限插件
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.youlai.system.base.security.config;
|
||||
package com.youlai.system.config;
|
||||
|
||||
import com.youlai.system.common.constant.SecurityConstants;
|
||||
import com.youlai.system.base.security.exception.MyAccessDeniedHandler;
|
||||
import com.youlai.system.base.security.exception.MyAuthenticationEntryPoint;
|
||||
import com.youlai.system.base.security.jwt.JwtTokenFilter;
|
||||
import com.youlai.system.core.security.exception.MyAccessDeniedHandler;
|
||||
import com.youlai.system.core.security.exception.MyAuthenticationEntryPoint;
|
||||
import com.youlai.system.core.security.jwt.JwtTokenFilter;
|
||||
import com.youlai.system.filter.VerifyCodeFilter;
|
||||
import com.youlai.system.base.security.jwt.JwtTokenProvider;
|
||||
import com.youlai.system.core.security.jwt.JwtTokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
111
src/main/java/com/youlai/system/config/WebSocketConfig.java
Normal file
111
src/main/java/com/youlai/system/config/WebSocketConfig.java
Normal file
@@ -0,0 +1,111 @@
|
||||
package com.youlai.system.config;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.core.security.jwt.JwtTokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSocketMessageBroker // 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
/**
|
||||
* 注册一个端点,客户端通过这个端点进行连接
|
||||
*/
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry
|
||||
.addEndpoint("/ws") // 注册了一个 /ws 的端点
|
||||
.setAllowedOriginPatterns("*") // 允许跨域的 WebSocket 连接
|
||||
.withSockJS(); // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
|
||||
registry.addEndpoint("/ws-app").setAllowedOriginPatterns("*"); // 注册了一个 /ws-app 的端点,支持 uni-app 的 ws 连接协议
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配置消息代理
|
||||
*/
|
||||
@Override
|
||||
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
||||
// 客户端发送消息的请求前缀
|
||||
registry.setApplicationDestinationPrefixes("/app");
|
||||
|
||||
// 客户端订阅消息的请求前缀,topic一般用于广播推送,queue用于点对点推送
|
||||
registry.enableSimpleBroker("/topic", "/queue");
|
||||
|
||||
// 服务端通知客户端的前缀,可以不设置,默认为user
|
||||
registry.setUserDestinationPrefix("/user");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配置客户端入站通道拦截器
|
||||
*
|
||||
* @param registration 通道注册器
|
||||
*/
|
||||
@Override
|
||||
public void configureClientInboundChannel(ChannelRegistration registration) {
|
||||
registration.interceptors(new ChannelInterceptor() {
|
||||
@Override
|
||||
public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
||||
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
|
||||
|
||||
// 如果 StompHeaderAccessor 为 null,说明不是 STOMP 消息,直接放行
|
||||
if (accessor == null) {
|
||||
return ChannelInterceptor.super.preSend(message, channel);
|
||||
}
|
||||
|
||||
// 如果是连接请求(CONNECT 命令),从请求头中取出 token 并设置到认证信息中
|
||||
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
|
||||
// 从连接头中提取授权令牌
|
||||
String bearerToken = accessor.getFirstNativeHeader(HttpHeaders.AUTHORIZATION);
|
||||
|
||||
// 验证令牌格式并提取用户信息
|
||||
if (StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith("Bearer ")) {
|
||||
try {
|
||||
// 移除 "Bearer " 前缀
|
||||
String tokenWithoutPrefix = bearerToken.substring(7);
|
||||
String username = jwtTokenProvider.getUsername(tokenWithoutPrefix);
|
||||
|
||||
// 如果用户名有效,设置用户到访问器中
|
||||
if (StrUtil.isNotBlank(username)) {
|
||||
accessor.setUser(() -> username);
|
||||
return message;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// 异常处理,可能是解析令牌失败
|
||||
log.error("Failed to process authentication token.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是连接命令或授权失败,继续执行默认逻辑
|
||||
return ChannelInterceptor.super.preSend(message, channel);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.plugin.xxljob;
|
||||
package com.youlai.system.config;
|
||||
|
||||
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.youlai.system.controller;
|
||||
|
||||
import com.youlai.system.model.dto.SocketMessage;
|
||||
import com.youlai.system.model.dto.ChatMessage;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.messaging.handler.annotation.DestinationVariable;
|
||||
@@ -48,11 +48,14 @@ public class WebsocketController {
|
||||
* @param message 消息内容
|
||||
*/
|
||||
@MessageMapping("/sendToUser/{username}")
|
||||
//@SendToUser(value = "/queue/greeting")
|
||||
public void sendToUser(Principal principal, @DestinationVariable String username, String message) {
|
||||
log.info("sender:{};receiver:{}", principal.getName(), username);
|
||||
messagingTemplate.convertAndSendToUser(username, "/queue/greeting", new SocketMessage(principal.getName(), message));
|
||||
/// return "Hello, " + message;
|
||||
|
||||
String sender = principal.getName(); // 发送人
|
||||
String receiver = username; // 接收人
|
||||
|
||||
log.info("发送人:{}; 接收人:{}", sender, receiver);
|
||||
// 发送消息给指定用户 /user/{username}/queue/greeting
|
||||
messagingTemplate.convertAndSendToUser(receiver, "/queue/greeting", new ChatMessage(sender, message));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.base.mybatisplus.annotation;
|
||||
package com.youlai.system.core.mybatis.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.youlai.system.base.mybatisplus.handler;
|
||||
package com.youlai.system.core.mybatis.handler;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
|
||||
import com.youlai.system.base.mybatisplus.annotation.DataPermission;
|
||||
import com.youlai.system.core.mybatis.annotation.DataPermission;
|
||||
import com.youlai.system.common.base.IBaseEnum;
|
||||
import com.youlai.system.common.enums.DataScopeEnum;
|
||||
import com.youlai.system.common.util.SecurityUtils;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.base.mybatisplus.handler;
|
||||
package com.youlai.system.core.mybatis.handler;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.base.security.exception;
|
||||
package com.youlai.system.core.security.exception;
|
||||
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.common.util.ResponseUtils;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.base.security.exception;
|
||||
package com.youlai.system.core.security.exception;
|
||||
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.common.util.ResponseUtils;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.base.security.jwt;
|
||||
package com.youlai.system.core.security.jwt;
|
||||
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.common.util.ResponseUtils;
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.youlai.system.base.security.jwt;
|
||||
package com.youlai.system.core.security.jwt;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import com.youlai.system.common.constant.JwtClaimConstants;
|
||||
import com.youlai.system.base.security.model.SysUserDetails;
|
||||
import com.youlai.system.core.security.model.SysUserDetails;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.base.security.model;
|
||||
package com.youlai.system.core.security.model;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.youlai.system.base.security.service;
|
||||
package com.youlai.system.core.security.service;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.youlai.system.base.security.service;
|
||||
package com.youlai.system.core.security.service;
|
||||
|
||||
import com.youlai.system.base.security.model.SysUserDetails;
|
||||
import com.youlai.system.core.security.model.SysUserDetails;
|
||||
import com.youlai.system.model.dto.UserAuthInfo;
|
||||
import com.youlai.system.service.SysUserService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -3,7 +3,7 @@ package com.youlai.system.mapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.youlai.system.base.mybatisplus.annotation.DataPermission;
|
||||
import com.youlai.system.core.mybatis.annotation.DataPermission;
|
||||
import com.youlai.system.model.entity.SysDept;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.youlai.system.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.youlai.system.base.mybatisplus.annotation.DataPermission;
|
||||
import com.youlai.system.core.mybatis.annotation.DataPermission;
|
||||
import com.youlai.system.model.bo.UserBO;
|
||||
import com.youlai.system.model.entity.SysUser;
|
||||
import com.youlai.system.model.dto.UserAuthInfo;
|
||||
|
||||
@@ -10,7 +10,7 @@ import lombok.NoArgsConstructor;
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SocketMessage {
|
||||
public class ChatMessage {
|
||||
|
||||
/**
|
||||
* 发送者
|
||||
@@ -4,7 +4,7 @@ import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.plugin.dupsubmit.annotation.PreventDuplicateSubmit;
|
||||
import com.youlai.system.common.result.ResultCode;
|
||||
import com.youlai.system.common.exception.BusinessException;
|
||||
import com.youlai.system.base.security.jwt.JwtTokenProvider;
|
||||
import com.youlai.system.core.security.jwt.JwtTokenProvider;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.youlai.system.plugin.websocket;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.simp.config.ChannelRegistration;
|
||||
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
|
||||
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
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSocketMessageBroker // 启用WebSocket消息代理功能和配置STOMP协议,实现实时双向通信和消息传递
|
||||
@RequiredArgsConstructor
|
||||
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
|
||||
|
||||
private final WebsocketChannelInterceptor websocketChannelInterceptor;
|
||||
|
||||
/**
|
||||
* 注册一个端点,客户端通过这个端点进行连接
|
||||
*/
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
registry
|
||||
.addEndpoint("/ws") // 注册了一个 /ws 的端点
|
||||
.setAllowedOriginPatterns("*") // 允许跨域的 WebSocket 连接
|
||||
.withSockJS(); // 启用 SockJS (浏览器不支持WebSocket,SockJS 将会提供兼容性支持)
|
||||
registry.addEndpoint("/ws-app").setAllowedOriginPatterns("*"); // 注册了一个 /ws-app 的端点,支持 uni-app 的 ws 连接协议
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配置消息代理
|
||||
*/
|
||||
@Override
|
||||
public void configureMessageBroker(MessageBrokerRegistry registry) {
|
||||
// 客户端发送消息的请求前缀
|
||||
registry.setApplicationDestinationPrefixes("/app");
|
||||
|
||||
// 客户端订阅消息的请求前缀,topic一般用于广播推送,queue用于点对点推送
|
||||
registry.enableSimpleBroker("/topic", "/queue");
|
||||
|
||||
// 服务端通知客户端的前缀,可以不设置,默认为user
|
||||
registry.setUserDestinationPrefix("/user");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 配置客户端入站通道拦截器
|
||||
*
|
||||
* @param registration 通道注册器
|
||||
*/
|
||||
@Override
|
||||
public void configureClientInboundChannel(ChannelRegistration registration) {
|
||||
registration.interceptors(websocketChannelInterceptor);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.youlai.system.plugin.websocket;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.base.security.jwt.JwtTokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
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.stereotype.Component;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
/**
|
||||
* Websocket 连接认证拦截器
|
||||
*
|
||||
* @author haoxr
|
||||
* @since 2.4.0
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class WebsocketChannelInterceptor implements ChannelInterceptor {
|
||||
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
/**
|
||||
* 连接前监听
|
||||
*
|
||||
* @param message 消息
|
||||
* @param channel 通道
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public Message<?> preSend(Message<?> message, MessageChannel channel) {
|
||||
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
|
||||
assert accessor != null;
|
||||
|
||||
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
|
||||
String bearerToken = accessor.getFirstNativeHeader("Authorization");
|
||||
if (StrUtil.isNotBlank(bearerToken)) {
|
||||
bearerToken = bearerToken.substring(7); // remove "Bearer "
|
||||
String username = jwtTokenProvider.getUsername(bearerToken);
|
||||
if (StrUtil.isNotBlank(username)) {
|
||||
Principal principal = () -> username;
|
||||
accessor.setUser(principal);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ChannelInterceptor.super.preSend(message, channel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.youlai.system.service.impl;
|
||||
|
||||
import cn.hutool.captcha.AbstractCaptcha;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.system.common.constant.CacheConstants;
|
||||
import com.youlai.system.base.security.jwt.JwtTokenProvider;
|
||||
import com.youlai.system.core.security.jwt.JwtTokenProvider;
|
||||
import com.youlai.system.model.dto.CaptchaResult;
|
||||
import com.youlai.system.model.dto.LoginResult;
|
||||
import com.youlai.system.plugin.captcha.CaptchaGenerator;
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.youlai.system.common.constant.SystemConstants;
|
||||
import com.youlai.system.common.model.Option;
|
||||
import com.youlai.system.converter.RoleConverter;
|
||||
import com.youlai.system.base.security.service.PermissionService;
|
||||
import com.youlai.system.core.security.service.PermissionService;
|
||||
import com.youlai.system.mapper.SysRoleMapper;
|
||||
import com.youlai.system.model.entity.SysRole;
|
||||
import com.youlai.system.model.entity.SysRoleMenu;
|
||||
|
||||
Reference in New Issue
Block a user