关于查询接口设计
此篇博客记录自己在设计模糊查询接口时候犯的错误,以及个人的一些浅略的思考。说明:此并非最优设计
前言
此模糊查询是项目的一个小接口,大致功能如下图所示。
产品的需求:
- 下拉框可以筛选状态,如选中已激活,则只展示已激活状态的学生名单。
- 搜索框中可以输入内容,进行姓名模糊查询。
- 可以根据创建时间进行排序,升序或者降序。
- 分页功能
第一次的接口设计(❌)
不知道从哪篇博客中看到这样一句话:GET操作不修改数据库,POST操作修改数据库(事实没这么绝对)。这不简单呀,5秒钟,Controller,Service...,前端对接,搞定。
GET /student/{studentName}/{state}?order=1&page=1&size=10
GET /student/{state}?order=1&page=1&size=10
order: -1:不排序,0:升序,1:降序
state: -1:全部,0:未激活,1:已激活
哦,这该死的天才,这么难的问题,轻易化解。
让我们对应需求,一一验证:
- 下拉框可以筛选状态,如选中已激活,则只展示已激活状态的学生名单。
GET /student/1?order=-1&page=1&size=10 - 搜索框中可以输入内容,进行姓名模糊查询。
GET /student/张三/-1?order=1&page=1&size=10 - 可以根据创建时间进行排序,升序或者降序。
GET /student/-1?order=1&page=1&size=10 升序 - 分页功能
GET /student/-1?order=1&page=1&size=10
前端,我的接口都能满足,要什么你自己组合去,很显然,目前为止功能正常。
测试登场,毫不犹豫扔给你一个缺陷,大意了没有闪。
为什么会出现404呢?哦因为你查询的内容导致接口变了。
第二次的接口设计(✔)(🟧待定) 2023-5-30 修改
- 为什么接口不能正常映射?
因为特殊字符,浏览器没把它当成字符串,导致请求的接口不能被后端识别。 - 有什么感想?
这种studentName未知的东西,尽量别放在PathParam,今天出来一个%,明天一个\,后天不知道出什么幺蛾子。
像state,这种固定的东西,只能取-1,0,1,可以放进PathParam中。
苦思冥想,这GET操作,还能怎么设计呢?
POST优雅登场
POST /student/list
{
"conditions":{
"name":"huiu9123",
"state":-1
},
"order":0,
"page":1,--
"size":10
}
通用Request
设计通用搜索请求体,conditions放自定义搜索条件,order、page、size这三个参数每个搜索都会用到,放在外边。
@Setter
@Getter
public class QueryRequest<T> {
/**
* 自定义搜索条件
* /
T conditions;
/**
* 排序
*/
Integer order;
/**
* 第几页
*/
Integer page;
/**
* 每页数据量
*/
Integer size;
}
设计需求自定义搜索条件
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class StudentQueryCondition {
String name;
Integer state;
}
设计搜索接口
@PostMapping(path = "/list")
public String list(@RequestBody QueryRequest<StudentQueryCondition> request) {
CodeMessageEnum msg = CodeMessageEnum.OK;
.......省略处理逻辑......
return ControllerUtil.wrap(msg, response).toString();
}
第三次接口设计(🟢)
由于后面添加了Mybatis-Plus框架,可以使用动态sql
@GetMapping("/student")
Result<ListDTO<StudentDTO>> queryStudentList(@Validated StudentQueryParam studentQueryParam) {
ListDTO<StudentDTO> result = subjectService.queryStudentList(studentListParam);
return Result.success(result);
}
class StudentQueryParam{
@Size(max = NAME_SIZE_MAX, message = NAME_SIZE_MESSAGE)
String name;
Integer state;
}
<select id="selectStudentPage" resultType="com.tao.entity.Student">
SELECT *
FROM demo_student ds
WHERE is_deleted = false
<if test="param.searchField!=null and param.searchField!='all' and param.searchVal != null and param.searchVal != ''">
and ds.${param.searchField} ilike '%${param.searchVal}%'
</if>
order by ${param.sortField} ${param.sortRule},ds.id desc
</select>
结尾
别人说的话不一定是对的。别人说的有道理 (/(ㄒoㄒ)/~~)- 踩过坑,才能长记性,这次因为我的错误,前端也要修改大量内容。
本文来自博客园,作者:帅气的涛啊,转载请注明原文链接:https://www.cnblogs.com/handsometaoa/p/16926613.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)