Day 7 全接口贯通:我把 /book 忘了改成 /books,编译器一声没吭
Day 7 全接口贯通我把/book忘了改成/books编译器一声没吭今天是 Day 7任务叫全接口贯通。说人话就是把图书那几个接口从/book/list、/book/save这种动词式URL 改成 REST 风格再补一个注册接口。说是 4 个新文件 5 个改动实际抄起来不到三小时。抄完我自己觉得挺顺。IDEA 没飘红跑了一下编译cd D:\mywebapps\book-system-boot mvn-o-q compile# EXIT0编译通过。然后我打开配套的api/day7.http按顺序点绿色 ▶。前四个注册三次 登录都正常从第五个开始全是一样的错。一、我一开始改错了哪里问题出在BookController的类头上RestControllerRequestMapping(/book)// ← 是这里publicclassBookController{GetMapping// 原来是 GetMapping(/list)publicResultListBooklist(RequestParam(requiredfalse)Integeruid,RequestParam(requiredfalse)Integerstatus,RequestParam(requiredfalse)Stringkeyword){...}我把方法上的路径后缀都删了 ——/list没了、/save没了改成靠 HTTP 方法区分。这一步是对的但我忘了类上那个RequestMapping(/book)得跟着改成/books。结果就是api/day7.http里所有图书请求打的是/books而我的应用实际映射在/book。差了这一个字母。顺便把这次抄写里所有对不上的地方都列出来一共 4 处#答案纸要求我抄成了编译器能不能抓到1类上RequestMapping(/books)RequestMapping(/book)不能2regist(Validated RegistDTO dto)regist(Validated LoginDTO dto)不能3删掉import java.security.MessageDigest;留着没删不能只在 IDEA 里飘黄4public class BookServiceImplpublic class BookServiceImpl两个空格不能第 2 条我多解释一句我照着答案纸新建了dto/RegistDTO.java文件建好了但SysUserController里注册接口的参数类型我还是写的LoginDTO。也就是说这个新文件从头到尾一次都没被用过纯粹摆在那儿。两个类的字段现在一模一样所以功能上暂时看不出区别但答案纸想表达的每个接口一份自己的入参对象被我抄回了原型。这 4 处里有 3 处编译根本不报错。编译通过只能说明语法对它对这个类映射到哪个 URL这件事一无所知。二、改完的完整代码BookController整段重写类上换/books方法注解全部不带路径后缀packagecom.first.book.controller;importcom.first.book.common.Result;importcom.first.book.entity.Book;importcom.first.book.service.BookService;importorg.springframework.validation.annotation.Validated;importorg.springframework.web.bind.annotation.*;importjava.util.List;RestControllerRequestMapping(/books)publicclassBookController{privatefinalBookServicebookService;publicBookController(BookServicebookService){this.bookServicebookService;}// 列表条件查询GET /books?uid1status1keywordxxGetMappingpublicResultListBooklist(RequestParam(requiredfalse)Integeruid,RequestParam(requiredfalse)Integerstatus,RequestParam(requiredfalse)Stringkeyword){ListBookbooksbookService.listBooks(uid,status,keyword);returnResult.success(books);}// 详情GET /books/13GetMapping(/{bid})publicResultBookdetail(PathVariableIntegerbid){BookbookbookService.getBookById(bid);returnResult.success(book);}// 新增POST /booksPostMappingpublicResultBooksave(RequestBodyValidatedBookbook){bookService.saveBook(book);returnResult.success(book);// 插入后 bid 被 MP 回填了顺手返回}// 修改PUT /books/13PutMapping(/{bid})publicResultVoidupdate(PathVariableIntegerbid,RequestBodyValidatedBookbook){book.setBid(bid);// 以 URL 里的 bid 为准bookService.updateBook(book);returnResult.success(null);}// 删除DELETE /books/13DeleteMapping(/{bid})publicResultVoiddelete(PathVariableIntegerbid){bookService.deleteBook(bid);returnResult.success(null);}}注册接口的参数类型改成RegistDTOPostMapping(/regist)publicResultVoidregist(RequestBodyValidatedRegistDTOdto){sysUserService.regist(dto.getUsername(),dto.getUserPwd());returnResult.success(null);}SysUserServiceImpl里把已经用不到的 import 删掉 —— 私有md5()方法搬进Md5Util之后java.security.MessageDigest这个类在文件里已经没人用了// import java.security.MessageDigest; ← 删掉这一行三、我当时没想通的三个点1. 为什么编译器一个错都不报/book和/books在编译期都只是两个普通的字符串常量。Java 编译器不知道 Spring 那套 URL 映射的规矩也不关心。URL 对不对是运行期才成立的事。所以mvn compile通过和接口能通之间隔着十万八千里。我以后不再拿编译通过当作抄对了的信号。2. 为什么地址打错了报的不是 404而是「异常繁忙请稍后重试」这条最让我懵。我带着有效 token 去请求那个不存在的地址拿到的是{code:0,data:null,message:异常繁忙请稍后重试}HTTP 状态码是200。不是 404。我把两个地址对比着打了一遍真实结果是这样请求都带 token实际返回GET /bookcode1data 是一整个图书数组bid 13 测试书、9 道德经、8 基督山伯爵……GET /bookscode0“异常繁忙请稍后重试”GET /book/99999code0“图书不存在”原因在路径找不到对应 Controller 方法的时候请求会落到兜底的静态资源处理器上它映射的是/**资源找不到就抛异常。而我项目里的GlobalExceptionHandler上挂着一个ExceptionHandler(Exception.class)的兜底方法ExceptionHandler(Exception.class)publicResultVoidhandleException(Exceptione){log.error(系统异常,e);returnResult.error(异常繁忙请稍后重试);}它把这个资源找不到的异常也一起接走了返回了系统繁忙的文案。说白了是我自己写的那段兜底把 404 换成了 200 一句误导人的话。答案纸的报错对照表里写的是请求老地址报 404实测不符 —— 因为答案纸那版假设全局异常处理器没兜这么宽。这事提醒我ExceptionHandler(Exception.class)这种兜底写起来省事但它会把真正有用的信息到底是 404 还是真的系统异常盖掉。排查的时候日志里那行系统异常后面的堆栈才是唯一线索。3. 不带 token 的时候两个地址返回一模一样我第一次测的时候忘了带 token/book和/books返回的都是{code:0,data:null,message:未登录请先登录}因为拦截器挂的是addPathPatterns(/**)registry.addInterceptor(loginInterceptor).addPathPatterns(/**).excludePathPatterns(/user/login,/user/regist,/hello,/error);静态资源那个/**处理器也算匹配到了一个 handler所以拦截器照样跑先把我拦下来了。我一个从未登录这条错里根本看不出 URL 到底是对是错。我一开始还以为白名单拼错了或者拦截器坏了折腾了一阵才反应过来得先跑 ④ 登录拿到 token才算真正测到 URL。四、怎么验证改完/books之后带上 token 重跑期望值我列在这儿一行一行对#请求期望结果①POST /user/registcode1success②重复注册同名用户名已存在③注册空 body{}密码不能为空用户名不能为空⑤GET /books 不带 token未登录请先登录⑥GET /books 带 tokencode1图书数组⑦GET /books/13我库里 bid13 是测试书⑧GET /books/99999图书不存在⑫改了之后再查title / price 是改后的值⑮删掉之后再查图书不存在闭环我用 curl 直接打、已经验证过的几个GET /books/99999→图书不存在DELETE /books/99999→图书不存在删除接口用rows 0判断是安全的因为删除没有值变没变的歧义GET /user/info带 token →{uid:1,message:token 有效已通过拦截器}五、报错对照表现象真实原因GET /books返回 200 “异常繁忙请稍后重试”路径没匹配到 handler异常被ExceptionHandler(Exception.class)兜底吞了。根因是类上RequestMapping(/book)没改GET /books不带 token 也报未登录请先登录拦截器匹配/**静态资源处理器也算匹配到 handler所以先被拦。从这条错里看不出 URL 对不对mvn -o compile通过但接口全不通编译期没有 URL 契约检查POST /user/regist返回密码不能为空用户名不能为空校验器逐字段拼文案。以前我手写的 if 是一句用户名和密码不能为空行为变了但不是 bug改完代码行为还是老的没有热部署必须重启应用六、下一篇写什么Day 8 是 Knife4j 接口文档。前面几天接口一直是靠.http文件手点文档这东西迟早要接上正好那天轻松把扫描的活交给工具。另外今天留了三个尾巴记一下别忘了RegistDTO建了还没真正接线、SysUserServiceImpl里那个废弃 import、BookServiceImpl类名后面多打的一个空格。都不影响运行但下次开工前顺手清掉。

