ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
## java开发规范 >在我们的日常开发过程中好的代码开发规范是必不可少的,下面我们来注意一下具体要注意哪些。 ### **1.类名使用** `UpperCamelCase` **风格** >例如:`ForceCode` `UserDO` `HtmlDTO` `XmlService` `TcpUdpDeal` `TaPromotion` ### **2.方法名、参数名、成员变量、局部变量都统一使用** `lowerCamelCase` **风格。** >例如:`localValue` `getHttpMessage()` `inputUserId` ### **3.常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。** >例如:`MAX_STOCK_COUNT` `CACHE_EXPIRED_TIME` ### **4.抽象类命名使用** `Abstract` **或** `Base` **开头;异常类命名使用** `Exception` **结尾;测试类命名以它要测试的类的名称开始,以** `Test` **结尾。** ### **5.类型与中括号紧挨相连来表示数组。** >定义整形数组 `int[]` `arrayDemo` ### **6.**`POJO` **类中的任何布尔类型的变量,都不要加** `is` **前缀,否则部分框架解析会引起序列化错误。** >例如:在本文 MySQL 规约中的建表约定第一条,表达是与否的值采用 is_xxx 的命名方式,所以,需要在设置从 is_xxx 到 xxx 的映射关系。 ### **7.包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用单数形式,但是类名如果有复数含义,类名可以使用复数形式。** >例如:应用工具类包名为 `com.alibaba.ei.kunlun.aap.util`类名为 `MessageUtils`(此规则参考 `spring` 的框架结构) ### **8.在** `long` **或者** `Long` **赋值时,数值后使用大写的 L,不能是小写的 l,小写容易跟数字混淆,造成误解。** >例如:Long a = 2l; 写的是数字的 21,还是 Long 型的 2。 ### **9.不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。** >例如:大而全的常量类,杂乱无章,使用查找功能才能定位到修改的常量,不利于理解,也不利于维护。 ### **10.如果变量值仅在一个固定范围内变化用** `enum` **类型来定义。** >说明:如果存在名称之外的延伸属性应使用 `enum` 类型,下面正例中的数字就是延伸信息,表示一年中的第几个季节。 ``` public enum SeasonEnum { SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4); private int seq; SeasonEnum(int seq) { this.seq = seq; } public int getSeq() { return seq; } } ``` ### **11.** `IDE` **的** `text file encoding` **设置为** `UTF-8`; `IDE` **中文件的换行符使用** `Unix` **格式,不要使用** `Windows` **格式。** ### **12.任何货币金额,均以最小货币单位且整型类型来进行存储。** ### **13.浮点数之间的等值判断,基本数据类型不能用** `==` **来比较,包装数据类型不能用** `equals` **来判断。** >说明:浮点数采用“尾数+阶码”的编码方式,类似于科学计数法的“有效数字+指数”的表示方式。二进制无法精确表示大部分的十进制小数。 ``` float a = 1.0f - 0.9f; float b = 0.9f - 0.8f; float diff = 1e-6f; if (Math.abs(a - b) < diff) { System.out.println("true"); } ``` ### **14.类成员与方法访问控制从严。** >1) 如果不允许外部直接通过 `new` 来创建对象,那么构造方法必须是 `private`。 >2) 工具类不允许有 `public` 或 `default` 构造方法。 >3) 类非 `static` 成员变量并且与子类共享,必须是 `protected`。 >4) 类非 `static` 成员变量并且仅在本类使用,必须是 `private`。 >5) 类 `static` 成员变量如果仅在本类使用,必须是 `private`。 >6) 若是 `static` 成员变量,考虑是否为 `final`。 >7) 类成员方法只供类内部调用,必须是 `private`。 >8) 类成员方法只对继承类公开,那么限制为 `protected`。 ### **说明:** 任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。思考:如果是一个 `private` 的方法,想删除就删除,可是一个 `public` 的 `service` 成员方法或成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,无限制的到处跑,那么你会担心的。 ### **15.用户敏感数据禁止直接展示,必须对展示数据进行脱敏。** >说明:中国大陆个人手机号码显示为:137****0969,隐藏中间 4 位,防止隐私泄露。 ### **16.用户输入的** `SQL` **参数严格使用参数绑定或者** `METADATA` **字段值限定,防止** `SQL` **注入,禁止字符串拼接** `SQL` **访问数据库。** ### **17.用户请求传入的任何参数必须做有效性验证。** >说明:忽略参数校验可能导致: >1.`page size` 过大导致内存溢出 >2.恶意 `order by` 导致数据库慢查询 >3.缓存击穿 >4.`SSRF` >5.任意重定向 >6.`SQL` 注入,`Shell` 注入,反序列化注入 >7.正则输入源串拒绝服务 `ReDoS` **Java 代码用正则来验证客户端的输入,有些正则写法验证普通用户输入没有问题,但是如果攻击人员使用 的是特殊构造的字符串来验证,有可能导致死循环的结果。** ### **18.禁止向 HTML 页面输出未经安全过滤或未正确转义的用户数据。** ### **19.表单、AJAX 提交必须执行 CSRF 安全验证。** >说明:CSRF(Cross-site request forgery)跨站请求伪造是一类常见编程漏洞。对于存在 CSRF 漏洞的应用/网站,攻击者可以事先构造好 URL,只要受害者用户一访问,后台便在用户不知情的情况下对数据库中用户参数进行相应修改。 ### **20.URL 外部重定向传入的目标地址必须执行白名单过滤。** ### **21.在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放的机制,如数量限制、疲劳度控制、验证码校验,避免被滥刷而导致资损。** >说明:如注册时发送验证码到手机,如果没有限制次数和频率,那么可以利用此功能骚扰到其它用户,并造成短信平台资源浪费。 ### **22.发贴、评论、发送即时消息等用户生成内容的场景必须实现防刷、文本内容违禁词过滤等风控策略。** ### **23.数据库表约定。** 1).表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 >说明:`MySQL` 在 `Windows` 下不区分大小写,但在 `Linux` 下默认是区分大小写。因此,数据库名、表名、字段名,都不允许出现任何大写字母,避免节外生枝。 例如:`aliyun_admin` `rdc_config` `level3_name` 2).表达 `是与否` 概念的字段,必须使用 `is_xxx` 的方式命名,数据类型是 `unsigned tinyint`(1 表示是,0 表示否)。 >说明:任何字段如果为非负数,必须是 `unsigned`。 >注意:POJO 类中的任何布尔类型的变量,都不要加 `is` 前缀,所以,需要在设置从 `is_xxx` 到 `Xxx` 的映射关系。数据库表示是与否的值,使用 `tinyint` 类型,坚持 `is_xxx` 的命名方式是为了明确其取值含义与取值范围。 >例如:表达逻辑删除的字段名 `is_deleted`,1 表示删除,0 表示未删除。 3).主键索引名为 `pk_`字段名;唯一索引名为 `uk_`字段名;普通索引名则为 `idx_`字段名。 >说明:`pk_` 即 `primary key`;`uk_` 即 `unique key`;`idx_` 即 `index` 的简称。 4).小数类型为 `decimal`,禁止使用 `float` 和 `double`。 >说明:在存储的时候,`float` 和 `double` 都存在精度损失的问题,很可能在比较值的时候,得到不正确的结果。如果存储的数据范围超过 `decimal` 的范围,建议将数据拆成整数和小数并分开存储。 5).如果存储的字符串长度几乎相等,使用 `char` 定长字符串类型。 6).`varchar` 是可变长字符串,不预先分配存储空间,长度不要超过 `5000`,如果存储长度大于此值,定义字段类型为 `text`,独立出来一张表,用主键来对应,避免影响其它字段索引效率。 7).表必备三字段:`id` `gmt_create` `gmt_modified`。 说明:其中 `id` 必为主键,类型为 `bigint unsigned` 单表时自增、步长为 `1`。`gmt_create` `gmt_modified`的类型均为 `datetime` 类型,前者现在时表示主动式创建,后者过去分词表示被动式更新。 8).表的命名最好是遵循 `业务名称_表的作用`。 >例如:`alipay_task` `force_project` `trade_config` 9).库名与应用名称尽量一致。 10).如果修改字段含义或对字段表示的状态追加时,需要及时更新字段注释。 11).字段允许适当冗余,以提高查询性能,但必须考虑数据一致。冗余字段应遵循: >1) 不是频繁修改的字段。 >2) 不是唯一索引的字段。 >3) 不是 `varchar` 超长字段,更不能是 `text` 字段。 >说明:各业务线经常冗余存储商品名称,避免查询时需要调用 `IC` 服务获取。 10).单表行数超过 `500` 万行或者单表容量超过 `2GB`,才推荐进行分库分表。 >说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。 11).合适的字符存储长度,不但节约数据库表空间、节约索引存储,更重要的是提升检索速度。 >说明:无符号值可以避免误存负数,且扩大了表示范围。 ### **24.索引规约** 1).业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。 >说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明显的;另外,即使在应用层做了非常完善的校验控制,只要没有唯一索引,根据墨菲定律,必然有脏数据产生。 2).超过三个表禁止 `join`。需要 `join` 的字段,数据类型保持绝对一致;多表关联查询时,保证被关联的字段需要有索引。 >说明:即使双表 `join` 也要注意表索引、`SQL 性能`。 3).在 `varchar` 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据实际文本区分度决定索引长度。 >说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))count(*)的区分度来确定。 4).如果有 `order by` 的场景,请注意利用索引的有序性。`order by` 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 `file_sort` 的情况,影响查询性能。 >说明:where a=? and b=? order by c; 索引:a_b_c 5).利用覆盖索引来进行查询操作,避免回表。 >说明:如果一本书需要知道第 11 章是什么标题,会翻开第 11 章对应的那一页吗?目录浏览一下就好,这个目录就是起到覆盖索引的作用。 >例如:能够建立索引的种类分为主键索引、唯一索引、普通索引三种,而覆盖索引只是一种查询的一种效果,用 `explain` 的结果,`extra` 列会出现:`using index`。 7).利用延迟关联或者子查询优化超多分页场景。 >说明:`MySQL` 并不是跳过 `offset` 行,而是取 `offset+N` 行,然后返回放弃前 `offset` 行,返回 `N` 行,那当 `offset` 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL改写。 >正例:先快速定位需要获取的 id 段,然后再关联: ``` SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id ``` 8).`SQL` 性能优化的目标:至少要达到 `range` 级别,要求是 `ref` 级别,如果可以是 `consts` 最好。 >1) `consts` 单表中最多只有一个匹配行(主键或者唯一索引),在优化阶段即可读取到数据。 >2) `ref` 指的是使用普通的索引`(normal index)`。 >3) `range` 对索引进行范围检索。 9).建组合索引的时候,区分度最高的在最左边。 >例如:如果 where a=? and b=?,a 列的几乎接近于唯一值,那么只需要单建 idx_a 索引即可。 ### **25.不得使用外键与级联,一切外键概念必须在应用层解决。** >说明:(概念解释)学生表中的 `student_id` 是主键,那么成绩表中的 `student_id` 则为外键。如果更新学生表中的 `student_id`,同时触发成绩表中的 `student_id` 更新,即为级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。 ### **26.禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。** ### **27.数据订正(特别是删除或修改记录操作)时,要先 select,避免出现误删除,确认无误才能执行更新语句。** ### **28.在表查询中,一律不要使用** `*` **作为查询的字段列表,需要哪些字段必须明确写明。** >1)增加查询分析器解析成本。 >2)增减字段容易与 `resultMap` 配置不一致。 >3)无用字段增加网络消耗,尤其是 `text` 类型的字段。