Files

195 lines
12 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 阿里巴巴Java开发手册 - Cursor规则
本项目遵循《阿里巴巴Java开发手册(黄山版)》的编码规范。以下规则将指导AI助手在编写、审查和重构Java代码时的行为。
## 一、编程规约
### 命名风格
- **类名**:使用 UpperCamelCase 风格(如:UserService, OrderDTO
- **方法名、参数名、变量名**:使用 lowerCamelCase 风格(如:getUserInfo, userName
- **常量名**:全部大写,单词间用下划线隔开(如:MAX_STOCK_COUNT
- **抽象类**:使用 Abstract 或 Base 开头
- **异常类**:使用 Exception 结尾
- **测试类**:以要测试的类名开始,以 Test 结尾
- **数组定义**:类型与中括号紧挨相连(如:int[] arrayDemo
- **包名**:统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词
- **禁止**:命名不能以下划线或美元符号开始/结束;禁止使用拼音与英文混合;禁止使用中文命名
- **禁止**:代码和注释中避免使用种族歧视性或侮辱性词语
### 常量定义
- **禁止魔法值**:不允许任何未经预先定义的常量直接出现在代码中
- **Long类型**:数值后使用大写 L(如:2L),不能是小写 l
- **浮点数**:数值后缀统一为大写的 D 或 F(如:175.5D, 150.3F
- **常量分类**:按功能归类,分开维护,不要使用一个常量类维护所有常量
### 代码格式
- **缩进**:采用 4 个空格缩进,禁止使用 Tab 字符
- **大括号**:左大括号前不换行,左大括号后换行;右大括号前换行
- **单行字符数**:限制不超过 120 个,超出需要换行
- **方法行数**:单个方法的总行数不超过 80 行
- **空行**:不同逻辑、不同语义、不同业务的代码之间插入一个空行
### OOP规约
- **静态访问**:避免通过对象引用访问静态变量或静态方法,直接用类名访问
- **覆写方法**:所有的覆写方法,必须加 @Override 注解
- **可变参数**:相同参数类型、相同业务含义才可使用可变参数,参数类型避免定义为 Object
- **equals方法**:使用常量或确定有值的对象来调用 equals,避免空指针异常
- **整型包装类**:所有整型包装类对象之间值的比较,全部使用 equals 方法比较
- **浮点数比较**:基本数据类型不能使用 == 进行比较,包装数据类型不能使用 equals 进行判断
- **BigDecimal**:等值比较应使用 compareTo() 方法,而不是 equals() 方法
- **POJO类**:属性必须使用包装数据类型;必须写 toString 方法;不要设定任何属性默认值
- **构造方法**:禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中
### 集合处理
- **hashCode和equals**:只要覆写 equals,就必须覆写 hashCode
- **集合判空**:使用 isEmpty() 方法,而不是 size() == 0
- **Stream toMap**:使用 toMap() 方法时,必须使用 mergeFunction 参数处理重复 key
- **foreach循环**:不要在 foreach 循环里进行元素的 remove/add 操作,使用 iterator 方式
- **集合转数组**:必须使用集合的 toArray(T[] array),传入类型完全一致、长度为 0 的空数组
### 并发处理
- **单例对象**:获取单例对象需要保证线程安全,其中的方法也要保证线程安全
- **线程池**:线程资源必须通过线程池提供,不允许在应用中自行显式创建线程
- **线程池创建**:不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式
- **SimpleDateFormat**:是线程不安全的类,一般不要定义为 static 变量
- **ThreadLocal**:必须回收自定义的 ThreadLocal 变量记录的当前线程的值
- **锁的使用**:能用无锁数据结构就不要用锁;能锁区块就不要锁整个方法体;能用对象锁就不要用类锁
- **死锁预防**:对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序
## 二、异常日志
### 错误码
- **错误码格式**:字符串类型,共 5 位,分成两个部分:错误产生来源 + 四位数字编号
- **错误来源**:A 表示用户端错误,B 表示系统执行出错,C 表示调用第三方服务出错
- **全部正常**:返回五个零:00000
- **禁止**:错误码不能直接输出给用户作为提示信息使用
### 异常处理
- **RuntimeException**:可以通过预检查方式规避的 RuntimeException 不应该通过 catch 来处理
- **异常控制流**:异常捕获后不要用来做流程控制、条件控制
- **异常分类**:catch 时请分清稳定代码和非稳定代码,尽可能进行区分异常类型
- **异常处理**:捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之
- **事务回滚**:事务场景中,抛出异常被 catch 后,如果需要回滚,一定要注意手动回滚事务
- **资源关闭**:finally 块必须对资源对象、流对象进行关闭,有异常也要做 try-catch
- **finally return**:不要在 finally 块中使用 return
- **异常匹配**:捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类
- **RPC异常**:在调用 RPC、二方包、或动态生成类的相关方法时,捕捉异常使用 Throwable 类进行拦截
### 日志规约
- **日志框架**:应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架(SLF4J、JCL)中的 API
- **日志保存**:日志文件至少保存 15 天
- **日志拼接**:字符串变量之间的拼接使用占位符的方式
- **日志级别判断**:对于 trace/debug/info 级别的日志输出,必须进行日志级别的开关判断
- **禁止**:生产环境禁止使用 System.out 或 System.err 输出或使用 e.printStackTrace() 打印异常堆栈
- **异常信息**:异常信息应该包括两类信息:案发现场信息和异常堆栈信息
## 三、单元测试
- **AIR原则**:好的单元测试必须遵守 AIR 原则(Automatic、Independent、Repeatable
- **自动化执行**:单元测试应该是全自动执行的,并且非交互式的
- **独立性**:保持单元测试的独立性,单元测试用例之间决不能互相调用
- **可重复执行**:单元测试是可以重复执行的,不能受到外界环境的影响
- **测试粒度**:要保证测试粒度足够小,有助于精确定位问题,单测粒度至多是类级别,一般是方法级别
- **测试目录**:单元测试代码必须写在 src/test/java,不允许写在业务代码目录下
## 四、安全规约
- **权限控制**:隶属于用户个人的页面或者功能必须进行权限控制校验
- **数据脱敏**:用户敏感数据禁止直接展示,必须对展示数据进行脱敏
- **SQL注入**:用户输入的 SQL 参数严格使用参数绑定或者 METADATA 字段值限定,防止 SQL 注入,禁止字符串拼接 SQL
- **参数验证**:用户请求传入的任何参数必须做有效性验证
- **XSS防护**:禁止向 HTML 页面输出未经安全过滤或未正确转义的用户数据
- **CSRF防护**:表单、AJAX 提交必须执行 CSRF 安全验证
- **URL重定向**:URL 外部重定向传入的目标地址必须执行白名单过滤
- **防重放**:使用平台资源(短信、邮件、电话、下单、支付)必须实现正确的防重放的机制
- **文件上传**:对于文件上传功能,需要对于文件大小、类型进行严格检查和控制
- **密码加密**:配置文件中的密码需要加密
## 五、MySQL数据库
### 建表规约
- **布尔字段**:表达是与否概念的字段,必须使用 is_xxx 的方式命名,数据类型是 unsigned tinyint
- **表名字段名**:必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字
- **表名**:不使用复数名词
- **保留字**:禁用保留字,如 desc、range、match、delayed 等
- **索引命名**:主键索引名为 pk_字段名;唯一索引名为 uk_字段名;普通索引名则为 idx_字段名
- **小数类型**:为 decimal,禁止使用 float 和 double
- **必备字段**:表必备三字段:idcreate_timeupdate_time
- **逻辑删除**:在数据库中不能使用物理删除操作,要使用逻辑删除
### 索引规约
- **唯一索引**:业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引
- **JOIN限制**:超过三个表禁止 join
- **索引长度**:在 varchar 字段上建立索引时,必须指定索引长度
- **模糊查询**:页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决
### SQL语句
- **count使用**:不要使用 count(列名) 或 count(常量) 来替代 count(*)
- **NULL判断**:使用 ISNULL() 来判断是否为 NULL 值
- **外键级联**:不得使用外键与级联,一切外键概念必须在应用层解决
- **存储过程**:禁止使用存储过程
- **表别名**:对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名进行限定
### ORM映射
- **字段列表**:在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明
- **布尔属性映射**:POJO 类的布尔属性不能加 is,而数据库字段必须加 is_,要求在 resultMap 中进行字段与属性之间的映射
- **resultMap**:不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需要定义 resultMap
- **参数绑定**sql.xml 配置参数使用:#{}#param# 不要使用 ${} 此种方式容易出现 SQL 注入
- **更新时间**:更新数据表记录时,必须同时更新记录对应的 update_time 字段值为当前时间
## 六、工程结构
### 应用分层
- **分层结构**:开放 API 层、终端显示层、Web 层、Service 层、Manager 层、DAO 层、第三方服务、外部数据接口
- **领域模型**
- DOData Object):与数据库表结构一一对应
- DTOData Transfer Object):数据传输对象
- BOBusiness Object):业务对象
- Query:数据查询对象
- VOView Object):显示层对象
### 二方库依赖
- **GAV规则**:定义 GAV 遵从 com.{公司/BU}.业务线.[子业务线] 格式
- **版本号**:主版本号.次版本号.修订号,注意起始版本号必须为:1.0.0
- **SNAPSHOT**:线上应用不要依赖 SNAPSHOT 版本(安全包除外)
## 七、设计规约
- **存储方案**:存储方案和底层数据结构的设计获得评审一致通过,并沉淀成为文档
- **用例图**:如果与系统交互的 User 超过一类并且相关的 UseCase 超过 5 个,使用用例图来表达
- **状态图**:如果某个业务对象的状态超过 3 个,使用状态图来表达
- **时序图**:如果系统中某个功能的调用链路上的涉及对象超过 3 个,使用时序图来表达
- **类图**:如果系统中模型类超过 5 个,且存在复杂的依赖关系,使用类图来表达
- **弱依赖**:系统设计时要准确识别出弱依赖,并针对性地设计降级和应急预案
- **单一原则**:类在设计与实现时要符合单一原则
- **继承谨慎**:谨慎使用继承的方式来进行扩展,优先使用聚合/组合的方式来实现
- **依赖倒置**:根据依赖倒置原则,尽量依赖抽象类与接口,有利于扩展与维护
## 使用说明
当编写、审查或重构Java代码时,请严格遵循以上规则。这些规则基于《阿里巴巴Java开发手册(黄山版)》,是Java社区集体智慧的结晶。
**规约分类说明:**
- **【强制】**:必须严格遵守,违反可能导致严重问题
- **【推荐】**:建议遵循,有助于提升代码质量
- **参考**:参考性建议,可根据实际情况选择
**版本信息:**
- 版本:黄山版(1.7.1
- 更新日期:2022.02.03