init: 导入RuoYi‑Vue‑Plus 6.X完整代码
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
# 贝尔实验室 Spring 官方推荐镜像 JDK下载地址 https://bell-sw.com/pages/downloads/
|
||||
FROM bellsoft/liberica-openjdk-rocky:21.0.12-cds
|
||||
# FROM bellsoft/liberica-openjdk-rocky:25.0.4-cds
|
||||
# FROM findepi/graalvm:java21-native
|
||||
|
||||
LABEL maintainer="Lion Li"
|
||||
|
||||
RUN mkdir -p /ruoyi/snailai/logs
|
||||
|
||||
WORKDIR /ruoyi/snailai
|
||||
|
||||
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS=""
|
||||
|
||||
EXPOSE 8900
|
||||
EXPOSE 18888
|
||||
|
||||
ADD ./target/ruoyi-snailai-server.jar ./app.jar
|
||||
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
|
||||
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom \
|
||||
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
|
||||
-jar app.jar
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-extend</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-snailai-server</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- Snail AI 服务端 -->
|
||||
<dependency>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>snail-ai-starter</artifactId>
|
||||
<version>${snailai.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>co.elastic.clients</groupId>
|
||||
<artifactId>elasticsearch-rest5-client</artifactId>
|
||||
<version>9.4.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>co.elastic.clients</groupId>
|
||||
<artifactId>elasticsearch-java</artifactId>
|
||||
<version>9.4.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring Boot Admin 客户端 -->
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
<version>${spring-boot-admin.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring-boot.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
package com.aizuda.snail.ai.starter.filter;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Actuator Basic Auth 认证过滤器。
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class ActuatorAuthFilter implements Filter {
|
||||
|
||||
/**
|
||||
* 认证用户名。
|
||||
*/
|
||||
private final String username;
|
||||
/**
|
||||
* 认证密码。
|
||||
*/
|
||||
private final String password;
|
||||
|
||||
/**
|
||||
* 创建 Actuator 认证过滤器。
|
||||
*
|
||||
* @param username 认证用户名
|
||||
* @param password 认证密码
|
||||
*/
|
||||
public ActuatorAuthFilter(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验 Actuator Basic Auth 请求。
|
||||
*
|
||||
* @param servletRequest 原始请求
|
||||
* @param servletResponse 原始响应
|
||||
* @param filterChain 过滤器链
|
||||
* @throws IOException IO 异常
|
||||
* @throws ServletException Servlet 异常
|
||||
*/
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
if (authHeader == null || !authHeader.startsWith("Basic ")) {
|
||||
response.setHeader("WWW-Authenticate", "Basic realm=\"realm\"");
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
|
||||
String base64Credentials = authHeader.substring("Basic ".length());
|
||||
byte[] credDecoded = Base64.getDecoder().decode(base64Credentials);
|
||||
String credentials = new String(credDecoded, StandardCharsets.UTF_8);
|
||||
String[] split = credentials.split(":");
|
||||
if (split.length != 2) {
|
||||
response.setHeader("WWW-Authenticate", "Basic realm=\"realm\"");
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
if (!username.equals(split[0]) || !password.equals(split[1])) {
|
||||
response.setHeader("WWW-Authenticate", "Basic realm=\"realm\"");
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||
return;
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化过滤器。
|
||||
*
|
||||
* @param filterConfig 过滤器配置
|
||||
*/
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁过滤器。
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package com.aizuda.snail.ai.starter.filter;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* 权限安全配置
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
|
||||
/**
|
||||
* 认证用户名。
|
||||
*/
|
||||
@Value("${spring.boot.admin.client.username}")
|
||||
private String username;
|
||||
/**
|
||||
* 认证密码。
|
||||
*/
|
||||
@Value("${spring.boot.admin.client.password}")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 注册 Actuator Basic Auth 过滤器。
|
||||
*
|
||||
* @return Actuator 过滤器注册对象
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean<ActuatorAuthFilter> actuatorFilterRegistrationBean() {
|
||||
FilterRegistrationBean<ActuatorAuthFilter> registrationBean = new FilterRegistrationBean<>();
|
||||
registrationBean.setFilter(new ActuatorAuthFilter(username, password));
|
||||
registrationBean.addUrlPatterns("/actuator", "/actuator/*");
|
||||
return registrationBean;
|
||||
}
|
||||
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package org.dromara.snailai;
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
/**
|
||||
* Snail AI Server 启动程序
|
||||
*
|
||||
* @author Lion Li
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
@SpringBootApplication
|
||||
public class SnailAiServerApplication {
|
||||
|
||||
/**
|
||||
* Snail AI 服务启动入口。
|
||||
*
|
||||
* @param args 启动参数
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
com.aizuda.snail.ai.starter.SnailAiApplication.main(args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: root
|
||||
hikari:
|
||||
connection-timeout: 30000
|
||||
validation-timeout: 5000
|
||||
minimum-idle: 10
|
||||
maximum-pool-size: 20
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 900000
|
||||
keepaliveTime: 30000
|
||||
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
metadata:
|
||||
username: ${spring.boot.admin.client.username}
|
||||
userpassword: ${spring.boot.admin.client.password}
|
||||
username: @monitor.username@
|
||||
password: @monitor.password@
|
||||
@@ -0,0 +1,28 @@
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: root
|
||||
hikari:
|
||||
connection-timeout: 30000
|
||||
validation-timeout: 5000
|
||||
minimum-idle: 10
|
||||
maximum-pool-size: 20
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 900000
|
||||
keepaliveTime: 30000
|
||||
|
||||
--- # 监控中心配置
|
||||
spring.boot.admin.client:
|
||||
# 增加客户端开关
|
||||
enabled: true
|
||||
url: http://localhost:9090/admin
|
||||
instance:
|
||||
service-host-type: IP
|
||||
metadata:
|
||||
username: ${spring.boot.admin.client.username}
|
||||
userpassword: ${spring.boot.admin.client.password}
|
||||
username: @monitor.username@
|
||||
password: @monitor.password@
|
||||
@@ -0,0 +1,87 @@
|
||||
server:
|
||||
port: 8900
|
||||
servlet:
|
||||
context-path: /snail-ai
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: ruoyi-snailai-server
|
||||
profiles:
|
||||
active: @profiles.active@
|
||||
servlet:
|
||||
multipart:
|
||||
enabled: true
|
||||
# 单个文件的最大限制 (根据 RAG 需求建议设为 50MB - 100MB)
|
||||
max-file-size: 50MB
|
||||
# 单次请求的总文件大小限制 (如果支持多文件并行上传,调大此项)
|
||||
max-request-size: 100MB
|
||||
web:
|
||||
resources:
|
||||
static-locations: classpath:admin/
|
||||
|
||||
snail-ai:
|
||||
server:
|
||||
grpc-port: 18888
|
||||
skill:
|
||||
upload-dir: ./upload/skills
|
||||
crypto:
|
||||
secret-key: ${SNAIL_AI_CRYPTO_KEY:0123456789abcdef0123456789abcdef}
|
||||
iv: ${SNAIL_AI_CRYPTO_IV:fedcba9876543210fedcba9876543210}
|
||||
resource:
|
||||
storage-type: LOCAL
|
||||
upload-dir: ./upload/resource
|
||||
minio:
|
||||
endpoint: http://localhost:9000
|
||||
access-key: minioadmin
|
||||
secret-key: minioadmin
|
||||
bucket: snail-ai
|
||||
# RAG 文档解析与图片 OCR 配置
|
||||
rag:
|
||||
docling:
|
||||
enabled: ${SNAIL_AI_RAG_DOCLING_ENABLED:true}
|
||||
url: ${SNAIL_AI_RAG_DOCLING_URL:http://127.0.0.1:5100}
|
||||
timeout-seconds: ${SNAIL_AI_RAG_DOCLING_TIMEOUT_SECONDS:300}
|
||||
concurrency: ${SNAIL_AI_RAG_DOCLING_CONCURRENCY:3}
|
||||
health-timeout-millis: ${SNAIL_AI_RAG_DOCLING_HEALTH_TIMEOUT_MILLIS:3000}
|
||||
poll-interval-millis: ${SNAIL_AI_RAG_DOCLING_POLL_INTERVAL_MILLIS:3000}
|
||||
status-timeout-millis: ${SNAIL_AI_RAG_DOCLING_STATUS_TIMEOUT_MILLIS:10000}
|
||||
result-timeout-millis: ${SNAIL_AI_RAG_DOCLING_RESULT_TIMEOUT_MILLIS:30000}
|
||||
max-image-count: ${SNAIL_AI_RAG_DOCLING_MAX_IMAGE_COUNT:100}
|
||||
max-image-bytes: ${SNAIL_AI_RAG_DOCLING_MAX_IMAGE_BYTES:10485760}
|
||||
paddle-ocr-enabled: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_ENABLED:true}
|
||||
paddle-ocr-url: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_URL:http://127.0.0.1:8866/ocr}
|
||||
paddle-ocr-timeout-millis: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_TIMEOUT_MILLIS:180000}
|
||||
paddle-ocr-batch-size: ${SNAIL_AI_RAG_DOCLING_PADDLE_OCR_BATCH_SIZE:5}
|
||||
vision-ocr-fallback-enabled: ${SNAIL_AI_RAG_DOCLING_VISION_OCR_FALLBACK_ENABLED:false}
|
||||
# 短期记忆配置
|
||||
memory:
|
||||
short-term:
|
||||
# 存储类型选项: memory(内存) | db(数据库)
|
||||
# - memory: 适用于单机部署,高性能,重启后数据丢失
|
||||
# - db: 适用于分布式部署,数据持久化,性能较低
|
||||
store-type: db
|
||||
|
||||
mybatis-plus:
|
||||
typeAliasesPackage: com.aizuda.snail.ai.persistence
|
||||
global-config:
|
||||
db-config:
|
||||
capital-mode: false
|
||||
logic-delete-value: 1
|
||||
logic-not-delete-value: 0
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
cache-enabled: true
|
||||
|
||||
logging:
|
||||
config: classpath:logback-plus.xml
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
endpoint:
|
||||
health:
|
||||
show-details: ALWAYS
|
||||
logfile:
|
||||
external-file: ./logs/ruoyi-snailai-server/console.log
|
||||
@@ -0,0 +1,9 @@
|
||||
Application Version: ${revision}
|
||||
Spring Boot Version: ${spring-boot.version}
|
||||
_ _ _
|
||||
(_) | (_)
|
||||
___ _ __ __ _ _| |______ __ _ _
|
||||
/ __| '_ \ / _` | | |______/ _` | |
|
||||
\__ \ | | | (_| | | | | (_| | |
|
||||
|___/_| |_|\__,_|_|_| \__,_|_|
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<property name="log.path" value="./logs/ruoyi-snailai-server" />
|
||||
<property name="console.log.pattern"
|
||||
value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>${console.log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出 -->
|
||||
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/console.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<!-- 日志文件名格式 -->
|
||||
<fileNamePattern>${log.path}/console.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||
<!-- 日志最大 1天 -->
|
||||
<maxHistory>1</maxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
<charset>utf-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<!-- 过滤的级别 -->
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/info.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</FileNamePattern>
|
||||
<MaxHistory>60</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>INFO</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${log.path}/error.log</file>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||
<FileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log
|
||||
</FileNamePattern>
|
||||
<MaxHistory>60</MaxHistory>
|
||||
</rollingPolicy>
|
||||
<encoder>
|
||||
<pattern>${log.pattern}</pattern>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name ="async_info" class= "ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold >100</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref ="file_info"/>
|
||||
</appender>
|
||||
|
||||
<appender name ="async_error" class= "ch.qos.logback.classic.AsyncAppender">
|
||||
<discardingThreshold >100</discardingThreshold>
|
||||
<queueSize>1024</queueSize>
|
||||
<appender-ref ref ="file_error"/>
|
||||
</appender>
|
||||
|
||||
<!-- 控制台输出日志级别 -->
|
||||
<root level="info">
|
||||
<appender-ref ref="console" />
|
||||
<appender-ref ref="file_console" />
|
||||
<appender-ref ref="async_info" />
|
||||
<appender-ref ref="async_error" />
|
||||
</root>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user