本篇学习指南
读完你能
  • 给 Java 类、方法、变量起符合规范的名字
  • 用 Swagger/OpenAPI3 注解把接口文档「写进代码里」
  • 理解为什么前后端要共用同一套命名约定
阅读时长
约 10 分钟 · 边读边对照代码
前置知识
了解 Java/Vue 基础;先读 01、02
接着读
打个比方:命名和注解
命名就像给人起名字——姓(包名)+ 名(类名)要让人一看就知道是谁、属于哪家。没人会给变量起名叫 a1、tmp2,就像没人会给孩子起名叫「孩子甲」。Swagger 注解则是给接口「贴标签」——@Tag 是分类标签(这个接口属于哪个模块),@Operation 是功能说明(这个接口干什么用),@Schema 是字段注释。贴好标签,接口文档就能自动生成,不用手写 Word。
概念入门
理解命名与接口
驼峰命名 camelCase
首字母小写,后续单词首字母大写,如 driverInstance。Java 和 JavaScript 的标准命名风格。
kebab-case
单词全小写,用连字符连接,如 driver-instance。URL 路径的标准风格。
Swagger / OpenAPI
自动生成 API 文档的工具。通过在代码中加注解(如 @Tag、@Operation),Swagger 会自动生成可交互的接口文档页面。
同一个东西在不同地方叫不同的名字,规范就是统一命名
URL
/api/iot/driver-instance
kebab-case(小写 + 连字符)
对应
Java
getDriverInstanceList()
camelCase(驼峰命名)
对应
Vue
api/iot/driverInstance.js
camelCase 文件名
1
前后端命名规范
3.1 后端(Java / SpringBoot)

下表示例取自 EasyPro 代码库(包名 com.sctech.opti.cloud、资源 DriverInstance 等),命名规范本身适用于所有产品。

对象规范示例
包名com.sctech.opti.cloud.<模块>.<子模块>com.sctech.opti.cloud.modules.iot.driver
Controller<资源>Controller,@RestControllerDriverInstanceController
Service 接口<资源>ServiceDriverInstanceService
Service 实现<资源>ServiceImplDriverInstanceServiceImpl
Mapper<资源>Mapper + 同名 XMLDriverInstanceMapper
实体<资源> 或 <资源>EntityDriverInstance
DTO(入参)<资源>DTO / <操作><资源>DTOSaveDriverInstanceDTO
VO(出参)<资源>VODriverInstanceVO
枚举<语义>EnumDriverTypeEnum
API 路径/api/<模块>/<资源>,小写连字符/api/iot/driver-instance
方法名(Controller)驼峰,动词前缀list / getById / save / update / delete
常量全大写下划线MAX_RETRY_COUNT
一眼能看懂的命名
  • DriverInstanceController — 管理什么+是什么
  • SaveDriverInstanceDTO — 动作+资源+类型
  • DriverTypeEnum — 语义+类型
  • /api/iot/driver-instance — 模块/资源,小写连字符
让人猜的命名
  • Ctrl1 / Manager — 编号/泛称,不知管啥
  • Data / Info / Temp — 无意义后缀
  • UserServiceImpl2 — 靠编号区分实现
  • /api/doSomething — 动词当资源,无模块归属
命名是代码可读性的第一道关,烂命名靠注释也救不回来
3.2 前端(Vue)
对象规范示例
组件文件PascalCaseDriverInstanceList.vue
组件名(注册)PascalCaseDriverInstanceList
路由 pathkebab-case/iot/driver-instance
变量/方法camelCasedriverList / handleSave()
常量UPPER_SNAKE_CASEAPI_BASE_URL
API 请求文件按模块组织,与后端模块对齐api/iot/driverInstance.js
API 函数名与后端方法对齐getDriverInstanceList()
CSS classkebab-case,BEM 可选driver-instance-card

前后端路径必须一致:后端 /api/iot/driver-instance ↔ 前端 api/iot/driverInstance.js,避免命名漂移。

3.3 通用
对象规范示例
数据库表名ibms-<模块>(业务库) / iot_<实体>(物联库),沿用现有ibms-system / iot_driver
字段名snake_caseproject_id / create_time
文件名(文档)<主题>.md,可中文开发规范.md / 驱动开发指南.md
文件名(代码/脚本)英文小写下划线/连字符driver_instance.sql
目录名小写英文,业务文档目录可中文doc/规则/ / sql/release/2.1.1/
2
Swagger / OpenAPI3 接口规范
3.4 Swagger / OpenAPI3 接口规范

本项目使用 springdoc-openapi(OpenAPI 3),接口文档由 @Tag/@Operation/@Schema 等注解描述。规范如下:

注解用法:

@Tag 注解格式拆解
@Tag
注解
(name = "
(iot)
模块前缀
小写英文括号
驱动实例
中文描述
接口分组名
")
正确
@Tag(name = "(system)用户管理")
@Tag(name = "(iot)驱动实例")
@Tag(name = "(energy)能耗报表")
错误
收支对账管理 — 缺 (bill) 前缀
B 端支付订单查询 — 中英混排
(bill) 用户资金密码管理 — 前缀后多空格
注解作用位置规范
@TagController 类接口分组,统一格式 (<模块>)<中文描述>
@OperationController 方法必填 summary(接口功能,中文祈使句)
@SchemaDTO/VO/Entity 字段必填 description;入参 DTO 补 example
@Parameter方法参数(非实体字段)描述 path/query 参数
~~@Api~~ ~~@ApiOperation~~ ~~@ApiModel~~— 已废弃(Swagger2 注解),全量替换为 OpenAPI3 注解

为什么把文档写进注解,而不是单独维护 Word?因为代码和文档一旦分离,就一定会脱节——改了接口忘了改文档,前端按旧文档联调就会踩坑。注解和代码放在一起,改接口时顺手就能改注解,Swagger 自动生成最新文档页面,前端随时可查。这是「单一事实来源」原则:代码即文档。

@Tag 命名格式(统一为现有主流风格,修正不一致项):

JAVA
// [✓] 统一格式:<模块>用小写英文括号,后接中文描述
@Tag(name = "(system)用户管理")
@Tag(name = "(iot)驱动实例")
@Tag(name = "(energy)能耗报表")

// [✗] 不规范(缺模块前缀 / 中英混排 / 大小写不一)
@Tag(name = "收支对账管理")           // 缺 (bill) 前缀
@Tag(name = "B 端支付订单查询")        // 中英混排
@Tag(name = "(bill) 用户资金密码管理") // 前缀后多空格

模块前缀参考:(system) (iot) (energy) (eoms) (bill) (driver) (zw),与 §2.5 scope 对齐。

为什么 @Tag 要带 (模块) 前缀?Swagger 文档按 Tag 分组展示全部接口,一百多个 Controller 若只用中文描述命名,分组就是一堆无法检索的散乱标题;带模块前缀后,接口在文档里按模块聚合、可折叠可搜索。前缀还与提交 scope、模块包名共用同一套词汇——从提交记录到接口文档,一个模块名走遍全链路。

@Operation 与方法:

JAVA
@Operation(summary = "新增驱动实例", description = "可选的详细说明")
@PostMapping
public Result<Void> save(@Validated @RequestBody SaveDriverDTO dto) { ... }

SwaggerConfig 标准写法:

JAVA
@Configuration
public class SwaggerConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                // 统一鉴权:让文档支持带 Authorization 请求调试
                .components(new Components().addSecuritySchemes("Authorization",
                        new SecurityScheme()
                                .type(SecurityScheme.Type.APIKEY)
                                .in(SecurityScheme.In.HEADER)
                                .name("Authorization")))
                .addSecurityItem(new SecurityRequirement().addList("Authorization"))
                .info(new Info()
                        .title("源创云平台")
                        .version("2.0.0")
                        .description("源创云平台在线 API"));
    }
}

统一返回 Result<T>:所有 Controller 返回 com.sctech.opti.cloud.common.core.api.data.Result<T>,结构为 { success, code, msg, data, errorMsg },禁止裸返回实体或 Map。

为什么必须统一返回 Result<T>,而不是直接返回实体或 Map?统一结构后,前端只需要写一套响应解析:先看 success/code,再取 data。裸返回意味着每个接口的出错形态都不一样——有的抛 500、有的返回 null、有的塞在 Map 里,前端没法统一处理,全局异常处理器也无从兜底。返回结构是前后端的「接口契约」,契约只有一种,协作才不会扯皮。

新手常见错误
名字是给别人看的,注解是给文档用的,这两处出错最容易被 review 打回
我给变量起了 UserServiceImpl2,因为已经有个 Impl 了,这样对吗?
不对。接口是 UserService,实现类固定叫 UserServiceImpl(后缀 Impl)。如果需要第二个实现,说明它们代表不同策略,应该用语义命名,比如 UserRdbServiceImpl(关系库实现)和 UserRedisServiceImpl(缓存实现),而不是加数字编号。
我给 Controller 方法加了 @Operation 但没写 summary,会怎样?
接口文档里这个接口会显示成方法名(如 getUserById),前端同事看不出它是干嘛的。summary 是必填的,要用中文祈使句写清楚功能,比如 @Operation(summary = "根据ID查询用户详情")。提交前检查清单第 7 项会检查这个。
我用的是 Swagger2 的 @Api / @ApiOperation,有什么问题?
项目已统一升级到 OpenAPI3注解。@Api→@Tag、@ApiOperation→@Operation、@ApiModel→@Schema。Swagger2 注解已废弃,新代码必须用 OpenAPI3,存量代码遇到时顺手替换。
前端组件名我用了驼峰 myComponent,review 时被要求改?
Vue 组件名用多词短横线(kebab-case),如 user-profile-card,避免和 HTML 原生元素冲突(单词名可能撞 <myComponent> 被当成未知标签)。变量、方法用驼峰(getUserInfo),但组件模板里用短横线。