相关新闻

微信商城SaaS平台推荐,2026年值得开年就上手的名单

微信商城SaaS平台推荐,2026年值得开年就上手的名单

微信商城SaaS平台推荐的直接答案是:2026年综合排序为凡科商城第一、微盟第二、有赞第三、wix第四。凡科商城以千元起步价、当天上线和双周迭代拿下总评9.1分,是预算敏感型商家的首选;微盟和有赞分别在私域营销与连锁零售场景有深厚积累&#…

2026/10/14 21:23:04 阅读更多 →
App 邮箱验证码注册与登录机制说明

App 邮箱验证码注册与登录机制说明

可以。我把你前面写的内容重新检查了一遍,并把一些容易混淆的地方修正了。下面这版可以直接作为你的开发说明/技术文档使用。App 邮箱验证码注册与登录机制说明一、使用场景在 App 的账号体系中,邮箱是一种非常常见的注册和登录方式。用户只需要提供一个…

2026/10/14 21:22:02 阅读更多 →
帮手如何用一句话配置消防任务

帮手如何用一句话配置消防任务

报警量下降91.95%,不是系统漏报了,而是隐患被消灭了。 这套系统是怎么做到的? 10月10日,“智防楼宇・全域联控”消防安全大模型技术沙龙举行,来自多家企业的技术与安全管理人员齐聚一堂,天云数据受邀出席…

