refactor(project):重构项目结构并迁移至snails-chat模块- 将项目主模块更名为snails-chat,调整包结构
- 移除JPA相关依赖,替换为MyBatis-Plus- 数据库从MySQL迁移至PostgreSQL- 移除QueryTool工具类及相关依赖- 更新Redis配置,使用JSON序列化- 移除DashScopeController及AIResponse类 - 添加User实体类及Mapper接口 - 调整ChatClientConfiguration配置类- 更新pom.xml依赖管理及模块配置
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package com.hanserwei.chat;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.hanserwei.chat.domain.mapper")
|
||||
public class SnailsChatApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SnailsChatApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.hanserwei.chat.config;
|
||||
|
||||
import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel;
|
||||
import com.alibaba.cloud.ai.memory.redis.BaseRedisChatMemoryRepository;
|
||||
import com.alibaba.cloud.ai.memory.redis.LettuceRedisChatMemoryRepository;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.client.advisor.PromptChatMemoryAdvisor;
|
||||
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
|
||||
import org.springframework.ai.chat.memory.ChatMemory;
|
||||
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class ChatClientConfiguration {
|
||||
|
||||
@Value("${spring.ai.memory.redis.host}")
|
||||
private String redisHost;
|
||||
@Value("${spring.ai.memory.redis.port}")
|
||||
private int redisPort;
|
||||
@Value("${spring.ai.memory.redis.password}")
|
||||
private String redisPassword;
|
||||
@Value("${spring.ai.memory.redis.timeout}")
|
||||
private int redisTimeout;
|
||||
|
||||
|
||||
@Resource
|
||||
private DashScopeChatModel dashScopeChatModel;
|
||||
|
||||
@Bean
|
||||
public BaseRedisChatMemoryRepository redisChatMemoryRepository() {
|
||||
// 构建RedissonRedisChatMemoryRepository实例
|
||||
return LettuceRedisChatMemoryRepository.builder()
|
||||
.host(redisHost)
|
||||
.port(redisPort)
|
||||
.password(redisPassword)
|
||||
.timeout(redisTimeout)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ChatMemory chatMemory(BaseRedisChatMemoryRepository chatMemoryRepository) {
|
||||
return MessageWindowChatMemory
|
||||
.builder()
|
||||
.maxMessages(100000)
|
||||
.chatMemoryRepository(chatMemoryRepository).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ChatClient dashScopeChatClient(ChatMemory chatMemory) {
|
||||
return ChatClient.builder(dashScopeChatModel)
|
||||
.defaultAdvisors(PromptChatMemoryAdvisor.builder(chatMemory).build(), new SimpleLoggerAdvisor())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.hanserwei.chat.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class CorsConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**") // 匹配所有路径
|
||||
.allowedOriginPatterns("*") // 允许所有域名(生产环境应指定具体域名)
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的请求方法
|
||||
.allowedHeaders("*") // 允许所有请求头
|
||||
.allowCredentials(true) // 允许发送 Cookie
|
||||
.maxAge(3600); // 预检请求的有效期(秒)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.hanserwei.chat.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.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfig {
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
// 设置 RedisTemplate 的连接工厂
|
||||
redisTemplate.setConnectionFactory(connectionFactory);
|
||||
|
||||
// 使用 StringRedisSerializer 来序列化和反序列化 redis 的 key 值,确保 key 是可读的字符串
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
|
||||
// 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 redis 的 value 值, 确保存储的是 JSON 格式
|
||||
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||
redisTemplate.setValueSerializer(serializer);
|
||||
redisTemplate.setHashValueSerializer(serializer);
|
||||
|
||||
redisTemplate.afterPropertiesSet();
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.hanserwei.chat.domain.dataobject;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@TableName(value = "t_user")
|
||||
public class User {
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Integer id;
|
||||
|
||||
@TableField(value = "\"name\"")
|
||||
private String name;
|
||||
|
||||
@TableField(value = "email")
|
||||
private String email;
|
||||
|
||||
@TableField(value = "age")
|
||||
private Integer age;
|
||||
|
||||
@TableField(value = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@TableField(value = "is_active")
|
||||
private Boolean isActive;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.hanserwei.chat.domain.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.hanserwei.chat.domain.dataobject.User;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper extends BaseMapper<User> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.hanserwei.chat.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.hanserwei.chat.domain.dataobject.User;
|
||||
|
||||
public interface UserService extends IService<User> {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.hanserwei.chat.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.hanserwei.chat.domain.dataobject.User;
|
||||
import com.hanserwei.chat.domain.mapper.UserMapper;
|
||||
import com.hanserwei.chat.service.UserService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.hanserwei.chat.utils;
|
||||
|
||||
import org.jasypt.util.text.AES256TextEncryptor;
|
||||
|
||||
public class EncryptorUtil {
|
||||
public static void main(String[] args) {
|
||||
AES256TextEncryptor textEncryptor = new AES256TextEncryptor();
|
||||
textEncryptor.setPassword("yyyyyyyyyyyy");
|
||||
System.out.println(textEncryptor.encrypt("xxxxxxxxxxxxxxxxxxxxxx"));
|
||||
}
|
||||
}
|
||||
66
snails-chat/src/main/resources/config/application.yml
Normal file
66
snails-chat/src/main/resources/config/application.yml
Normal file
@@ -0,0 +1,66 @@
|
||||
#file: noinspection SpringBootConfigYamlInspection
|
||||
server:
|
||||
servlet:
|
||||
encoding:
|
||||
charset: utf-8
|
||||
force: true
|
||||
spring:
|
||||
application:
|
||||
name: snails-ai
|
||||
banner:
|
||||
location: config/banner.txt
|
||||
data:
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
password: redis
|
||||
database: 4
|
||||
lettuce:
|
||||
pool:
|
||||
enabled: true
|
||||
max-active: 20
|
||||
max-idle: 10
|
||||
max-wait: 10000
|
||||
min-idle: 10
|
||||
time-between-eviction-runs: 10000
|
||||
datasource:
|
||||
driver-class-name: org.postgresql.Driver
|
||||
url: jdbc:postgresql://localhost:5432/postgres
|
||||
username: postgres
|
||||
password: postgressql
|
||||
# HikariCP 连接池配置
|
||||
hikari:
|
||||
maximum-pool-size: 20 # 最大连接数设置为 20
|
||||
minimum-idle: 20 # 保持 20 个空闲连接(与最大连接数一致)
|
||||
connection-timeout: 5000 # 获取连接超时 5 秒
|
||||
max-lifetime: 28800000 # 8 小时(确保在数据库连接超时前被回收)
|
||||
ai:
|
||||
memory:
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
timeout: 5000
|
||||
password: redis
|
||||
dashscope:
|
||||
api-key: ENC(cMgcKZkFllyE88DIbGwLKot9Vg02co+gsmY8L8o4/o3UjhcmqO4lJzFU35Sx0n+qFG8pDL0wBjoWrT8X6BuRw9vNlQhY1LgRWHaF9S1zzyM=)
|
||||
chat:
|
||||
options:
|
||||
model: qwen-plus
|
||||
temperature: 0.5
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||
global-config:
|
||||
banner: false
|
||||
mapper-locations: classpath*:/mapperxml/*.xml
|
||||
logging:
|
||||
level:
|
||||
# 隐藏掉 Hibernate 冗长的连接池 INFO 信息
|
||||
org.hibernate.orm.connections.pooling: WARN
|
||||
org.springframework.ai.chat.client.advisor: DEBUG
|
||||
jasypt:
|
||||
encryptor:
|
||||
password: ${jasypt.encryptor.password}
|
||||
algorithm: PBEWithHMACSHA512AndAES_256
|
||||
iv-generator-classname: org.jasypt.iv.RandomIvGenerator
|
||||
11
snails-chat/src/main/resources/config/banner.txt
Normal file
11
snails-chat/src/main/resources/config/banner.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
___ ___ ___ ___ ___ ___
|
||||
/\ \ /\__\ /\ \ ___ /\__\ /\ \ /\ \ ___
|
||||
/::\ \ /::| | /::\ \ /\ \ /:/ / /::\ \ /::\ \ /\ \
|
||||
/:/\ \ \ /:|:| | /:/\:\ \ \:\ \ /:/ / /:/\ \ \ /:/\:\ \ \:\ \
|
||||
_\:\~\ \ \ /:/|:| |__ /::\~\:\ \ /::\__\ /:/ / _\:\~\ \ \ /::\~\:\ \ /::\__\
|
||||
/\ \:\ \ \__\ /:/ |:| /\__\ /:/\:\ \:\__\ __/:/\/__/ /:/__/ /\ \:\ \ \__\ /:/\:\ \:\__\ __/:/\/__/
|
||||
\:\ \:\ \/__/ \/__|:|/:/ / \/__\:\/:/ / /\/:/ / \:\ \ \:\ \:\ \/__/ \/__\:\/:/ / /\/:/ /
|
||||
\:\ \:\__\ |:/:/ / \::/ / \::/__/ \:\ \ \:\ \:\__\ \::/ / \::/__/
|
||||
\:\/:/ / |::/ / /:/ / \:\__\ \:\ \ \:\/:/ / /:/ / \:\__\
|
||||
\::/ / /:/ / /:/ / \/__/ \:\__\ \::/ / /:/ / \/__/
|
||||
\/__/ \/__/ \/__/ \/__/ \/__/ \/__/
|
||||
18
snails-chat/src/main/resources/mapperxml/UserMapper.xml
Normal file
18
snails-chat/src/main/resources/mapperxml/UserMapper.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.hanserwei.chat.domain.mapper.UserMapper">
|
||||
<resultMap id="BaseResultMap" type="com.hanserwei.chat.domain.dataobject.User">
|
||||
<!--@mbg.generated-->
|
||||
<!--@Table t_user-->
|
||||
<id column="id" jdbcType="INTEGER" property="id" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="email" jdbcType="VARCHAR" property="email" />
|
||||
<result column="age" jdbcType="INTEGER" property="age" />
|
||||
<result column="created_at" jdbcType="TIMESTAMP" property="createdAt" />
|
||||
<result column="is_active" jdbcType="BOOLEAN" property="isActive" />
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
<!--@mbg.generated-->
|
||||
id, "name", email, age, created_at, is_active
|
||||
</sql>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user