diff --git a/pom.xml b/pom.xml
index 1c6ccd6..4df16b9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -126,6 +126,10 @@
test
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
org.dromara.x-file-storage
x-file-storage-spring
diff --git a/src/main/java/com/yupi/springbootinit/config/RabbitMQConfig.java b/src/main/java/com/yupi/springbootinit/config/RabbitMQConfig.java
new file mode 100644
index 0000000..9840dee
--- /dev/null
+++ b/src/main/java/com/yupi/springbootinit/config/RabbitMQConfig.java
@@ -0,0 +1,64 @@
+package com.yupi.springbootinit.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.amqp.core.ExchangeBuilder;
+import org.springframework.amqp.core.HeadersExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitAdmin;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.amqp.support.converter.MessageConverter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class RabbitMQConfig {
+
+ private static final String QUEUE = "HOST_INFO_QUEUE";
+
+ public static final String EXCHANGE_NAME = "user.headers.exchange";
+
+ //创建队列
+ //true:表示持久化
+ //队列在默认情况下放到内存,rabbitmq重启后就丢失了,如果希望重启后,队列
+ //数据还能使用,就需要持久化
+ @Bean
+ public Queue hostInfoQueue(){
+ return new Queue(QUEUE,true);
+ }
+
+//
+// @Bean
+// public MessageConverter messageConverter(){
+// return new Jackson2JsonMessageConverter();
+// }
+
+
+
+ @Bean
+ public HeadersExchange userHeadersExchange() {
+ return ExchangeBuilder.headersExchange(EXCHANGE_NAME)
+ .durable(true)
+ .build();
+ }
+
+ @Bean
+ public RabbitAdmin rabbitAdmin(ConnectionFactory cf) {
+ return new RabbitAdmin(cf);
+ }
+
+
+ @Bean
+ public MessageConverter messageConverter() {
+ ObjectMapper om = new ObjectMapper();
+ om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+ om.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ om.registerModule(new JavaTimeModule());
+ return new Jackson2JsonMessageConverter(om);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/yupi/springbootinit/config/RedisConfig.java b/src/main/java/com/yupi/springbootinit/config/RedisConfig.java
index 287c1d5..a7e848e 100644
--- a/src/main/java/com/yupi/springbootinit/config/RedisConfig.java
+++ b/src/main/java/com/yupi/springbootinit/config/RedisConfig.java
@@ -1,37 +1,49 @@
package com.yupi.springbootinit.config;
-
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
- @Bean(name="redisTemplate")
- public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
- RedisTemplate template = new RedisTemplate<>();
- RedisSerializer redisSerializer = new StringRedisSerializer();
+ // @Bean(name="redisTemplate")
+// public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
+// RedisTemplate template = new RedisTemplate<>();
+// RedisSerializer redisSerializer = new StringRedisSerializer();
+// template.setConnectionFactory(factory);
+// //key序列化方式
+// template.setKeySerializer(redisSerializer);
+// //value序列化
+// template.setValueSerializer(redisSerializer);
+// //value hashmap序列化
+// template.setHashValueSerializer(redisSerializer);
+// //key haspmap序列化
+// template.setHashKeySerializer(redisSerializer);
+// //
+// return template;
+// }
+ @Bean
+ public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
+ RedisTemplate template = new RedisTemplate<>();
template.setConnectionFactory(factory);
- //key序列化方式
- template.setKeySerializer(redisSerializer);
- //value序列化
- template.setValueSerializer(redisSerializer);
- //value hashmap序列化
- template.setHashValueSerializer(redisSerializer);
- //key haspmap序列化
- template.setHashKeySerializer(redisSerializer);
- //
+
+ // 使用 JSON 序列化器
+ GenericJackson2JsonRedisSerializer jsonSerializer = new GenericJackson2JsonRedisSerializer();
+
+ template.setKeySerializer(new StringRedisSerializer());
+ template.setValueSerializer(jsonSerializer);
+ template.setHashKeySerializer(new StringRedisSerializer());
+ template.setHashValueSerializer(jsonSerializer);
+
+ template.afterPropertiesSet();
return template;
}
-
-
-
}
diff --git a/src/main/java/com/yupi/springbootinit/config/SaTokenConfigure.java b/src/main/java/com/yupi/springbootinit/config/SaTokenConfigure.java
index 477d045..9e160ab 100644
--- a/src/main/java/com/yupi/springbootinit/config/SaTokenConfigure.java
+++ b/src/main/java/com/yupi/springbootinit/config/SaTokenConfigure.java
@@ -47,7 +47,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
"/tenant/get-id-by-name",
"/user/bigbrother-doLogin",
"/user/aiChat-doLogin",
- "/error"
+ "/user/aiChat-logout",
+ "/error",
};
}
diff --git a/src/main/java/com/yupi/springbootinit/controller/UserController.java b/src/main/java/com/yupi/springbootinit/controller/UserController.java
index ec2d9ea..65c5caf 100644
--- a/src/main/java/com/yupi/springbootinit/controller/UserController.java
+++ b/src/main/java/com/yupi/springbootinit/controller/UserController.java
@@ -57,6 +57,10 @@ public class UserController {
// return ResultUtils.success(systemUsersVO);
}
+ @PostMapping("aiChat-logout")
+ public BaseResponse aiChatLogout(@RequestBody SystemUsersDTO usersDTO){
+ return ResultUtils.success(loginService.aiChatLogout(usersDTO));
+ }
//
// private SystemUsers getUserByName(@RequestBody SystemUsersDTO usersDTO) {
diff --git a/src/main/java/com/yupi/springbootinit/model/dto/user/SystemUsersDTO.java b/src/main/java/com/yupi/springbootinit/model/dto/user/SystemUsersDTO.java
index 7948950..55f9299 100644
--- a/src/main/java/com/yupi/springbootinit/model/dto/user/SystemUsersDTO.java
+++ b/src/main/java/com/yupi/springbootinit/model/dto/user/SystemUsersDTO.java
@@ -29,4 +29,6 @@ public class SystemUsersDTO {
* 租户编号
*/
private Long tenantId;
+
+ private Long userId;
}
\ No newline at end of file
diff --git a/src/main/java/com/yupi/springbootinit/service/impl/LoginService.java b/src/main/java/com/yupi/springbootinit/service/impl/LoginService.java
index 5b536b8..72b10ac 100644
--- a/src/main/java/com/yupi/springbootinit/service/impl/LoginService.java
+++ b/src/main/java/com/yupi/springbootinit/service/impl/LoginService.java
@@ -11,17 +11,51 @@ import com.yupi.springbootinit.model.enums.LoginSceneEnum;
import com.yupi.springbootinit.model.vo.user.SystemUsersVO;
import com.yupi.springbootinit.service.SystemUsersService;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.*;
+import org.springframework.amqp.rabbit.core.RabbitAdmin;
+import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Slf4j
@Service
@RequiredArgsConstructor
public class LoginService {
private final SystemUsersService usersService;
+ @Resource
+ private RedisTemplate redisTemplate;
+
+ private final Set created = ConcurrentHashMap.newKeySet();
+ private final HeadersExchange userHeadersExchange;
+ @Resource
+ private RabbitAdmin rabbitAdmin;
+
public SystemUsersVO login(LoginSceneEnum scene, SystemUsersDTO dto) {
SystemUsers user = validateUser(dto); // 校验用户名、密码、状态、租户过期
checkRole(scene, user.getId()); // 按场景做角色校验
+ if (scene.equals(LoginSceneEnum.AI_CHAT)) {
+ redisTemplate.opsForValue().set("ai_login:"+user.getTenantId() ,true);
+ String queueName = "q.tenant." + user.getTenantId();
+ if (created.add(String.valueOf(user.getTenantId()))) {
+ Queue queue = QueueBuilder.durable(queueName).build();
+ rabbitAdmin.declareQueue(queue);
+
+ Map headers = Map.of("tenantId", user.getTenantId(), "x-match", "all");
+ Binding binding = BindingBuilder
+ .bind(queue)
+ .to(userHeadersExchange) // ← 传 Exchange 对象
+ .whereAll(headers)
+ .match();
+ rabbitAdmin.declareBinding(binding);
+ }
+ }
Long second = usersService.getTenantExpiredTime(dto.getTenantId());
// Sa-Token 登录
StpUtil.login(user.getId(), scene.getSaMode());
@@ -53,4 +87,12 @@ public class LoginService {
};
if (!pass) throw new BusinessException(ErrorCode.LOGIN_NOW_ALLOWED);
}
+
+ public Boolean aiChatLogout(SystemUsersDTO usersDTO) {
+ Boolean delete = redisTemplate.delete("ai_login:"+usersDTO.getTenantId());
+ created.remove(String.valueOf(usersDTO.getTenantId()));
+ log.info("删除租户:{}登录状态:{}",usersDTO.getTenantId(),delete);
+ StpUtil.logout(usersDTO.getUserId());
+ return true;
+ }
}
\ No newline at end of file