# dynamic-api-service
**Repository Path**: nicky1224/dynamic-api-service
## Basic Information
- **Project Name**: dynamic-api-service
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-02-03
- **Last Updated**: 2026-02-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 对外接口服务平台
基于 SpringBoot 3 + MySQL + Redis + SaToken + Freemarker 的动态API服务运行平台。
## 项目结构
```
dynamic-api-service/
├── dynamic-api-common/ # 公共模块
├── dynamic-api-infrastructure/ # 基础设施模块
├── dynamic-api-domain/ # 领域模块
├── dynamic-api-runtime/ # 运行时模块
├── dynamic-api-admin/ # Admin管理模块
├── dynamic-api-admin-web/ # Admin前端(Vue 3)
└── src/main/resources/sql/init.sql # 数据库初始化脚本
```
## 技术栈
- **后端**: SpringBoot 3.2.0, MyBatis Plus, SaToken, Freemarker
- **数据库**: MySQL 8.0+
- **缓存**: Redis
- **前端**: Vue 3, Element Plus, Vite
## 核心功能
### 1. 动态数据源管理
- 支持多数据源配置
- 运行时动态创建 JdbcTemplate
- 数据源连接测试
### 2. SQL模板引擎
- 基于 Freemarker 的动态 SQL
- 支持 `<#if param??>` 条件判断
- 支持分页查询
### 3. 动态接口
- 统一返回结构 ResponseEntity
- 支持多种结果类型(LIST/MAP/PAGE)
- 自动处理分页参数
### 4. 管理后台
- 数据源管理
- 服务管理
- 接口管理
- SQL模板管理
- 接口调试
## 快速开始
### 1. 环境要求
- JDK 17+
- Maven 3.6+
- MySQL 8.0+
- Redis 5.0+
- Node.js 16+
### 2. 数据库初始化
```sql
-- 执行初始化脚本
source src/main/resources/sql/init.sql
```
### 3. 配置文件
修改 `dynamic-api-runtime/src/main/resources/application.yml`:
```yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/dynamic_api
username: root
password: your_password
data:
redis:
host: localhost
port: 6379
```
### 4. 启动后端
```bash
# 进入项目目录
cd dynamic-api-service
# 编译打包
mvn clean package -DskipTests
# 启动运行时模块
cd dynamic-api-runtime/target
java -jar dynamic-api-runtime-1.0.0.jar
# 或启动Admin模块
cd dynamic-api-admin/target
java -jar dynamic-api-admin-1.0.0.jar
```
### 5. 启动前端
```bash
cd dynamic-api-admin-web
# 安装依赖
npm install
# 启动开发服务器
npm run dev
```
访问 http://localhost:3000,默认账号:
- 用户名: admin
- 密码: admin123
## 使用示例
### 1. 创建数据源
在管理后台"数据源管理"中添加数据源配置。
### 2. 创建服务
在"服务管理"中创建服务并绑定数据源。
### 3. 创建SQL模板
例如:
```sql
SELECT * FROM da_datasource
WHERE 1=1
<#if status??>AND status = ${status}#if>
<#if dsCode??>AND ds_code LIKE '%${dsCode}%'#if>
```
### 4. 创建接口
配置接口路径、HTTP方法,绑定SQL模板。
### 5. 调用接口
```bash
curl http://localhost:8080/api/test/queryDatasource?status=1
```
## 接口返回格式
```json
{
"code": 200,
"message": "成功",
"data": [
{"id": 1, "dsCode": "default_ds", ...}
]
}
```
分页返回:
```json
{
"code": 200,
"message": "成功",
"data": {
"pageNum": 1,
"pageSize": 10,
"total": 100,
"pages": 10,
"records": [...]
}
}
```
## 开发说明
### 添加新的数据源类型
1. 在 `DataSourceTypeEnum` 中添加新类型
2. 配置驱动类名和URL模板
3. 更新数据库 `da_datasource` 表的 `ds_type` 字段
### 扩展SQL模板功能
在 `FreemarkerSqlProcessor` 中添加自定义处理逻辑。
## License
MIT License
## 更新日志
### 2026-02-05 - SaToken Redis 集成与 URL 格式更新
#### 主要变更
1. **SaToken 跨服务 Redis 集成**
- Admin 服务(8081)和 Runtime 服务(8080)现在通过 Redis 共享认证 token
- 添加 `sa-token-redis-jackson` 依赖实现分布式 token 存储
- Token 存储在 Redis 中,key 前缀为 `Authorization:`
2. **统一 URL 格式**
- 所有 API 路径从 `/api/{serviceCode}/{path}` 改为 `/api/data-service/api-center/dataApi/{apiCode}`
- Runtime 服务支持按 `api_code` 查询 API
- 数据库已更新所有现有 API 的路径格式
3. **认证鉴权增强**
- 所有 Admin 和 Runtime 接口都需要 token 认证
- 请求时需在 Header 中携带 `Authorization: {token}`
- 未携带 token 的请求将返回 "暂无权限访问"
- 自动放行 OPTIONS 请求以支持 CORS 跨域
#### 技术实现
**依赖更新:**
```xml
cn.dev33
sa-token-redis-jackson
1.37.0
```
**配置更新:**
```yaml
# application.yml (Admin & Runtime)
sa-token:
token-name: Authorization
is-share: true # 启用跨服务 token 共享
active-timeout: -1 # 修复配置项名称(原 activity-timeout)
```
**代码更新:**
- `InfraApiMapper.java`: 新增 `getByCode()` 方法支持按 api_code 查询
- `SqlExecutor.java`: 增加按 api_code 查询 API 的逻辑
- `SaTokenConfig.java`: 配置拦截器放行 OPTIONS 请求
- `runtime-request.js`: 前端新增专门调用 Runtime API 的 axios 实例
#### 完整认证流程
1. **登录获取 token**
```bash
curl -X POST http://localhost:8081/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
```
响应:
```json
{
"code": 200,
"msg": "成功",
"data": "2cffebea-e22a-40b6-9622-5095f359476c"
}
```
2. **Token 存储到 Redis**
```
Authorization:login:session:1
Authorization:login:token:2cffebea-e22a-40b6-9622-5095f359476c
```
3. **调用 Runtime API**
```bash
curl -X GET "http://localhost:8080/api/data-service/api-center/dataApi/DKJJQTFXLB" \
-H "Authorization: 2cffebea-e22a-40b6-9622-5095f359476c"
```
4. **Runtime 从 Redis 验证 token 并执行 API**
#### 前端调试
前端调试界面已更新,现在:
- 显示新的 URL 格式:`http://localhost:8080/api/data-service/api-center/dataApi/{apiCode}`
- 自动在请求头中携带 token
- 支持新建接口的实时调试
#### 服务端口
- Admin 服务: http://localhost:8081
- Runtime 服务: http://localhost:8080
- 前端界面: http://localhost:3000
- Redis: localhost:6379
#### 注意事项
- 确保 Redis 服务已启动,否则 token 无法跨服务共享
- 所有 API 调用必须携带有效的 token
- 新建接口后会在数据库中自动使用新的 URL 格式
- 旧格式 URL 仍然向后兼容
---
## 开发命令参考
### 一键停止所有服务
```bash
# 停止后端服务
pkill -f "dynamic-api-(runtime|admin).*\.jar"
# 停止前端服务
pkill -f "vite\|npm.*dev"
# 或者一键停止所有
pkill -f "dynamic-api-(runtime|admin).*\.jar" && pkill -f "vite\|npm.*dev"
```
### 后端服务管理
#### 1. 清理并编译
```bash
# 进入项目根目录
cd /path/to/dynamic-api-service
# 清理并编译(跳过测试)
mvn clean install -DskipTests
# 或者编译并运行测试
mvn clean install
```
#### 2. 启动后端服务
**方式一:直接启动(前台运行)**
```bash
# 启动 Runtime 服务(端口 8080)
java -jar dynamic-api-runtime/target/dynamic-api-runtime-1.0.0.jar
# 启动 Admin 服务(端口 8081)
java -jar dynamic-api-admin/target/dynamic-api-admin-1.0.0.jar
```
**方式二:后台启动(推荐)**
```bash
# 启动 Runtime 服务(后台运行,日志输出到 /tmp/runtime.log)
nohup java -jar dynamic-api-runtime/target/dynamic-api-runtime-1.0.0.jar > /tmp/runtime.log 2>&1 &
# 启动 Admin 服务(后台运行,日志输出到 /tmp/admin.log)
nohup java -jar dynamic-api-admin/target/dynamic-api-admin-1.0.0.jar > /tmp/admin.log 2>&1 &
```
**方式三:一键启动所有后端服务**
```bash
nohup java -jar dynamic-api-runtime/target/dynamic-api-runtime-1.0.0.jar > /tmp/runtime.log 2>&1 & \
nohup java -jar dynamic-api-admin/target/dynamic-api-admin-1.0.0.jar > /tmp/admin.log 2>&1 & \
sleep 5 && echo "后端服务已启动"
```
#### 3. 查看后端日志
```bash
# 实时查看 Runtime 服务日志
tail -f /tmp/runtime.log
# 实时查看 Admin 服务日志
tail -f /tmp/admin.log
# 查看最近 100 行日志
tail -100 /tmp/runtime.log
```
### 前端服务管理
#### 1. 安装依赖(首次运行)
```bash
cd dynamic-api-admin-web
npm install
```
#### 2. 启动前端服务
**方式一:直接启动(前台运行)**
```bash
cd dynamic-api-admin-web
npm run dev
```
**方式二:后台启动(推荐)**
```bash
cd dynamic-api-admin-web
nohup npm run dev > /tmp/frontend.log 2>&1 &
```
#### 3. 查看前端日志
```bash
# 实时查看前端日志
tail -f /tmp/frontend.log
# 查看最近 50 行日志
tail -50 /tmp/frontend.log
```
### 完整开发流程
#### 场景一:首次启动所有服务
```bash
# 1. 进入项目根目录
cd /path/to/dynamic-api-service
# 2. 清理并编译后端
mvn clean install -DskipTests
# 3. 安装前端依赖(首次运行)
cd dynamic-api-admin-web && npm install && cd ..
# 4. 启动后端服务
nohup java -jar dynamic-api-runtime/target/dynamic-api-runtime-1.0.0.jar > /tmp/runtime.log 2>&1 & \
nohup java -jar dynamic-api-admin/target/dynamic-api-admin-1.0.0.jar > /tmp/admin.log 2>&1 & \
sleep 5
# 5. 启动前端服务
cd dynamic-api-admin-web
nohup npm run dev > /tmp/frontend.log 2>&1 &
```
#### 场景二:代码修改后重新编译启动
```bash
# 1. 停止所有服务
pkill -f "dynamic-api-(runtime|admin).*\.jar" && pkill -f "vite\|npm.*dev"
sleep 2
# 2. 重新编译
mvn clean install -DskipTests
# 3. 重新启动所有服务
nohup java -jar dynamic-api-runtime/target/dynamic-api-runtime-1.0.0.jar > /tmp/runtime.log 2>&1 & \
nohup java -jar dynamic-api-admin/target/dynamic-api-admin-1.0.0.jar > /tmp/admin.log 2>&1 & \
cd dynamic-api-admin-web && \
nohup npm run dev > /tmp/frontend.log 2>&1 & \
sleep 5 && echo "所有服务已重启"
```
#### 场景三:仅前端代码修改
```bash
# 前端使用热重载,修改会自动生效
# 如需重启前端服务:
pkill -f "vite\|npm.*dev"
cd dynamic-api-admin-web
nohup npm run dev > /tmp/frontend.log 2>&1 &
```
### 服务验证
#### 检查服务状态
```bash
# 检查后端服务是否运行
ps aux | grep "dynamic-api.*jar" | grep -v grep
# 检查前端服务是否运行
ps aux | grep "vite\|npm.*dev" | grep -v grep
# 统计运行的服务数量
ps aux | grep -E "dynamic-api.*jar|npm.*dev|vite" | grep -v grep | wc -l
```
#### 测试服务接口
```bash
# 测试 Admin 登录接口
curl -X POST http://localhost:8081/admin/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"admin123"}'
# 预期响应
# {"code":200,"msg":"成功","data":"token值","success":true}
# 检查 Redis 中的 token
redis-cli KEYS "Authorization:*"
```
### 故障排查
#### 1. 端口被占用
```bash
# 查看端口占用
lsof -i :8080 # Runtime 服务
lsof -i :8081 # Admin 服务
lsof -i :3000 # 前端服务
# 杀死占用端口的进程
kill -9
```
#### 2. 服务启动失败
```bash
# 查看详细错误日志
tail -100 /tmp/runtime.log | grep -i "error\|exception"
tail -100 /tmp/admin.log | grep -i "error\|exception"
tail -100 /tmp/frontend.log | grep -i "error"
```
#### 3. Redis 连接失败
```bash
# 检查 Redis 是否运行
redis-cli ping
# 预期响应
# PONG
# 启动 Redis(如果未运行)
redis-server
```
#### 4. 数据库连接失败
```bash
# 检查 MySQL 是否运行
mysql -uroot -p -e "SELECT 1"
# 测试数据库连接
mysql -uroot -p12345678 -e "USE dynamic_api; SHOW TABLES;"
```
### 快速参考
| 服务 | 端口 | 日志文件 | 启动命令 |
|------|------|---------|---------|
| Runtime | 8080 | /tmp/runtime.log | `java -jar dynamic-api-runtime-1.0.0.jar` |
| Admin | 8081 | /tmp/admin.log | `java -jar dynamic-api-admin-1.0.0.jar` |
| 前端 | 3000 | /tmp/frontend.log | `npm run dev` |
| Redis | 6379 | - | `redis-server` |
| MySQL | 3306 | - | `systemctl start mysql` |
### 访问地址
- **前端管理界面**: http://localhost:3000
- **Admin API**: http://localhost:8081
- **Runtime API**: http://localhost:8080
- **Swagger 文档**: http://localhost:8081/swagger-ui.html
**默认登录账号:**
- 用户名: `admin`
- 密码: `admin123`
---
## UI/UX 优化 - 2026-02-06
### 前端列表显示全面优化
#### 主要改进
**1. 视觉层次优化**
- 编码/名称使用蓝色加粗显示,突出主键信息
- 类型/方法使用彩色标签,快速识别分类
- 时间信息使用灰色小字体,弱化次要信息
- 移除无意义的ID列,节省表格空间
**2. 表格布局优化**
- 固定列宽改为自适应列宽(min-width)
- 长文本自动省略 + 悬浮提示(show-overflow-tooltip)
- 操作列固定右侧(fixed="right")
- 添加创建时间列,便于数据追溯
**3. 交互体验提升**
- 添加加载状态(loading 动画)
- 空状态友好提示(暂无数据/加载失败)
- 操作按钮改为链接式,添加图标(✏️编辑、🗑️删除、🔌测试)
- 分页组件右对齐,开启背景模式
**4. 状态标签色彩方案**
**HTTP 方法标签:**
- GET - 绿色(查询操作)
- POST - 蓝色(新增操作)
- PUT - 橙色(更新操作)
- DELETE - 红色(删除操作)
**返回类型标签:**
- LIST - 蓝色(列表)
- MAP - 绿色(单对象)
- PAGE - 橙色(分页)
**数据源类型标签:**
- MySQL - 蓝色
- PostgreSQL - 绿色
**状态标签:**
- 启用 - 绿色(深色效果)
- 禁用 - 灰色(深色效果)
**5. 信息聚合显示**
**数据源:**
```
连接地址: host:port/database(合并显示)
```
**接口管理:**
```
API路径: /api/data-service/api-center/dataApi/{code}(等宽字体)
服务: 服务名称(黄色标签)
SQL模板: 模板名称(绿色标签)
```
**SQL模板:**
```
SQL预览: {SQL内容}(等宽字体,预览前200字符)
```
**6. 日期时间格式化**
统一格式:`YYYY-MM-DD HH:mm:ss`
示例:
```
2026-02-06 10:30:45
```
**7. 响应式设计**
- 表格列宽自适应屏幕尺寸
- 搜索表单自动换行
- 移动端友好的布局
#### 技术实现
**日期格式化函数:**
```javascript
const formatDateTime = (dateTime) => {
if (!dateTime) return '-'
const date = new Date(dateTime)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
const seconds = String(date.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
```
**关联数据获取:**
```javascript
const getServiceName = (serviceId) => {
if (!serviceId) return ''
const service = serviceList.value.find(s => s.id === serviceId)
return service ? service.serviceName : ''
}
```
**加载状态管理:**
```javascript
const loading = ref(false)
const emptyText = ref('暂无数据')
const loadData = async () => {
loading.value = true
try {
const res = await getList(params)
tableData.value = res.records
pagination.total = res.total
} catch (error) {
emptyText.value = '加载失败'
} finally {
loading.value = false
}
}
```
#### CSS 样式优化
**表格样式:**
```css
:deep(.el-table) {
font-size: 13px;
}
:deep(.el-table th) {
background-color: #fafafa;
font-weight: 600;
color: #333;
}
:deep(.el-table .el-table__empty-block) {
padding: 40px 0;
}
```
**分页样式:**
```css
:deep(.el-pagination) {
display: flex;
padding: 0;
}
:deep(.el-pagination.is-background .el-pager li) {
border-radius: 4px;
}
```
**标签样式:**
```css
:deep(.el-tag--small) {
padding: 2px 8px;
height: 20px;
line-height: 16px;
}
```
#### 优化效果对比
| 项目 | 优化前 | 优化后 |
|------|--------|--------|
| 列宽 | 固定宽度,浪费空间 | 自适应宽度,充分利用 |
| 主键列 | ID(无意义) | 编码/名称(蓝色加粗) |
| 状态显示 | 普通标签 | 彩色标签 + 深色效果 |
| 操作按钮 | 实体按钮(占用空间) | 链接按钮 + 图标(紧凑) |
| 加载反馈 | 无 | Loading 动画 |
| 空状态 | 默认提示 | 友好的文字提示 |
| 时间显示 | 无 | YYYY-MM-DD HH:mm:ss |
| 长文本 | 换行显示 | 省略 + Tooltip |
#### 优化的页面
- ✅ 数据源管理
- ✅ 服务管理
- ✅ SQL模板管理
- ✅ 接口管理
#### 浏览器兼容性
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
#### 注意事项
- 前端使用 Vite 热重载,修改自动生效
- 日期时间字段需要在后端返回时包含 createTime
- 关联数据(服务、数据源、模板)需要在 loadOptions 中预先加载
- 等宽字体用于显示代码类信息(API路径、SQL内容)
---