


查询图书属性接口
约定前后端交互接口
约定前后端交互接口,进入修改页面,需要显示当前图书的信息;
tex
请求
/book/queryBookById?bookId=25
参数
无
响应
{
"id": 25,
"bookName": "图书21",
"author": "作者2",
"count": 999,
"price": 222.00,
"publish": "出版社1",
"status": 2,
"statusCN": null,
"createTime": "2023-09-04T04:01:27.000+00:00",
"updateTime": "2023-09-05T03:37:03.000+00:00"
}
根据图书ID,获取当前图书的信息。
实现服务器代码
控制层 BookController

业务层 BookService

数据层 BookInfoMapper
根据图书ID,查询图书信息。
java
@Select("select id, book_name, author, count, price, publish, `status`,
create_time, update_time " +
"from book_info where id=#{bookId} and status<>0")
BookInfo queryBookById(Integer bookId);

接口测试
重新运行程序,打开页面127.0.0.1:9090/book/queryBookById?bookId=5

修改图书属性接口
约定前后端交互接口
点击修改按钮,修改图书信息。
tex
请求
/book/updateBook
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
参数
id=1&bookName=图书1&author=作者1&count=23&price=36&publish=出版社1&status=1
响应
"" // 失败信息, 成功时返回空字符串
我们约定,浏览器给服务器发送一个 /book/updateBook 这样的 HTTP 请求,form表单的形式来提交数据;
服务器返回处理结果,返回""表示添加图书成功,否则,返回失败信息。
实现服务器代码
控制层 BookController


业务层 BookService

数据层 BookInfoMapper
更新逻辑相对较为复杂,因为一本书不是每个属性都需要进行修改的;
所以 bookInfo 对象的哪些属性传递了值,我们就更新哪些值,需要使用动态SQL
。
对于初学者而言,注解的方式拼接动态SQL不太友好,煮啵采用xml
的方式来实现。
因为注解和 XML 可以同时在一个 interface 中共存,所以煮啵就不创建新接口了;

配置 xml 路径:
yaml
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
最终整体的 yml 配置文件为:

xml 实现:
创建BookInfoMapper.xml文件,并初始化




接口测试
重新运行程序:

结果层层筛查和尝试,煮啵才锁定问题:

查看以前的博客,煮啵发现:spring 和 mybatis 是同级别的层次,煮啵把 mybatis 设置成了 spring 的小弟
;

修改好代码之后,重新提供 Postman 构造请求,终于成功返回响应:

提前开香槟,我们这一路走来不容易,多少次流着泪说不分离~~~(bushi)
验证数据库表信息是否被修改:


查找、修改图书客户端代码实现
查找图书
我们希望点击修改按钮时:

跳转的输入框中有原来的值:

修改好数据后,点击确认按钮,会调用后端:

接下来,我们来写前端代码:
我们希望,点击修改页面后,马上调用后端,补全输入框中的信息:

点击修改按钮之后,我们看到 URL 中 bookId 的赋值是未被定义的参数:

按修改按钮时,会跳转页面,但是跳转的 URL 参数 bookId 赋值是 book.bookId ,与后端属性名 id 不同,自然无法识别 bookId:



修复好 book_list 跳转 book_update 的 URL 参数后,我们继续补齐 book_update 的 ajax 请求:

location.search
是 JavaScript 中 window.location 对象的一个属性,它返回 URL 中从问号?
开始的部分(包括问号),也就是查询字符串部分。例如:
- 如果当前 URL 是
http://example.com/book_update.html?bookId=123
- 那么
location.search
的值就是"?bookId=123"
在你的代码中:
javascript$.ajax({ type: "get", url: "/book.queryBookId" + location.search, });
这意味着:
- 当用户从图书列表点击"修改"按钮时,会跳转到
book_update.html?bookId=123
(假设图书ID是123)- 在修改页面,
location.search
就是"?bookId=123"
- 这个查询字符串会直接附加到请求URL后面,形成完整的请求:
/book.queryBookId?bookId=123
为什么不用传data给后端了?
在
GET请求
中,数据通常是通过URL的查询字符串
传递的(就像这里做的),而不是像POST请求那样放在请求体中
。这是因为:
- GET请求的设计初衷就是用于
获取数据
,其参数直接体现在URL中
- 查询字符串
?bookId=123
本身就是传递给后端的数据- 这种方式更符合RESTful风格,URL本身就标识了要操作的资源
所以在这种情况下,不需要额外使用
data
参数来传递数据,因为数据已经包含在URL的查询字符串中了。
我们通过 URL 中的信息,想后端发送 get 请求,接下来就通过 success 接收后端的返回结果,并且通过 id 选择器,对前端输入框对应的属性赋值,赋的值是后端对应的属性:


这里需要注意:图书状态的 value = "1" ,"2" ,是与我们后端数据库的定义有关的,要和后端的枚举对应上:

修改图书
我们观察,在列表页时,我们已经补充了[修改]的链接:


补全修改图书的方法:
通过 id 选择器
选中 form 表单
,使用 serialize()
对表单进行序列化
,就拿到了 fom 表单的值
,这样就不需要对 bookName,bookAuthor 这些属性分别赋值

对后端返回的数据进行处理:

接口测试
ctrl+s 保存代码,重新运行程序,结果发现输入框并没有值:

通过 deepseek 不断缩小问题范围,最终锁定 bug:

修改 URL ,保存代码,重新运行程序:

此时点击修改按钮,跳转页面的输入框中有值了:

我们试着修改值:

修改数据,点击确定后,页面跳转到图书列表的第一页:

找到原来的那本书,发现又出 bug 了,对应的属性没有更新:

遇到这种问题,我们要先冷静下来,因为后端打印有日志,方便排查问题,所以我们先看后端,再看前端;
找到对应 update 的日志:

我们发现 SQL 对应的 id 赋值为 null,很幸运的找到了出现问题的原因!
我们再仔细看这条日志,发现前端传过来的 id 值为 null,就说明问题出在前端:


我们修改图书信息,是根据图书ID来修改的,所以需要前端传递的参数中,包含图书ID。
有两种方式:
- 获取url中参数的值(比较复杂,需要拆分url)
- 在form表单中,再增加一个隐藏输入框,存储图书ID,随 $("#updateBook").serialize() 一起提交到后端。
我们采用第二种方式:
在form表单中,添加隐藏输入框。
hidden
类型的<input>
元素。- 隐藏表单,用户不可见、不可改的数据,在用户提交表单时,这些数据会一并发送出。
- 使用场景:正被请求或编辑的内容的ID。这些隐藏的input元素在渲染完成的页面中完全不可见,且没有方法可以使它重新变为可见。


保存代码,重新运行程序,执行上述修改步骤:



