【RuoYi-SpringBoot3-Pro】:Magic API 低代码开发
本文详细介绍 RuoYi-SpringBoot3-Pro 框架中集成的 Magic API 低代码开发平台,帮助开发者快速构建 REST API 接口。
GitHub:
https://github.com/undsky/RuoYi-SpringBoot3-Pro
一、什么是 Magic API?
Magic API 是一个基于 Java 的接口快速开发框架,通过 Web 界面编写脚本即可完成接口开发,无需定义 Controller、Service、Mapper 等传统分层代码。
1.1 核心优势
| 特性 | 说明 |
|---|---|
| 可视化开发 | 通过 Web 界面编写接口,所见即所得 |
| 即时生效 | 接口修改后无需重启,立即生效 |
| 脚本语言 | 基于 Java 语法的脚本语言,学习成本低 |
| 数据库操作 | 内置强大的数据库操作 API |
| 多数据源 | 支持动态切换多个数据源 |
| 参数校验 | 内置参数校验功能 |
| 接口文档 | 自动生成接口文档 |
| 版本控制 | 支持接口历史记录和回滚 |
1.2 适用场景
- 快速原型开发
- 简单 CRUD 接口
- 数据查询报表
- 临时接口需求
- 低代码平台集成
二、项目集成
2.1 Maven 依赖
RuoYi-SpringBoot3-Pro 已集成 Magic API 2.2.2 版本:
<!-- Magic API 核心依赖 -->
<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- Magic API Redis 插件 -->
<dependency>
<groupId>org.ssssssss</groupId>
<artifactId>magic-api-plugin-redis</artifactId>
<version>2.2.2</version>
</dependency>
2.2 配置文件
在 application.yml 中配置 Magic API:
# Magic API 配置
# 官方文档:https://www.ssssssss.org/magic-api/pages/config/spring-boot/
magic-api:
# Web 编辑器访问路径(生产环境建议设为 null 禁用)
web: /magic/web
# 编辑器配置文件
editor-config: classpath:./magic-editor-config.js
# 接口存储方式
resource:
type: database # 存储类型:database(数据库)/ file(文件)
tableName: magic_api_file # 存储表名
# 接口访问前缀
prefix: /magic/api
# 编辑器登录认证
security:
username: jyx # 登录用户名
password: jyx_692483 # 登录密码
# 历史记录备份
backup:
enable: true # 是否启用备份
max-history: -1 # 最大历史记录数(-1 表示不限制)
table-name: magic_backup_record # 备份表名
# 响应结果格式
response: |-
{
code: code,
msg: message,
data,
}
2.3 编辑器主题配置
magic-editor-config.js 文件配置编辑器主题:
var MAGIC_EDITOR_CONFIG = {
theme: 'dark', // 主题:dark(暗色)/ light(亮色)
}
2.4 安全配置
Magic API 接口默认放行,在 SecurityConfig.java 中配置:
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeHttpRequests(auth -> auth
// Magic API 接口放行
.requestMatchers("/magic/**").permitAll()
.anyRequest().authenticated()
);
return httpSecurity.build();
}
三、访问编辑器
3.1 访问地址
启动项目后,访问 Magic API 编辑器:
http://localhost:8087/magic/web
3.2 登录认证
使用配置文件中设置的账号密码登录:
- 用户名:
jyx - 密码:
jyx_692483
3.3 编辑器界面
┌─────────────────────────────────────────────────────────────┐
│ Magic API Editor [用户] │
├─────────────┬───────────────────────────────────────────────┤
│ │ │
│ 接口列表 │ 脚本编辑区 │
│ │ │
│ 📁 分组1 │ // 编写接口脚本 │
│ └─ 接口1 │ var list = db.select(""" │
│ └─ 接口2 │ SELECT * FROM sys_user │
│ 📁 分组2 │ """) │
│ └─ 接口3 │ return list │
│ │ │
├─────────────┼───────────────────────────────────────────────┤
│ 接口配置 │ 执行结果 │
│ 请求方式 │ [ │
│ 请求路径 │ {"userId": 1, "userName": "admin"}, │
│ 请求参数 │ {"userId": 2, "userName": "test"} │
│ │ ] │
└─────────────┴───────────────────────────────────────────────┘
四、接口开发
4.1 创建第一个接口
- 点击左侧「+」创建分组
- 在分组下创建接口
- 配置请求方式和路径
- 编写脚本代码
- 点击「执行」测试
- 点击「保存」发布
4.2 基础语法
Magic API 使用类 Java 语法的脚本语言:
// 变量定义
var name = "张三"
var age = 18
// 条件判断
if (age >= 18) {
return "成年人"
} else {
return "未成年人"
}
// 循环
var list = [1, 2, 3, 4, 5]
for (item in list) {
print(item)
}
// 函数定义
var add = (a, b) => a + b
return add(1, 2)
4.3 获取请求参数
// 获取 Query 参数:/api/user?name=张三&age=18
var name = name // 直接使用参数名
var age = age
// 获取 Path 参数:/api/user/{id}
var userId = path.id
// 获取 Body 参数(JSON)
var user = body
var userName = body.userName
// 获取 Header
var token = header.Authorization
// 获取完整请求对象
var request = request
4.4 数据库操作
Magic API 内置强大的数据库操作 API:
// 查询列表
var list = db.select("""
SELECT * FROM sys_user WHERE status = '0'
""")
// 查询单条
var user = db.selectOne("""
SELECT * FROM sys_user WHERE user_id = #{userId}
""")
// 带参数查询
var users = db.select("""
SELECT * FROM sys_user
WHERE dept_id = #{deptId}
AND user_name LIKE CONCAT('%', #{keyword}, '%')
""")
// 分页查询
var page = db.page("""
SELECT * FROM sys_user WHERE status = '0'
""")
// 插入数据
var result = db.insert("""
INSERT INTO sys_user (user_name, nick_name, email)
VALUES (#{userName}, #{nickName}, #{email})
""")
// 更新数据
var result = db.update("""
UPDATE sys_user SET nick_name = #{nickName} WHERE user_id = #{userId}
""")
// 删除数据
var result = db.delete("""
DELETE FROM sys_user WHERE user_id = #{userId}
""")
4.5 链式查询
// 使用链式 API 构建查询
var list = db.table('sys_user')
.where()
.eq('status', '0')
.like('user_name', keyword)
.orderBy('create_time desc')
.page(pageNum, pageSize)
.select()
// 插入
db.table('sys_user').insert({
userName: '张三',
nickName: '小张',
email: 'zhangsan@example.com'
})
// 更新
db.table('sys_user')
.where()
.eq('user_id', 1)
.update({
nickName: '新昵称'
})
// 删除
db.table('sys_user')
.where()
.eq('user_id', 1)
.delete()
4.6 多数据源
// 切换数据源
var list = db.slave.select("""
SELECT * FROM other_table
""")
// 或使用 datasource 指定
var list = db.datasource('slave').select("""
SELECT * FROM other_table
""")
五、接口鉴权
5.1 鉴权拦截器
RuoYi-SpringBoot3-Pro 实现了 Magic API 的请求拦截器,支持登录验证和权限校验:
@Component
public class MagicApiRequestInterceptor implements RequestInterceptor {
@Override
public Object preHandle(ApiInfo info, MagicScriptContext context,
MagicHttpServletRequest request, MagicHttpServletResponse response) {
// 获取接口配置的选项
boolean needLogin = StringUtils.equals("true", info.getOptionValue(Options.REQUIRE_LOGIN));
String role = info.getOptionValue(Options.ROLE);
String permission = info.getOptionValue(Options.PERMISSION);
// 需要角色或权限时,自动要求登录
if (StringUtils.isNotBlank(role) || StringUtils.isNotBlank(permission)) {
needLogin = true;
}
// 登录校验
if (needLogin) {
try {
SecurityUtils.getLoginUser();
} catch (Exception e) {
return new JsonBean<>(401, "用户未登录");
}
}
// 角色校验
if (StringUtils.isNotBlank(role)) {
if (!SecurityUtils.hasRole(role)) {
return new JsonBean<>(403, "用户权限不足");
}
}
// 权限校验
if (StringUtils.isNotBlank(permission)) {
if (!SecurityUtils.hasPermi(permission)) {
return new JsonBean<>(403, "用户权限不足");
}
}
return null; // 返回 null 表示放行
}
}
5.2 配置接口权限
在 Magic API 编辑器中,为接口配置权限选项:
| 选项 | 说明 | 示例值 |
|---|---|---|
require_login | 是否需要登录 | true / false |
role | 需要的角色 | admin |
permission | 需要的权限 | system:user:list |
配置方式:
- 在编辑器中选择接口
- 点击「选项」标签
- 添加对应的选项配置
5.3 获取当前用户
在脚本中获取当前登录用户信息:
import com.ruoyi.common.utils.SecurityUtils
// 获取当前用户 ID
var userId = SecurityUtils.getUserId()
// 获取当前用户名
var username = SecurityUtils.getUsername()
// 获取当前用户信息
var loginUser = SecurityUtils.getLoginUser()
var user = loginUser.getUser()
六、Redis 缓存
6.1 基础操作
Magic API 集成了 Redis 插件,可直接使用:
// 设置缓存
redis.set('key', 'value')
// 设置缓存(带过期时间,单位秒)
redis.set('key', 'value', 3600)
// 获取缓存
var value = redis.get('key')
// 删除缓存
redis.del('key')
// 判断是否存在
var exists = redis.exists('key')
// 设置过期时间
redis.expire('key', 3600)
6.2 接口缓存示例
// 先从缓存获取
var cacheKey = 'user:list:' + deptId
var list = redis.get(cacheKey)
if (list == null) {
// 缓存不存在,查询数据库
list = db.select("""
SELECT * FROM sys_user WHERE dept_id = #{deptId}
""")
// 存入缓存,1小时过期
redis.set(cacheKey, list, 3600)
}
return list
6.3 Hash 操作
// 设置 Hash 字段
redis.hset('user:1', 'name', '张三')
redis.hset('user:1', 'age', 18)
// 获取 Hash 字段
var name = redis.hget('user:1', 'name')
// 获取所有字段
var user = redis.hgetAll('user:1')
// 删除 Hash 字段
redis.hdel('user:1', 'name')
七、高级特性
7.1 事务支持
import db
// 开启事务
db.transaction(() => {
db.update("""
UPDATE account SET balance = balance - 100 WHERE user_id = 1
""")
db.update("""
UPDATE account SET balance = balance + 100 WHERE user_id = 2
""")
})
7.2 异步执行
import async
// 异步执行
async.run(() => {
// 耗时操作
db.insert("""
INSERT INTO log (content) VALUES ('异步日志')
""")
})
return "请求已接收"
7.3 HTTP 请求
import http
// GET 请求
var result = http.get('https://api.example.com/users')
// POST 请求
var result = http.post('https://api.example.com/users', {
body: {
name: '张三',
age: 18
}
})
// 带 Header 的请求
var result = http.get('https://api.example.com/users', {
headers: {
'Authorization': 'Bearer token'
}
})
7.4 参数校验
import assert
// 非空校验
assert.notNull(userId, '用户ID不能为空')
assert.notBlank(userName, '用户名不能为空')
// 条件校验
assert.isTrue(age >= 18, '年龄必须大于等于18')
// 正则校验
assert.regx(email, '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$', '邮箱格式不正确')
7.5 日志输出
import log
log.info('这是一条信息日志')
log.warn('这是一条警告日志')
log.error('这是一条错误日志')
log.debug('这是一条调试日志')
八、实战示例
8.1 用户列表接口
/**
* 接口路径:GET /magic/api/user/list
* 请求参数:pageNum, pageSize, userName, status
*/
// 参数处理
var pageNum = pageNum ?: 1
var pageSize = pageSize ?: 10
// 构建查询
var query = db.table('sys_user')
.where()
.eq('del_flag', '0')
// 动态条件
if (userName) {
query.like('user_name', userName)
}
if (status) {
query.eq('status', status)
}
// 分页查询
var page = query.orderBy('create_time desc')
.page(pageNum, pageSize)
.select()
return page
8.2 用户详情接口
/**
* 接口路径:GET /magic/api/user/{id}
* 路径参数:id
*/
import assert
// 参数校验
assert.notNull(path.id, '用户ID不能为空')
// 查询用户
var user = db.selectOne("""
SELECT u.*, d.dept_name
FROM sys_user u
LEFT JOIN sys_dept d ON u.dept_id = d.dept_id
WHERE u.user_id = #{path.id} AND u.del_flag = '0'
""")
if (user == null) {
return {
code: 404,
msg: '用户不存在'
}
}
return user
8.3 新增用户接口
/**
* 接口路径:POST /magic/api/user
* 请求体:userName, nickName, email, phonenumber, deptId
*/
import assert
import com.ruoyi.common.utils.SecurityUtils
// 参数校验
assert.notBlank(body.userName, '用户名不能为空')
assert.notBlank(body.nickName, '昵称不能为空')
// 检查用户名是否存在
var exists = db.selectOne("""
SELECT 1 FROM sys_user WHERE user_name = #{body.userName} AND del_flag = '0'
""")
if (exists) {
return {
code: 500,
msg: '用户名已存在'
}
}
// 插入用户
var result = db.insert("""
INSERT INTO sys_user (user_name, nick_name, email, phonenumber, dept_id,
password, create_by, create_time)
VALUES (#{body.userName}, #{body.nickName}, #{body.email}, #{body.phonenumber},
#{body.deptId}, #{SecurityUtils.encryptPassword('123456')},
#{SecurityUtils.getUsername()}, NOW())
""")
return {
code: 200,
msg: '新增成功'
}
8.4 统计报表接口
/**
* 接口路径:GET /magic/api/report/user-stats
* 请求参数:startDate, endDate
*/
// 用户统计
var stats = db.selectOne("""
SELECT
COUNT(*) as totalCount,
SUM(CASE WHEN status = '0' THEN 1 ELSE 0 END) as activeCount,
SUM(CASE WHEN status = '1' THEN 1 ELSE 0 END) as disabledCount
FROM sys_user
WHERE del_flag = '0'
""")
// 部门分布
var deptStats = db.select("""
SELECT d.dept_name, COUNT(u.user_id) as userCount
FROM sys_dept d
LEFT JOIN sys_user u ON d.dept_id = u.dept_id AND u.del_flag = '0'
WHERE d.del_flag = '0'
GROUP BY d.dept_id, d.dept_name
ORDER BY userCount DESC
LIMIT 10
""")
// 注册趋势
var trend = db.select("""
SELECT DATE(create_time) as date, COUNT(*) as count
FROM sys_user
WHERE del_flag = '0'
AND create_time BETWEEN #{startDate} AND #{endDate}
GROUP BY DATE(create_time)
ORDER BY date
""")
return {
stats: stats,
deptStats: deptStats,
trend: trend
}
九、生产环境配置
9.1 禁用编辑器
生产环境建议禁用 Web 编辑器:
magic-api:
web: null # 设为 null 禁用编辑器
9.2 修改默认密码
magic-api:
security:
username: your_username
password: your_strong_password
9.3 接口访问控制
通过 Spring Security 控制 Magic API 接口访问:
.requestMatchers("/magic/api/**").authenticated() // 需要登录
.requestMatchers("/magic/web/**").hasRole("ADMIN") // 仅管理员
十、常见问题
10.1 接口不生效
- 检查是否点击「保存」按钮
- 检查接口路径是否正确
- 查看控制台是否有错误日志
10.2 数据库连接失败
- 检查数据源配置是否正确
- 确认数据库服务是否启动
- 查看连接池配置
10.3 权限校验失败
- 确认接口配置了正确的权限选项
- 检查请求是否携带有效的 Token
- 验证用户是否拥有对应权限
十一、总结
RuoYi-SpringBoot3-Pro 集成的 Magic API 具有以下特点:
- 开箱即用:预配置完善,启动即可使用
- 可视化开发:Web 界面编写接口,所见即所得
- 即时生效:无需重启,修改立即生效
- 数据库持久化:接口存储在数据库,支持版本控制
- 权限集成:与 RuoYi 权限体系无缝集成
- Redis 支持:内置 Redis 插件,轻松实现缓存
Magic API 适合快速开发简单接口,与传统 Controller 开发方式互补,可根据实际需求灵活选择。
5147

被折叠的 条评论
为什么被折叠?



