Java 程序员成长记(四):菜鸟入职之接口「前后端 Battle」

108 阅读7分钟

技术知识点:Swagger @Schema用法、@Validated参数校验、前后端协作流程、接口文档自动化生成

一、工作群里的「红色@全体」

周三上午十点,阳光正透过百叶窗在办公区织出金色条纹。小彬的手机突然震动,企业微信弹出99+消息——前端小浩在工作群里@全体,附带三张截图,每张都用红色箭头标着触目惊心的"文档不一致"。

「后端Swagger枚举值和代码对不上!」小浩的消息带着三个爆炸表情,「TaskStatusEnum在文档里是'1=进行中',代码里明明是'2=进行中'!这让我怎么写下拉框?」

小彬感觉喉咙发紧。他昨天刚写完任务状态查询接口,为了图方便,直接在@ApiParam里手动标注枚举值,没想到代码里的枚举常量早在上周重构时被贝贝哥改过。工位隔板外传来滑板的摩擦声,小浩穿着破洞牛仔裤晃过来,潮牌卫衣帽子上的耳机线还在晃荡:「彬哥,咱能别让接口文档比前任心思还难懂吗?」

大飞哥从会议室探出头,POLO衫领口的"流程控"徽章闪了闪:「小彬,带笔记本过来,开个紧急接口对齐会。」会议室里,投影仪投出小彬的Swagger文档,参数说明栏里的枚举值像错位的牙齿般刺眼。

二、小浩的「文档控诉」

「给大家演示下前端的痛。」小浩连上投影仪,打开Postman演示接口调用。当他选择TaskStatusEnum时,下拉菜单里的选项赫然是过时的"1=草稿",而实际代码中"草稿"对应的枚举值早已改为0。

「上周贝贝哥重构枚举时,后端没同步文档,」小浩敲了敲屏幕,「我按文档写的前端逻辑,上线后用户选'草稿'结果提交到'进行中',差点被运营部骂死。」他转向小彬,语气稍软:「不是针对你,是咱们团队得建立文档同步机制。」

大飞哥在白板上画了个双向箭头:「需求铁三角里,文档是范围管理的底线。小彬,你用的@ApiParam是手动维护的,太容易出错。小浩,你平时怎么处理这种情况?」

小浩从卫衣口袋掏出U盘,插上电脑后打开一个Spring Boot项目:「用@Schema(implementation = EnumClass.class)啊!」他指着代码里的注解:「Swagger能自动读取枚举的name和value,永远和代码同步。」

小彬凑近屏幕,看到TaskStatusEnum的定义:

@Getter
@AllArgsConstructor
public enum TaskStatusEnum {
    DRAFT(0, "草稿"),
    IN_PROGRESS(1, "进行中"),
    COMPLETED(2, "已完成");

    private final int code;
    private final String desc;
}

在Controller的接口里,小浩演示了正确的注解用法:

@GetMapping("/tasks")
public List<Task> getTasksByStatus(
    @RequestParam("status") 
    @Schema(implementation = TaskStatusEnum.class) 
    TaskStatusEnum status
) {
    // 业务逻辑
}

「这样Swagger会自动生成枚举列表,」小浩敲了敲键盘,「而且配合@Validated参数校验,还能防止前端传非法值。」他转头对大飞哥说:「建议把Swagger文档生成加到CI/CD流程里,每次代码提交自动更新文档。」

三、贝贝哥的「代码洁癖手术」

会议结束后,小彬回到工位修改代码。刚把@ApiParam换成@Schema,贝贝哥就晃着马克杯过来,杯身上"代码即文档"的字样映着他严肃的表情:「让我看看接口设计。」

「参数校验用@Validated了吗?」贝贝哥一眼扫到Controller,「光同步文档不够,得防止脏数据进服务层。」他在方法参数前加上@Validated,并在枚举类里添加校验逻辑:

@RestController
@RequestMapping("/tasks")
@Validated
public class TaskController {
    @GetMapping
    public List<Task> getTasksByStatus(
        @RequestParam("status") 
        @Schema(implementation = TaskStatusEnum.class) 
        @NotNull(message = "状态不能为空") 
        TaskStatusEnum status
    ) {
        // 业务逻辑
    }
}

「代码洁癖第四条:永远假设前端会传垃圾数据。」贝贝哥摸出酒精湿巾擦了擦小彬的键盘,「上周有个实习生没做参数校验,被黑客用非法枚举值击穿了防火墙——差点酿成生产事故。」

小彬想起红姐的"120%覆盖率"传说,赶紧在Service层加了一道防御:

public List<Task> getTasksByStatus(TaskStatusEnum status) {
    if (!Arrays.asList(TaskStatusEnum.values()).contains(status)) {
        throw new IllegalArgumentException("非法任务状态");
    }
    // 业务逻辑
}

贝贝哥满意地点头:「这就对了。接口就像城门,文档是通行证,校验是护城河,缺一不可。」

四、茶水间的「跨端和解」

午休时,小彬在茶水间遇到小浩。潮男正在用咖啡机拉花,奶泡在咖啡上堆出Swagger的logo:「还在为文档的事自责?我刚入行时,把后端接口的BigDecimal当成String解析,导致金额显示成科学计数法,被产品经理骂得狗血淋头。」

小浩递过咖啡,杯壁上凝着水珠:「其实前后端协作就像谈恋爱,得互相迁就。我们前端希望文档像渣男的承诺一样准确,你们后端希望接口像处女的代码一样干净——平衡点就在工具链里。」

他掏出手机展示自己写的Chrome插件:「这玩意儿能自动同步Swagger文档到Figma,设计师再也不用手动标枚举值了。对了,」小浩突然神秘兮兮,「下午大飞哥要搞'接口文档靠谱奖'颁发仪式,你准备上台领奖吧。」

五、下班后的「文档攻坚战」

夕阳把办公区染成蜜色时,小彬还在研究Swagger配置。他按照小浩的教程,在application.properties里添加了全局配置:

springdoc.swagger-ui.path=/api-docs
springdoc.api-docs.path=/v3/api-docs
springdoc.swagger-ui.enabled=true

打开http://localhost:8080/swagger-ui.html,全新的文档界面让他眼前一亮:枚举值自动对齐代码,参数校验错误信息清晰可见。正当他陶醉时,老王抱着保温杯路过,格子衬衫上别着"架构师认证"徽章:「在研究OpenAPI?其实可以用Springdoc的@ParameterObject注解,把复杂参数封装成POJO,文档更清爽。」

老王在白板上画起架构图:「接口文档是团队的公共契约,就像微服务间的API网关,必须统一标准。我们下周要搞个'接口设计评审会',你正好练练手。」

六、第二天的「勋章时刻」

周四上午,大飞哥抱着甘特图来到开发区:「全体注意,今天有两个重要事项:第一,小彬的接口文档整改通过验收;第二——」他掏出一个金色徽章,上面刻着"接口文档靠谱奖",「根据团队'技术温度'制度,颁发电子勋章一枚!」

小浩在旁边用手机播放《颁奖曲》改编版,歌词变成"接口一致世界和平"。贝贝哥递来一张新的键盘贴纸:"Swagger不是终点,是协作的起点"。最让小彬惊喜的是,红姐居然在测试报告里写了句批注:"文档清晰,测试用例编写效率提升40%——值得表扬"。

当小彬把新文档链接发到项目群时,运营部同事立刻回复:"终于能看懂状态码了!感动哭"。他突然明白,为什么团队把"接口文档"看得和代码一样重要——这不仅是技术问题,更是跨部门协作的生命线。

尾声:键盘上的「契约精神」

下班前,小浩发来消息:"你的接口被收录进团队最佳实践啦!"附带的链接里,小彬的Swagger配置被写成《前后端协作黄金法则》案例,作者栏里有小浩、贝贝哥、大飞哥的签名。文档开头写着:"接口是代码与产品的翻译官,是团队协作的第一战场"。

小彬摸着键盘上的新贴纸,想起今天大飞哥说的话:"每个接口都是项目铁三角的缩影——范围(文档)、时间(响应速度)、质量(稳定性),缺一不可。"窗外的暮色中,XX科技的LOGO灯亮起,他在笔记本上写下:"写接口就像写情书,要让对方一眼看懂心意,更要经得起时间的考验。而Swagger,就是程序员的情书模板。"

【下章预告】
《Java 程序员成长记(五):菜鸟入职之 Optional「空指针陷阱」》