diff --git a/src/main/java/com/yolo/keyborad/config/AsyncConfig.java b/src/main/java/com/yolo/keyborad/config/AsyncConfig.java index 34c7ed8..679e2ee 100644 --- a/src/main/java/com/yolo/keyborad/config/AsyncConfig.java +++ b/src/main/java/com/yolo/keyborad/config/AsyncConfig.java @@ -1,10 +1,45 @@ package com.yolo.keyborad.config; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import java.util.concurrent.Executor; + +/** + * 异步任务配置 + */ @Configuration @EnableAsync public class AsyncConfig { + /** + * 默认异步任务执行器 + * 用于处理 @Async 注解的异步方法 + */ + @Bean(name = "taskExecutor") + public Executor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + // 核心线程数 + executor.setCorePoolSize(10); + // 最大线程数 + executor.setMaxPoolSize(20); + // 队列容量 + executor.setQueueCapacity(200); + // 线程名称前缀 + executor.setThreadNamePrefix("async-task-"); + // 拒绝策略:由调用线程处理 + executor.setRejectedExecutionHandler(new java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy()); + // 线程空闲时间(秒) + executor.setKeepAliveSeconds(60); + // 等待所有任务结束后再关闭线程池 + executor.setWaitForTasksToCompleteOnShutdown(true); + // 等待时间(秒) + executor.setAwaitTerminationSeconds(60); + + executor.initialize(); + return executor; + } } diff --git a/src/main/java/com/yolo/keyborad/config/CorsConfig.java b/src/main/java/com/yolo/keyborad/config/CorsConfig.java index 0bd6673..0c80d39 100644 --- a/src/main/java/com/yolo/keyborad/config/CorsConfig.java +++ b/src/main/java/com/yolo/keyborad/config/CorsConfig.java @@ -1,6 +1,8 @@ package com.yolo.keyborad.config; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @@ -24,4 +26,31 @@ public class CorsConfig implements WebMvcConfigurer { .allowedHeaders("*") .exposedHeaders("*"); } + + /** + * 配置 WebMvc 异步请求处理的执行器 + * 用于处理异步 HTTP 请求(如 DeferredResult、Callable 等) + */ + @Override + public void configureAsyncSupport(AsyncSupportConfigurer configurer) { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + + // 核心线程数 + executor.setCorePoolSize(10); + // 最大线程数 + executor.setMaxPoolSize(30); + // 队列容量 + executor.setQueueCapacity(100); + // 线程名称前缀 + executor.setThreadNamePrefix("mvc-async-"); + // 线程空闲时间(秒) + executor.setKeepAliveSeconds(60); + + executor.initialize(); + + // 设置异步请求超时时间(毫秒) + configurer.setDefaultTimeout(30000); + // 设置异步请求执行器 + configurer.setTaskExecutor(executor); + } } diff --git a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java index 02d439e..4077171 100644 --- a/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java +++ b/src/main/java/com/yolo/keyborad/config/SaTokenConfigure.java @@ -79,7 +79,9 @@ public class SaTokenConfigure implements WebMvcConfigurer { "/user/verifyMailCode", "/character/listWithNotLogin", "/character/listByTagWithNotLogin", - "/character/detailWithNotLogin" + "/character/detailWithNotLogin", + "/character/addUserCharacter", + "/api/apple/validate-receipt" }; } @Bean diff --git a/src/main/java/com/yolo/keyborad/config/SecurityConfig.java b/src/main/java/com/yolo/keyborad/config/SecurityConfig.java index 9a35d9c..b7a4f7d 100644 --- a/src/main/java/com/yolo/keyborad/config/SecurityConfig.java +++ b/src/main/java/com/yolo/keyborad/config/SecurityConfig.java @@ -1,11 +1,15 @@ package com.yolo.keyborad.config; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.SecurityFilterChain; @Configuration @@ -33,4 +37,13 @@ public class SecurityConfig { return http.build(); } + + /** + * 提供一个空的 UserDetailsService,防止 Spring Security 自动配置生成默认密码 + */ + @Bean + @ConditionalOnMissingBean(UserDetailsService.class) + public UserDetailsService userDetailsService() { + return new InMemoryUserDetailsManager(); + } } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/controller/DemoController.java b/src/main/java/com/yolo/keyborad/controller/DemoController.java index 6b31c81..605453b 100644 --- a/src/main/java/com/yolo/keyborad/controller/DemoController.java +++ b/src/main/java/com/yolo/keyborad/controller/DemoController.java @@ -1,5 +1,6 @@ package com.yolo.keyborad.controller; +import cn.dev33.satoken.stp.StpUtil; import cn.hutool.json.JSONUtil; import com.yolo.keyborad.common.BaseResponse; import com.yolo.keyborad.common.ResultUtils; @@ -18,11 +19,13 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.embedding.Embedding; import org.springframework.ai.embedding.EmbeddingResponse; +import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.OpenAiEmbeddingModel; import org.springframework.boot.context.properties.bind.DefaultValue; import org.springframework.web.bind.annotation.*; import reactor.core.publisher.Flux; +import java.util.Arrays; import java.util.List; /* @@ -59,15 +62,34 @@ public class DemoController { @Operation(summary = "测试聊天接口", description = "测试接口") @Parameter(name = "userInput",required = true,description = "测试聊天接口",example = "talk to something") public Flux testTalk(@DefaultValue("you are so cute!") String userInput){ + String delimiter = "/t"; + return client - .prompt("You're a 25-year-old guy—witty and laid-back, always replying in English.\n" + - "Read the user's last message, then write three short and funny replies that sound like something a guy would say. Go easy on the emojis.\n" + - "Keep each under 20 words. Use '/t' to separate them—no numbers or extra labels.") + .prompt(""" + You're a 25-year-old guy—witty and laid-back, always replying in English. + + Read the user's last message, then write three short and funny replies that sound like something a guy would say. + Go easy on the emojis. + Keep each under 20 words. + + User message: %s + """.formatted(userInput)) + .system(""" + Format rules (very important): + - Return EXACTLY 3 replies. + - Use "" as the separator between replies. + - Output format: reply1reply2reply3 + - Do NOT use "" inside any reply. + """) .user(userInput) + .options(OpenAiChatOptions.builder() + .user(StpUtil.getLoginIdAsString()) // ✅ 这里每次请求都会重新取当前登录用户 + .build()) .stream() .content(); } + @PostMapping("/embed") @Operation(summary = "测试向量接口", description = "测试向量接口") @Parameter(name = "userInput",required = true,description = "测试向量接口",example = "you are so cute!") diff --git a/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterAddDTO.java b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterAddDTO.java index 9863a1f..b99a97f 100644 --- a/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterAddDTO.java +++ b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterAddDTO.java @@ -1,5 +1,6 @@ package com.yolo.keyborad.model.dto.userCharacter; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -12,4 +13,6 @@ public class KeyboardUserCharacterAddDTO { @Schema(description="键盘人设 id") private Long characterId; + @Schema(description = "emoji") + private String emoji; } diff --git a/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterDTO.java b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterDTO.java index 1c5f101..c837b6a 100644 --- a/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterDTO.java +++ b/src/main/java/com/yolo/keyborad/model/dto/userCharacter/KeyboardUserCharacterDTO.java @@ -1,5 +1,6 @@ package com.yolo.keyborad.model.dto.userCharacter; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -25,4 +26,8 @@ public class KeyboardUserCharacterDTO { @Schema(description = "是否删除") private Boolean deleted; + + @TableField(value = "emoji") + @Schema(description = "emoji") + private String emoji; } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/model/entity/KeyboardCharacter.java b/src/main/java/com/yolo/keyborad/model/entity/KeyboardCharacter.java index e50fa4a..7d8b263 100644 --- a/src/main/java/com/yolo/keyborad/model/entity/KeyboardCharacter.java +++ b/src/main/java/com/yolo/keyborad/model/entity/KeyboardCharacter.java @@ -60,4 +60,8 @@ public class KeyboardCharacter { @TableField(value = "\"rank\"") @Schema(description="排名顺序") private Integer rank; + + @TableField(value = "emoji") + @Schema(description = "emoji") + private String emoji; } \ No newline at end of file diff --git a/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java b/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java index 6b782bf..0a1d18e 100644 --- a/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java +++ b/src/main/java/com/yolo/keyborad/model/vo/character/KeyboardCharacterRespVO.java @@ -40,4 +40,7 @@ public class KeyboardCharacterRespVO { @Schema(description = "是否添加") private Boolean added; + + @Schema(description = "emoji") + private String emoji; } \ No newline at end of file diff --git a/src/main/resources/mapper/KeyboardCharacter‌Mapper.xml b/src/main/resources/mapper/KeyboardCharacter‌Mapper.xml index 6d28caa..c58f8d4 100644 --- a/src/main/resources/mapper/KeyboardCharacter‌Mapper.xml +++ b/src/main/resources/mapper/KeyboardCharacter‌Mapper.xml @@ -14,9 +14,10 @@ + id, character_name, "character_background", avatar_url, download, tag, deleted, created_at, - updated_at, prompt, "rank" + updated_at, prompt, "rank",emoji \ No newline at end of file