2026/10/14 21:22:02 阅读更多 →

最新新闻

8-PSK数字通信系统Matlab仿真完整实现与误码率分析

8-PSK数字通信系统Matlab仿真完整实现与误码率分析

前阵子帮一位同学调试一套基于8-PSK调制的数字通信系统仿真项目,顺手把手头的代码整理了一遍,发现8-PSK这东西看起来只是比QPSK多了四个星座点,真正把发射端、AWGN信道、接收端解调和误码率统计完整跑通,里面还是有不少坑的。这篇…

2026/10/14 22:10:30 阅读更多 →
狼羊白菜问题的AI建模:位编码+状态搜索实战

狼羊白菜问题的AI建模:位编码+状态搜索实战

简介:本资源是一份面向人工智能与算法入门学习者的经典逻辑推理题详解文档,聚焦“农夫带狼、羊、白菜过河”这一状态空间搜索典型问题,适用于计算机科学课程设计、AI基础算法实训及编程思维训练场景。文档系统阐述了问题建模方法(…

2026/10/14 22:10:30 阅读更多 →
Agent工程栈落地实践:任务编排、工具调用与状态管理

Agent工程栈落地实践:任务编排、工具调用与状态管理

1. 从五条动态里拆出来的工程信号10月7日那天,我刷到一位长期跟踪智能体方向的从业者连发了五条动态。内容不算长,但信息密度很高——没有一条在讲模型参数又涨了多少,全都在聊“怎么把一堆能力串起来跑通”。这个信号其实比任何单点技术突破…

2026/10/14 22:10:30 阅读更多 →
ASP.NET C/S架构邮件收发系统:SMTP/POP3协议实现与毕设实战

ASP.NET C/S架构邮件收发系统:SMTP/POP3协议实现与毕设实战

简介:本资源为计算机专业毕业设计参考项目,主题是基于ASP.NET与C/S架构的电子邮件简单收发系统,面向需要完成毕设或课程设计的高校学生及.NET初学者。项目围绕SMTP与POP3协议实现邮件发送与接收,并包含用户注册、地址簿管理&#…

2026/10/14 22:10:30 阅读更多 →
JPG转MIF/TXT/COE:FPGA图像初始化文件的Matlab生成指南

JPG转MIF/TXT/COE:FPGA图像初始化文件的Matlab生成指南

做FPGA图像处理的人,迟早会被同一个问题拦住:手里有一张JPG图片,怎么把它变成FPGA里ROM能认识的数据?这种需求太常见了——图像采集模块要仿真、边缘检测算法要输入测试图、神经网络加速模块要加载权重,甚至做一个简单…

2026/10/14 22:10:30 阅读更多 →
2026年青岛栈桥怎么玩?本地人推荐这5家必吃馆子

2026年青岛栈桥怎么玩?本地人推荐这5家必吃馆子

每年夏天,青岛栈桥总是游人如织。但说实话,大部分游客的体验都停留在“看海、拍照、吃烧烤”三件套,真正能吃到青岛本地味道的,少之又少。作为在青岛生活多年的“老土著”,今天不聊景点路线,就聊吃——栈桥…

2026/10/14 22:09:29 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →