一、背景
在日常业务开发过程中,传统接口的查询条件、排序规则等参数均为硬编码实现,参数格式和查询逻辑固定,仅能满足预设的业务场景。当客户需要调整查询条件(如修改字段筛选范围、新增筛选维度、调整排序方式)时,必须由开发人员修改代码、重新测试并发布版本,导致:
- 客户需求响应周期长,灵活性极低;
- 开发人员重复编写相似的查询接口,效率低下;
- 接口版本迭代频繁,维护成本高。
为解决上述问题,设计并实现通用灵活查询接口,支持客户通过标准化 JSON 参数自定义查询条件、排序规则,无需修改代码即可满足多样化的查询需求。
二、核心实现逻辑
2.1 整体设计思路
通用灵活查询接口的核心是将结构化的 JSON 查询参数动态解析为可执行的 SQL 语句,整体逻辑分为三层:
- 参数接收层:接收前端传入的标准化 JSON 参数,完成参数格式校验和结构化转换;
- SQL 解析层:递归解析 JSON 中的筛选条件和排序规则,将其转换为 SQL 的
WHERE子句和ORDER BY子句; - 执行层:对解析后的 SQL 执行并返回查询结果。
2.2 核心解析逻辑
(1)筛选条件解析逻辑
- 支持嵌套条件:外层条件和内层条件均通过
joiner定义连接关系,递归解析所有层级的条件; - 支持多操作符:将 JSON 中的
operator映射为 SQL 的比较运算符(如>=、in等); - 支持多值条件:将
conditionValues数组适配不同操作符的参数格式(单值取第一个元素,多值拼接为(val1, val2))。
(2)排序规则解析逻辑
- 按
sortName匹配数据库表字段,按sortDirection确定排序方向; - 支持多字段排序,多个排序规则按数组顺序拼接为
ORDER BY 字段1 方向1, 字段2 方向2。
三、传参格式详细解释
3.1 示例参数解读
构建条件
(id >= 100 and id <= 1000) and (createTime >= "2025-7-1 12:00:00" and createTime <= "2025-8-1 12:00:00")
输入 JSON 参数
json
{
"filter": {
"joiner": "and",
"conditions": [{
"joiner": "and",
"conditions": [{
"conditionName": "id",
"operator": ">=",
"conditionValues": ["100"]
}, {
"conditionName": "id",
"operator": "<=",
"conditionValues": ["1000"]
}]
}, {
"joiner": "and",
"conditions": [{
"conditionName": "createTime",
"operator": ">=",
"conditionValues": ["2025-7-1 00:00:00"]
}, {
"conditionName": "createTime",
"operator": "<=",
"conditionValues": ["2025-8-1 00:00:00"]
}]
}]
},
"sorts": [{
"sortName": "createTime",
"sortDirection": "desc"
}]
}
解析逻辑说明
filter.joiner = "and":表示根层级的两个子条件(id 区间、时间区间)需同时满足;- 第一个子条件(
filter.conditions[0]):joiner = "and",表示id >= 100且id <= 1000; - 第二个子条件(
filter.conditions[1]):joiner = "and",表示createTime >= '2025-7-1 00:00:00'且createTime <= '2025-8-1 00:00:00'; sorts[0].sortName = "createTime"+sortDirection = "desc":表示按createTime降序排序。
3.2 核心参数路径与说明
| 参数路径 | 类型 | 必选 | 说明 |
|---|---|---|---|
| filter | Object | 是 | 筛选条件的根容器,所有筛选规则均包含在此节点下 |
| filter.joiner | String | 是 | 根层级子条件的连接符,仅支持 and/or,表示所有子条件的组合关系 |
| filter.conditions | Array | 是 | 根层级的子条件列表,元素可为嵌套的 filter对象或原子条件对象 |
| filter.conditions[*].joiner | String | 是(元素为 filter 时) | 嵌套层级子条件的连接符,仅支持 and/or |
| filter.conditions[*].conditions | Array | 是(元素为 filter 时) | 嵌套层级的子条件列表 |
| filter.conditions[*].conditionName | String | 是(元素为原子条件时) | 筛选字段名,需与数据库表字段名完全一致(如 id、createTime) |
| filter.conditions[*].operator | String | 是(元素为原子条件时) | 筛选操作符,支持 >=/<=/=/!=/like/in/not in等 |
| filter.conditions[*].conditionValues | Array | 是(元素为原子条件时) | 筛选值数组:1. 单值操作符(如 >=)取数组第一个元素;2. 多值操作符(如 in)取数组所有元素 |
| sorts | Array | 排序规则列表,无此节点时不排序 | |
| sorts[*].sortName | String | 是(sorts 非空时) | 排序字段名,需与数据库表字段名完全一致 |
| sorts[*].sortDirection | 否 | 排序方向,默认 asc(升序),支持 desc(降序) |
四、使用场景
- 客户自助调整查询条件:如运营人员需要灵活筛选不同时间范围、ID 区间的订单 / 用户数据,无需开发介入;
- 多维度查询:报表系统需要支持用户自定义筛选维度(如按地区、时间、状态组合筛选)和排序方式;
- 临时数据导出需求:业务人员临时需要导出特定条件的数据,通过该接口快速获取,无需开发定制接口;
- 第三方系统对接:对接外部系统时,对方需自定义查询条件,通用接口可满足多样化的对接需求。
五、风险点与防控措施
| 风险类型 | 具体风险 | 防控措施 |
|---|---|---|
| SQL 注入 | 恶意传入表名、字段名、操作符或值,构造注入语句 | 1. 表名做白名单校验,仅允许查询指定表; 2. 字段名校验,仅允许查询表中存在的字段; 3. 操作符白名单(仅允许预设的 >=、<= 等); 4. 参数值使用占位符,避免直接拼接; 5. 限制接口访问权限,仅授权用户可调用 |
| 性能风险 | 复杂嵌套条件、大范围数据查询导致数据库慢查询 | 1. 限制单次查询返回条数(如默认最多 1000 条); 2. 对查询字段增加索引; 3. 记录慢查询日志,监控异常查询; 4. 禁止使用 like '% xxx' 等低效查询(可选) |
| 数据安全 | 未授权用户查询敏感数据 | 1. 接口增加身份认证和权限校验; 2. 按用户权限过滤数据(如普通用户仅能查询自己的数据); 3. 敏感字段(如手机号、身份证)脱敏返回; 4. 记录接口调用日志,审计操作行为 |
| 参数格式错误 | 字段名错误、操作符不支持、值类型不匹配 | 1. 入参时校验字段名是否存在、操作符是否合法;2. 对时间、数字等字段做类型转换校验;3. 返回清晰的错误提示(如 “字段 createTime 不存在”) |
| 嵌套层级过深 | 条件嵌套层级过多导致 SQL 解析异常 | 1. 限制条件嵌套最大层级(如最多 3 层);2. 解析 SQL 时增加异常捕获,返回友好提示 |
六、参数到 SQL 的转换效果
6.1 转换规则
- 筛选条件:JSON 中的嵌套条件 → SQL 的
WHERE子句(括号区分嵌套层级); - 排序规则:JSON 中的
sorts数组 → SQL 的ORDER BY子句; - 最终 SQL:拼接
SELECT * FROM 目标表 + WHERE子句 + ORDER BY子句(目标表通过接口参数指定)。
6.2 示例转换效果
扩展示例
若 JSON 参数调整为多值 in查询 +or连接:
json
{
"filter": {
"joiner": "or",
"conditions": [{
"conditionName": "id",
"operator": "in",
"conditionValues": ["100", "200", "300"]
}, {
"conditionName": "status",
"operator": "=",
"conditionValues": ["1"]
}]
},
"sorts": [{
"sortName": "id",
"sortDirection": "asc"
}]
}
转换后的 SQL:
sql
SELECT * FROM user
WHERE id IN ('100', '200', '300') OR status = '1'
ORDER BY id ASC;
七、总结
- 核心逻辑:通用灵活查询接口的核心是将标准化 JSON 参数递归解析为 SQL 的 WHERE 子句和 ORDER BY 子句,实现查询条件的动态配置;
- 参数规范:关键参数路径(如
filter.joiner、filter.conditions[*].conditionName)需严格匹配数据库字段和预设规则,确保解析正确; - 风险防控:接口安全的核心是防范 SQL 注入、控制查询性能、保障数据安全,需通过白名单、权限校验、参数校验等手段落地。