# sqlrest **Repository Path**: tianxiaohua/sqlrest ## Basic Information - **Project Name**: sqlrest - **Description**: SQLREST是一款完全开源的SQL转 RESTful API的SQL2API低代码工具 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: https://gitee.com/inrgihc/sqlrest - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 315 - **Created**: 2026-08-14 - **Last Updated**: 2026-09-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SQLREST 项目说明文档(开发者视角) > 一款将 SQL 操作转化为 RESTful API 的便捷工具 - 坐标:`org.dromara.sqlrest:sqlrest-parent` - 版本:`1.9.0` - 语言: [简体中文](README.zh.md) [English](README.md) 本文档基于项目源码(`e:/03Codes/04db/RESTful-API-sqlrest`)实际实现撰写,重点揭示模块间的调用关系、配置加载机制与运行时数据流,帮助开发者快速建立全貌并在本地跑通项目。 --- ## 目录 1. [项目背景与目标](#1-项目背景与目标) 2. [技术栈与依赖](#2-技术栈与依赖) 3. [目录结构说明](#3-目录结构说明) 4. [系统架构](#4-系统架构) 5. [核心模块与功能解析](#5-核心模块与功能解析) 6. [系统部署拓扑](#6-系统部署拓扑) 7. [安装与运行步骤](#7-安装与运行步骤) 8. [配置说明](#8-配置说明) 9. [常见问题排查](#9-常见问题排查) 10. [贡献指南](#10-贡献指南) --- ## 1. 项目背景与目标 在数据平台、BI 工具、低代码平台等场景中,经常出现「把数据库查询结果快速暴露为接口」的需求。传统做法需要为每个查询编写 Controller、Service、DAO,开发与维护成本高。 **SQLREST** 的设计目标是:**让 SQL(或类 SQL 的 DSL)本身成为 API 定义**。用户在管理后台选择数据源、编写 SQL/脚本、绑定参数并配置路径,即可零编码生成对外 API,无需编写后端逻辑。其核心价值: - **数据访问中间件**:作为微服务架构中「数据库 ↔ 业务系统」的薄封装层。 - **动态 API 运行时**:API 定义存储在元数据库,由执行器(executor)在运行时加载并对外提供服务,支持热部署/下线。 - **多数据源/多协议**:支持 20+ 关系型与国产数据库、MongoDB/ElasticSearch 文档库、以及基于 HTTP 的下游 RESTful API 转发。 > 与同类工具的区别:SQLREST 不是单进程工具,而是一个由 **网关 / 执行器 / 管理器** 三个可独立部署节点组成的微服务,通过 Eureka 注册发现协作,天然支持分布式与水平扩展。 --- ## 2. 技术栈与依赖 | 类别 | 技术 / 组件 | 备注 | |---|---|---| | 语言 / 构建 | Java 8、Maven(多模块,`pom.xml` 父工程) | JDK 建议 1.8 | | 核心框架 | Spring Boot `2.5.6`、Spring Cloud `2020.0.4` | | | 服务注册 | Netflix Eureka | 由 `sqlrest-manager` 托管 `@EnableEurekaServer` | | API 网关 | Spring Cloud Gateway(WebFlux 响应式) | 纯反向代理,无业务控制器 | | ORM / SQL | MyBatis `3.5.9`、MyBatis-Plus `3.5.4.1`、PageHelper `1.4.2` | 元数据持久化 + 动态 SQL 执行 | | 动态 SQL | MyBatis `ScriptRunner` / OGNL 表达式求值 | 解析 ``、`` 等动态标签 | | 脚本引擎 | Groovy `3.0.20` | 复杂接口后置处理(`exec` 包) | | 缓存 | Hazelcast `4.2.8`(默认)/ Redis(Jedis) | `sqlrest-cache` 抽象 `DistributedCache` | | 流控 | Sentinel `2023.0.1.0` | 守护 executor 端点,限流返回 429 | | HTTP 客户端 | Apache HttpClient5 `5.4.3` | DSL 的 `http` 类型转发 | | 表结构迁移 | Liquibase | manager 元数据表自动建表/升级 | | API 文档 | Springfox Swagger `3.0.0` / Knife4j | 管理后台与动态 API 在线文档 | | 协议 | 自研 MCP(`sqlrest-mcp`) | 暴露为 `/mcp`、`/mcp/sse` 端点 | | 工具库 | Hutool `5.7.5`、Guava `23.0`、commons-lang3/collections4 | | | 前端界面 | Vue `2.5.2` + Element-UI `2.15.6` + webpack `3`(sqlrest-manager-ui) | echarts、vue-codemirror、mxgraph-js、vue-i18n | 核心外部依赖统一在父 `pom.xml` 的 `` 中锁定版本(`spring-boot.version=2.5.6`、`spring-cloud.version=2020.0.4`)。 --- ## 3. 目录结构说明 ``` sqlrest/ ├── pom.xml # 父 POM(多模块聚合,version=1.9.0) ├── build.cmd / build.sh # 一键构建脚本(mvn clean package) ├── docker-maven-build.sh # Docker 内构建脚本 ├── version.cmd # 版本变量 ├── drivers/ # 各数据库 JDBC/驱动 jar(24 个子目录) │ ├── mysql/ oracle/ postgresql/ dm/ kingbase/ ... │ ├── mongodb/ elasticsearch/ http/ # 文档库 / HTTP 转发驱动 │ └── clickhouse/ doris/ starrocks/ tdengine/ ... ├── docs/ # 文档图片与建表 SQL 示例 ├── build-docker/ # 容器化部署与 docker-compose 安装脚本 ├── sqlrest-common/ # 公共定义:DTO、常量、统一响应、异常、工具 ├── sqlrest-mcp/ # MCP 协议模块 │ ├── sqlrest-mcp-core/ # 协议核心(Jackson + HttpClient5 自研实现) │ └── sqlrest-mcp-springmvc/ # Spring MVC 端点暴露 ├── sqlrest-template/ # SQL 内容模板(MyBatis 动态 SQL 解析) ├── sqlrest-persistence/ # 元数据库持久化(MyBatis-Plus / Mapper / 实体) ├── sqlrest-core/ # 核心实现:driver、servlet、service、exec、cache 装配 ├── sqlrest-cache/ # 缓存模块:Hazelcast / Redis 实现 ├── sqlrest-executor/ # 执行器节点(内嵌 Tomcat,HttpApiServlet) ├── sqlrest-gateway/ # 网关节点(Spring Cloud Gateway) ├── sqlrest-manager/ # 管理节点(Eureka Server + 后台 API + 静态 UI) ├── sqlrest-manager-ui/ # Web 前端(Vue,构建产物打入 manager 的 static) └── sqlrest-dist/ # 打包模块(maven-assembly 产出 sqlrest-release) ``` **模块依赖拓扑**(编译期,箭头表示「依赖」): ``` common ← persistence ← core ← {executor, gateway, manager} template ←┘ cache ←┘ manager ← mcp-springmvc ← mcp-core dist(仅聚合,不参与编译依赖) ``` | 模块 | 依赖 | 关键外部依赖 | |---|---|---| | sqlrest-common | — | lombok、guava、commons、hutool、swagger、servlet-api | | sqlrest-template | — | mybatis(仅 SQL 模板解析) | | sqlrest-persistence | sqlrest-common | mysql/postgres 驱动、mybatis-plus、pagehelper、jackson | | sqlrest-core | template、persistence、cache | groovy、spring-web、validation、actuator、eureka-client | | sqlrest-cache | sqlrest-common | hazelcast-all、hazelcast-eureka-one、jedis | | sqlrest-executor | sqlrest-core | spring-boot-starter-web、actuator、eureka-client、sentinel | | sqlrest-gateway | sqlrest-core | spring-boot-starter-webflux、spring-cloud-starter-gateway、eureka-client | | sqlrest-manager | sqlrest-core、sqlrest-mcp-springmvc | spring-boot-starter-web、eureka-server、liquibase-core | | sqlrest-mcp | —(core + springmvc 子模块) | 自研 MCP 协议(jackson、httpclient5) | | sqlrest-dist | — | maven-assembly(产出 `sqlrest-release`) | --- ## 4. 系统架构 ### 4.1 三节点微服务架构 SQLREST 由三个可独立部署、通过 Eureka 协作的节点组成: - **manager**(`sqlrest-manager`,默认端口 `8090`):既是 **Eureka Server**(服务注册中心),也是**管理后台**。负责数据源、API 赋权(assignment)、用户、客户端、防火墙、MCP 工具等元数据的管理,通过 MyBatis-Plus 持久化到外部 MySQL/PostgreSQL;并通过 `ManagerWebConfiguration` 将前端构建产物(`classpath:/index.html`、`/static/**`)作为静态资源对外提供。 - **gateway**(`sqlrest-gateway`,默认端口 `8091`):基于 Spring Cloud Gateway(WebFlux 响应式)的纯**反向代理**。`web-application-type: reactive`,无任何业务控制器,仅按服务名(`lb://sqlrest-executor`、`lb://sqlrest-manager`)转发流量,全开 CORS。 - **executor**(`sqlrest-executor`,默认端口 `8092`):真正**执行** SQL/DSL 的节点。内嵌 Tomcat,`HttpApiServlet` 映射到 `/api/*` 对外提供用户自定义的动态 API,并负责 Token 生成与缓存。 ```mermaid flowchart TB subgraph Client[客户端] B[浏览器 / 外部 HTTP 调用方] LLM[LLM 客户端 / MCP] end subgraph GW[sqlrest-gateway :8091 反向代理] G[Spring Cloud Gateway
routes: /api/** /token /apidoc/** -> executor
/user/** /sqlrest/manager/** -> manager] end subgraph EX[sqlrest-executor :8092 执行器] S[HttpApiServlet /api/*] F[AuthenticationFilter 鉴权+流控] A[ApiExecuteService] D[DriverLoadService 加载 drivers/] H[HikariCP 连接池] C[CacheService
Hazelcast/Redis] end subgraph MG[sqlrest-manager :8090 管理+注册中心] E[Eureka Server 注册中心] API[后台 API / Mapper / Service] UI[静态前端 index.html] MCPC[McpToolController / McpClientController] end DB[(元数据库 MySQL/PostgreSQL
Liquibase 自动建表)] TARGET[(业务数据库 / MongoDB / ES / 下游 HTTP)] LLMREG[SQLREST_MCP_TOOL / SQLREST_MCP_CLIENT 表] B --> G LLM -->|/mcp /mcp/sse| G G -->|lb://sqlrest-executor| S G -->|lb://sqlrest-manager| API G -->|lb://sqlrest-manager| UI S --> F --> A A --> C A --> D --> H --> TARGET F -.记录访问.-> DB EX -.register/discover.-> E MG -.托管 Eureka.-> E API --> DB MCPC --> LLMREG LLMREG --> DB ``` ### 4.2 动态 API 调用与数据流(executor 内部) ```mermaid sequenceDiagram participant C as 调用方 participant GW as Gateway participant SV as HttpApiServlet participant AF as AuthenticationFilter participant AE as ApiExecuteService participant DL as DriverLoadService participant DS as HikariCP / 驱动 participant CA as CacheService C->>GW: POST /api/{path} GW->>SV: 转发(lb://sqlrest-executor) SV->>AF: 进入过滤器 AF->>AF: 按 method+path 查 SQLREST_API_ONLINE alt open=false AF->>AF: 校验 Bearer Token + 分组权限 end AF->>SV: 放行(配置存入 ThreadLocal) SV->>AE: execute(config, request) AE->>AE: 合并 Header/Body/Query 参数 + 必填校验 AE->>CA: 命中缓存? alt 命中 CA-->>AE: 返回缓存结果 else 未命中 AE->>DL: getVersionDriverFile(type, version) DL->>DS: 建立连接并执行 SQL/DSL/Groovy DS-->>AE: 结果集 AE->>CA: 写回缓存 end AE-->>SV: ResultEntity SV-->>C: JSON(完整响应或仅 data) ``` ### 4.3 统一响应格式 所有 manager / executor 接口统一返回 `org.dromara.sqlrest.common.dto.ResultEntity`: ```json { "code": 0, "message": "success", "data": { } } ``` - `code`:`0` 成功;非 `0` 为错误码(`ResponseErrorCode`)。 - 分页接口返回 `PageResult`(含 `pagination: {page, total, size}`)。 - Token 接口返回 `AccessToken`:`realName`、`appKey`、`accessToken`、`expireSeconds`(默认 `7200`,见 `Constants.CLIENT_TOKEN_DURATION_SECONDS`)。 ### 4.4 网关路由表 | 网关接收路径 | 转发至 | 节点 | 说明 | |---|---|---|---| | `/api/**` | `lb://sqlrest-executor` | executor | 用户自定义动态 API | | `/token/generate` | `lb://sqlrest-executor` | executor | 生成 AccessToken | | `/apidoc/**` | `lb://sqlrest-executor` | executor | 动态 API 在线文档 | | `/user/**` | `lb://sqlrest-manager` | manager | 登陆/登出 | | `/sqlrest/manager/**` | `lb://sqlrest-manager` | manager | 后台管理 API(前缀见 `Constants.MANGER_API_V1`) | | `/dashboard/**` | `lb://sqlrest-manager` | manager | Eureka 仪表盘(默认 `dashboard.enabled=false`) | > 路由定义见 `sqlrest-gateway/src/main/resources/application.yaml` 的 `spring.cloud.gateway.routes`。 --- ## 5. 核心模块与功能解析 ### 5.1 公共层 `sqlrest-common` - **统一响应**:`common.dto.ResultEntity` / `PageResult` / `AccessToken`。 - **常量**:`common.consts.Constants` —— `API_PATH_PREFIX="api"`、`MANGER_API_V1="/sqlrest/manager/api/v1"`、缓存名 `response_result`/`variable_value`、MCP 端点 `/mcp`、`/mcp/sse`、`/mcp/message`、Token 有效期 `7200` 秒、流控状态码 `429`。 - **异常**:`common.exception.ResponseErrorCode` 集中定义业务错误码;`CommonException`/`UnAuthorizedException`(401)/`UnPermissionException`(403) 贯穿各层。 - **工具**:`JdbcUrlUtils`、`JacksonUtils` 等。 ### 5.2 元数据持久化 `sqlrest-persistence` 基于 MyBatis-Plus,实体类以 `@TableName("SQLREST_xxx")` 映射到元数据库表(前缀统一 `SQLREST_`): | 实体(`entity/`) | 表名 | 用途 | |---|---|---| | `ApiAssignmentEntity` | `SQLREST_API_ASSIGNMENT` | API 赋权定义(SQL/DSL、参数、路径、状态) | | `ApiOnlineEntity` | `SQLREST_API_ONLINE` | 已部署上线的 API(executor 运行时查询对象) | | `ApiContextEntity` | `SQLREST_API_CONTEXT` | 赋权上下文(SQL 片段、命名策略) | | `DataSourceEntity` | `SQLREST_DATASOURCE` | 数据源连接信息(可加密落盘) | | `ApiModuleEntity` / `ApiGroupEntity` | `SQLREST_API_MODULE` / `SQLREST_API_GROUP` | API 模块树 / 分组 | | `AppClientEntity` / `ClientGroupEntity` | `SQLREST_APP_CLIENT` / `SQLREST_CLIENT_GROUP` | 调用方 appKey/appSecret 与授权分组 | | `SystemUserEntity` / `SystemParamEntity` | `SQLREST_SYSTEM_USER` / `SQLREST_SYSTEM_PARAM` | 后台用户 / 系统参数 | | `FirewallRulesEntity` | `SQLREST_FIREWALL_RULES` | IP/规则防火墙 | | `McpToolEntity` / `McpClientEntity` | `SQLREST_MCP_TOOL` / `SQLREST_MCP_CLIENT` | MCP 工具/客户端配置 | | `AccessRecordEntity` | `SQLREST_ACCESS_RECORD` | API 访问记录(鉴权后异步写入,供告警) | | `VersionCommitEntity` | `SQLREST_VERSION_COMMIT` | API 版本历史 | | `UnifyAlarmEntity` | `SQLREST_UNIFY_ALARM` | 统一告警配置 | 表结构由 **Liquibase** 在 manager 启动时自动迁移:`db/changelog/db.changelog-master.yaml` 串联 `log-v1.0.1` … `log-v1.7.1` 多个变更集;变更日志表为 `SQLREST_DB_CHANGE_LOG_RECORD`。 ### 5.3 核心实现 `sqlrest-core` 包结构(`org.dromara.sqlrest.core`): - **`servlet/`**:`AuthenticationFilter`(鉴权 + 流控 + 访问记录)、`ClientTokenService`(Token 校验与分组授权)、`ApiSwaggerService`(动态 API 文档生成)。 - **`driver/`**:`DriverLoadService` —— 监听 `ApplicationReadyEvent`,扫描 `datasource.driver.base-path`(运行时环境变量 `APP_DRIVERS_PATH`,即 `drivers/`)按 `类型/版本/jar` 三层结构加载驱动 jar,存入 `Map>`;仅加载 `ProductTypeEnum.exists(typeName)` 识别的数据库类型。 - **`exec/`**:`ApiExecuteService`(执行编排)、`ApiAssignmentCache`(ThreadLocal 存放当前 API 配置)、`engine/`(执行引擎工厂 `ApiExecutorEngineFactory`)、`module/`(变量模块 `VarModule`,如 `EnvVarModule` 通过 `Environment` 读取配置)、`extractor/`、`logger/`、`annotation/`(如 `@Module`、`@Comment` 用于 DSL 变量定义)。 - **`service/`**:`ApiAssignmentService`、`DataSourceService`、`AppClientService`、`SystemUserService`、`OverviewService` 等,供 manager 后台调用。 - **`gateway/`**:`FirewallFilterService`(防火墙规则校验)。 - **`executor/`**:`UnifyAlarmOpsService`(统一告警触发)、`DataSourceCleanService`、`AlarmHttpRequestFactory`。 - **`serdes/`**:日期/数字 Jackson 序列化(`DateTimeSerDesFactory`),受 `JSON_TIMEZONE` 控制。 ### 5.4 执行器 `sqlrest-executor` - 启动类:`executor.ExecutorApplication`(`@EnableDiscoveryClient`,`@MapperScan("...persistence.mapper")`,`scanBasePackages` 含 persistence / core.driver / core.servlet / core.exec / core.executor / cache / executor)。 - **Servlet 注册**:`config.ExecutorServletConfig`(`@Configuration`,`@EnableScheduling`)通过 `ServletRegistrationBean` 将 `executor.model.HttpApiServlet` 映射到 `/api/*`,并通过 `FilterRegistrationBean` 注册 `AuthenticationFilter`(同样匹配 `/api/*`,`order=2`)。 - **执行流程**(`ApiExecuteService.execute`):合并参数 → 必填校验 → 缓存判定(SpEL 表达式或 SHA256 生成 key,`CacheFactory.getDistributedCache("response_result")`)→ `DriverLoadService.getVersionDriverFile` 取驱动 → `DataSourceUtils.getHikariDataSource` 建连接池 → `ApiExecutorEngineFactory.getExecutor(engine, dataSource, type).execute(...)` → 包装 `ResultEntity.success`。 - **DSL 引擎**:`engine` 支持 `sql`(关系库)、`http`(HttpClient5 转发下游 RESTful API)、`mongodb` / `elasticsearch`(文档库操作)。Groovy 脚本可在 `exec` 中做复杂后置处理。 - **流控**:`flowStatus=true` 时经 `FlowControlManger.checkFlowControl()`(Sentinel)限流,超限返回 `429`。 ### 5.5 管理器 `sqlrest-manager` - 启动类:`manager.ManagerApplication` 带 `@EnableEurekaServer` + `@EnableDiscoveryClient` + `@EnableScheduling`,托管 Eureka 注册中心与服务本身。 - **后台 API(Controller 清单,前缀 `MANGER_API_V1`)**: | Controller | 路径前缀 | 职责 | |---|---|---| | `AuthenticationController` | `/user` | 登录 `POST /login`、登出 `/logout` | | `DataSourceController` | `/datasource` | 数据源 CRUD、连接测试、库/表/字段元信息探查 | | `ApiAssignmentController` | `/assignment` | API 赋权 CRUD、解析/调试、`deploy`/`retire` 上下线、导入导出 | | `ApiModuleController` / `ApiGroupController` | `/module` `/group` | 模块树 / 分组管理 | | `AppClientController` | `/client` | 调用方 appKey/appSecret 管理 | | `FirewallController` | `/firewall` | 防火墙规则 | | `SystemParamController` / `SystemUserController` | `/param` `/user` | 系统参数 / 用户 | | `McpToolController` / `McpClientController` | `/mcp/tool` `/mcp/client` | MCP 工具/客户端配置 | | `NodeController` / `OverviewController` | `/node` `/overview` | 集群节点 / 仪表盘概览 | | `VersionCommitController` | `/version` | API 版本历史与回滚 | | `UnifyAlarmController` | `/alarm` | 统一告警 | | `AliveHealthController` | `/health` | 健康检查与构建版本 | - **静态前端**:`ManagerWebConfiguration` 将 `classpath:/index.html` 与 `/static/**` 暴露为静态资源,`/` 转发到 `index.html`;Knife4j/Swagger UI 通过 `doc.html` / `swagger-ui.html` 访问。 ### 5.6 缓存 `sqlrest-cache` - 抽象:`DistributedCache` 接口 + `CacheFactory` + `SqlrestCacheConfiguration`。 - 实现:`cache.hazelcast/`(默认,Hazelcast 4.2.8,可经 `hazelcast-eureka-one` 接入 Eureka 集群发现)、`cache.redis/`(Jedis)。 - 缓存名:`response_result`(API 响应)、`variable_value`(DSL 变量)、`token_client`(Token 缓存)。 ### 5.7 MCP 服务 `sqlrest-mcp` - `sqlrest-mcp-core`:自研 MCP(Model Context Protocol)实现,仅依赖 Jackson + HttpClient5,不绑定 Spring。 - `sqlrest-mcp-springmvc`:将 MCP 能力暴露为 Spring MVC 端点(`/mcp`、`/mcp/sse`、`/mcp/message`,常量见 `Constants`)。 - 管理侧:manager 的 `McpToolController` / `McpClientController` 维护 `SQLREST_MCP_TOOL` / `SQLREST_MCP_CLIENT`,将指定 API 赋权注册为可被 LLM 调用的工具。 ### 5.8 前端 `sqlrest-manager-ui` - Vue `2.5.2` + Element-UI `2.15.6`,webpack `3` 构建(`npm run dev` / `npm run build`)。 - 依赖:axios、echarts(仪表盘)、vue-codemirror(SQL 编辑器)、mxgraph-js(流程/拓扑)、vue-json-viewer、vue-i18n(中英文)、vue-router。 - 构建产物(`static/`、`index.html`)由 `sqlrest-dist` 打包进 manager 的 `resources`,最终随 manager 启动作为内置管理界面。 --- ## 6. 系统部署拓扑 ### 6.1 单机全量部署(默认,开发与演示) 三节点同机,端口 `8090/8091/8092`,均向本机 Eureka 注册;共享一个外部元数据库。 ```mermaid flowchart LR subgraph HOST[单机 127.0.0.1] G[sqlrest-gateway :8091] M[sqlrest-manager :8090
Eureka Server + 后台 + UI] E[sqlrest-executor :8092
HttpApiServlet /api/*] DRV[(drivers/ 驱动目录)] end META[(元数据库
MySQL/PostgreSQL
SQLREST_* 表)] BIZ[(业务数据库 / MongoDB / ES)] G -->|lb://sqlrest-manager| M G -->|lb://sqlrest-executor| E M -->|注册中心| M E -.register.-> M M --> META E --> DRV E --> BIZ ``` ### 6.2 多节点分布式部署(生产) manager 独立部署并托管 Eureka;gateway、executor 可多实例横向扩展,通过 `MANAGER_HOST` 指向 manager;executor 实例共享 `drivers/` 驱动与同一元数据库,缓存(Hazelcast/Redis)需跨节点一致。 ```mermaid flowchart TB LB[外部负载均衡 / DNS] subgraph MZ[管理区] M1[sqlrest-manager :8090
Eureka + 后台] end subgraph GZ[网关区] G1[sqlrest-gateway :8091] G2[sqlrest-gateway :8091] end subgraph EZ[执行区] E1[sqlrest-executor :8092] E2[sqlrest-executor :8092] end META[(元数据库 主从)] CACHE[(Hazelcast/Redis 集群)] BIZ[(业务数据库群)] LB --> G1 & G2 G1 & G2 -->|lb://sqlrest-executor| E1 & E2 G1 & G2 -->|lb://sqlrest-manager| M1 E1 & E2 -.register.-> M1 M1 --> META E1 & E2 --> CACHE E1 & E2 --> BIZ ``` > 节点间除业务端口外,还需放行 Eureka 通信端口(默认与 manager 同端口的 `/eureka`)。务必保证 manager 先启动,executor/gateway 后启动。 --- ## 7. 安装与运行步骤 ### 7.1 环境准备 | 依赖 | 版本要求 | 说明 | |---|---|---| | JDK | ≥ 1.8(推荐 1.8) | 编译与运行 | | Maven | ≥ 3.6 | 多模块构建 | | 元数据库 | MySQL 5.7+ 或 PostgreSQL 11+ | 存储 SQLREST 自身元数据 | | (可选)Redis | 任意稳定版 | 若用 Redis 替代 Hazelcast 缓存 | > Maven 仓库默认在海外,国内可切换阿里云镜像(`settings.xml` 中配置 `maven.aliyun.com`)。 ### 7.2 源码构建(可复制执行) **Windows:** ```bat cd sqlrest build.cmd ``` **Linux / macOS:** ```sh git clone https://gitee.com/inrgihc/sqlrest.git cd sqlrest sh ./build.sh ``` **Docker 内构建(产出镜像用):** ```sh sh ./docker-maven-build.sh ``` 构建完成后,在 `target/` 下生成 `sqlrest-release-1.9.0.tar.gz`(由 `sqlrest-dist` 的 maven-assembly 产出)。其内部结构: ``` sqlrest-release/ ├── bin/ # sqlrestctl.sh (Linux) + *_startup.cmd (Windows) ├── conf/ │ ├── config.ini # 全局配置(端口、元数据库、加密开关) │ ├── manager/ # application.yaml + application-mysql/postgres.yaml + logback │ ├── gateway/ # application.yaml ... │ └── executor/ # application.yaml ... ├── lib/ # common / webmvc / manager / executor / gateway / webflux 分层 jar ├── drivers/ # 各数据库驱动 jar ├── logs/ # 运行日志 └── run/ # pid 与运行日志(启动后生成) ``` ### 7.3 部署与配置 1. 将 `sqlrest-release-1.9.0.tar.gz` 拷贝到目标机(需装 JRE),解压: ```sh tar -zxf sqlrest-release-1.9.0.tar.gz -C /opt/sqlrest cd /opt/sqlrest ``` 2. 准备元数据库(MySQL 示例,库名 `sqlrest`),并修改 `conf/config.ini`(见 [第 8 节](#8-配置说明))。 3. 多节点部署:将解压目录分发到其他主机,统一 `MANAGER_HOST` 指向 manager 节点 IP。 ### 7.4 启动服务(顺序:manager → executor → gateway) **Linux / macOS:** ```sh sh bin/sqlrestctl.sh start manager sh bin/sqlrestctl.sh start executor sh bin/sqlrestctl.sh start gateway # 查看状态 sh bin/sqlrestctl.sh status manager sh bin/sqlrestctl.sh status executor sh bin/sqlrestctl.sh status gateway # 停止 sh bin/sqlrestctl.sh stop manager ``` **Windows:** 依次双击 `bin/manager_startup.cmd`、`bin/executor_startup.cmd`、`bin/gateway_startup.cmd`。 ### 7.5 访问与验证 - 管理界面:`http://:8090`(默认账号 `admin` / 密码 `123456`)。 - 网关地址:`http://:8091`。 - 后台 API 文档(Knife4j):`http://:8091/sqlrest/manager/doc.html`。 - 动态 API 文档:`http://:8091/apidoc/knife4j/swagger.json`。 - Eureka 注册中心(若开启 dashboard):`http://:8090/dashboard`。 ### 7.6 本地快速验证(不走网关,直连 executor) ```sh # 1) 在管理界面创建数据源并发布一个 open 的 API 赋权(路径 /demo/hello) # 2) 直接调用 executor(跳过网关) curl -X POST "http://127.0.0.1:8092/api/demo/hello" -H "Content-Type: application/json" -d '{}' # 3) 非 open 接口:先用 appKey/appSecret 换 token curl -X POST "http://127.0.0.1:8092/token/generate" \ -H "Content-Type: application/json" \ -d '{"appKey":"","appSecret":""}' # 再带 Authorization: Bearer 调用 /api/** ``` --- ## 8. 配置说明 ### 8.1 配置加载机制(关键) SQLREST 的配置采用 **`config.ini` → 环境变量 → `application.yml` 占位符** 三级注入: 1. 启动脚本(`bin/sqlrestctl.sh` 或 `bin/*_startup.cmd`)读取 `conf/config.ini`,将其中 `KEY=VALUE` 导出为**进程环境变量**(如 `MANAGER_HOST`、`EXECUTOR_PORT`、`MYSQLDB_*`、`DB_TYPE`)。 2. 各节点的 `conf/{node}/application.yaml` 通过 `${VAR}` 引用这些环境变量(例如 `server.port: ${EXECUTOR_PORT}`、`eureka.client.service-url.defaultZone: http://${MANAGER_HOST}:${MANAGER_PORT}/eureka/`)。 3. `spring.profiles.include: ${DB_TYPE}` 选择 `application-mysql.yaml` 或 `application-postgres.yaml`,填充元数据库连接信息。 > 因此**修改 `config.ini` 后需重启对应节点**才能生效;`application.yaml` 中的缓存、日志等也可直接编辑。 ### 8.2 `conf/config.ini` 全局变量 | 变量 | 默认值 | 说明 | |---|---|---| | `MANAGER_HOST` | `127.0.0.1` | manager 节点地址(跨机部署必改) | | `MANAGER_PORT` | `8090` | manager 端口 | | `EXECUTOR_PORT` | `8092` | executor 端口 | | `GATEWAY_PORT` | `8091` | gateway 端口 | | `DB_TYPE` | `mysql` | 元数据库类型:`mysql` 或 `postgres` | | `MYSQLDB_HOST` / `_PORT` / `_NAME` / `_USERNAME` / `_PASSWORD` | `192.168.31.57` / `3306` / `sqlrest` / `root` / `123456` | MySQL 元数据连接(URL 含 `createDatabaseIfNotExist=true`,库可自动创建) | | `PGDB_HOST` / `_PORT` / `_NAME` / `_USERNAME` / `_PASSWORD` | 同上结构 | PostgreSQL 元数据连接 | | `JSON_TIMEZONE` | `Asia/Shanghai` | JSON 序列化时区 | | `SQLREST_DS_ENCRYPT` | `false` | 是否对数据源账号密码加密落盘(`datasource.encrypt`) | | `SQLREST_MANAGER_URL` / `SQLREST_GATEWAY_URL` | 空 | 外部可访问的 manager/gateway 地址(反向代理/域名场景) | > 脚本还固定导出 `APP_DRIVERS_PATH=$APP_HOME/drivers`,供 `DriverLoadService` 扫描驱动。 ### 8.3 `conf/{node}/application.yaml` 关键项 **缓存(manager / gateway / executor 三者必须一致):** ```yaml sqlrest: cache: hazelcast: enabled: true # 默认启用 Hazelcast redis: enabled: false # 改为 true 启用 Redis host: 127.0.0.1 port: 6379 username: default password: 123456 database: 0 sentinel: # 哨兵模式(非哨兵模式删除该节点) master: mymaster nodes: 127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381 ``` **Eureka 注册(各节点):** ```yaml eureka: instance: prefer-ip-address: true lease-renewal-interval-in-seconds: 5 lease-expiration-duration-in-seconds: 10 client: service-url: defaultZone: http://${MANAGER_HOST}:${MANAGER_PORT}/eureka/ ``` **executor 额外开关:** ```yaml sqlrest: executor: print-sql-log: false # 是否打印执行 SQL datasource: encrypt: ${SQLREST_DS_ENCRYPT:false} datasource: driver: base-path: ${APP_DRIVERS_PATH} # 驱动目录 ``` **gateway 路由(节选):** ```yaml spring: cloud: gateway: routes: - { id: api_executor_route, uri: lb://sqlrest-executor, predicates: [Path=/api/**] } - { id: manager_route, uri: lb://sqlrest-manager, predicates: [Path=/sqlrest/manager/**] } globalcors: cors-configurations: '[/**]': { allowed-origins: '*', allowed-methods: '*', allowed-headers: '*' } ``` ### 8.4 Liquibase 元数据表 manager 启动时由 Liquibase 自动建表(无需手工执行 SQL)。变更日志表: - `SQLREST_DB_CHANGE_LOG_RECORD`(变更记录) - `SQLREST_DB_CHANGE_LOG_LOCK`(变更锁) 业务表均以 `SQLREST_` 前缀(见 [5.2](#52-元数据持久化-sqlrest-persistence))。 --- ## 9. 常见问题排查 **Q1. executor / gateway 无法向 manager 注册(Eureka 报连接失败)。** - 确认各节点 `config.ini` 的 `MANAGER_HOST` / `MANAGER_PORT` 指向 manager 且**manager 已先启动**(Eureka 需服务端就绪后客户端才能注册)。 - 确认 manager 端口未被占用、防火墙放行 `/eureka` 路径。 - 查看 `run/run_{module}.log` 中 `defaultZone` 解析值是否正确。 **Q2. 调用 `/api/**` 返回 404 / "not found"。** - API 赋权未部署上线。在管理界面点击「部署」,或调用 `PUT /sqlrest/manager/api/v1/assignment/deploy/{id}`,使 executor 能在 `SQLREST_API_ONLINE` 中找到该配置。 - 确认路径与方法(GET/POST)与赋权定义一致(executor 按 `method + path` 唯一匹配)。 **Q3. 已上线的 API 返回 401 / 403。** - 赋权非 `open`:需在 manager 的 `/client` 注册 `appKey/appSecret`,调用 executor `POST /token/generate` 换取 `AccessToken`,再带 `Authorization: Bearer `。 - 403 表示 Token 合法但无对应分组(`ClientGroup`)授权,检查 `verifyAuthGroup`。 **Q4. 缓存不一致 / 数据陈旧。** - Hazelcast 与 Redis 不能混用,且 `enabled`、`host`、`password`、`database` 在 manager/gateway/executor 三者 `application.yaml` 中必须完全一致。 - 多实例部署时若用 Hazelcast,建议开启 `hazelcast-eureka-one` 形成集群;或统一切到 Redis。 **Q5. 元数据库连不上 / 表不存在。** - 确认 `DB_TYPE` 与 `MYSQLDB_*` / `PGDB_*` 配置匹配,且数据库用户有建库建表权限(MySQL URL 含 `createDatabaseIfNotExist=true` 可自动建库)。 - 检查 Liquibase 是否正常执行(`SQLREST_DB_CHANGE_LOG_RECORD` 是否生成)。 **Q6. 新增数据库类型驱动不生效。** - 驱动 jar 须放入 `drivers///` 三层目录;`dbType` 须被 `ProductTypeEnum` 识别(`DriverLoadService` 在 `ApplicationReadyEvent` 时扫描,仅加载已识别类型)。 **Q7. 单机端口冲突。** - 默认 `8090/8091/8092` 需空闲;冲突时统一在 `config.ini` 修改三端口后重启。 **Q8. 如何将 API 暴露给 LLM(MCP)?** - 在管理界面 `McpToolController`(`/mcp/tool`)把指定赋权注册为 MCP 工具;LLM 客户端连接 `http://:8091/mcp`(或 `/mcp/sse`),由 `sqlrest-mcp-springmvc` 转发。 --- ## 10. 贡献指南 欢迎开发者参与共建,方向包括但不限于: - 改善前端 UI/UX(`sqlrest-manager-ui`,Vue 2 + Element-UI)。 - 修复缺陷、优化性能(尤其是 `sqlrest-core` 执行引擎与缓存)。 - 新增数据库驱动或 DSL 类型(在 `drivers/` 与 `ProductTypeEnum` 中扩展)。 - 完善文档与测试用例。 **开发约定(来自项目规范):** - 命名使用有意义的描述性名称,遵循 Java / Vue 各自规范,避免无意义缩写。 - 用户输入与外部数据一律校验(白名单优先);SQL 一律参数化以防止注入(本项目已用预编译参数绑定)。 - 敏感信息(数据源密码)通过 `SQLREST_DS_ENCRYPT` 加密落盘,日志中不得输出明文凭证。 - 注释解释「为什么」而非「做什么」;公共 API 提供清晰文档。 - 重构遵循「小步、可测试、随时可运行」原则。 **提交流程:** 1. Fork 仓库并基于 `master` 创建特性分支(`git checkout -b feature/xxx`)。 2. 本地执行 `sh ./build.sh` 确保多模块构建通过。 3. 如涉及配置变更,同步更新本文档与相关 `config.ini` / `application.yaml`。 4. 提交 Pull Request,描述变更动机与验证方式。 详细规范见:[贡献指南 CONTRIBUTE.md](CONTRIBUTE.md) --- ## 附录:相关资源 - 用户使用手册: - 社区:Dromara - 推荐项目:[数据库迁移同步工具 dbswitch](https://github.com/inrgihc/dbswitch) 如遇问题或发现缺陷,请在 Issues 反馈;若本工具对您有帮助,欢迎 Star 支持。