阿里巴巴Java编程规范考试
今天在阿里云官网把阿里巴巴Java编程规范认证考试考过了, 写下这篇文章总结一下考试中需要注意的知识点, 主体内容还是要直接看规范:
- 编程规约
- 异常日志
- 单元测试
- 安全规约
- MySQL数据库
- 工程结构
编程规约
- 类名使用UpperCamelCase风格, 但以下情形例外: DO / BO / DTO / VO / AO / PO 等, 如UserDO等。在阿里巴巴Java编程规范中POJO(Plain Ordinary Java Object)专指只有setter / getter / toString 的简单类, 包括DO / BO / DTO / VO 等, 禁止命名成xxxPOJO。
- 定义DO / DTO / VO 等POJO类时, 不要设定任何属性默认值。
- 定义数组: 类型与中括号紧挨相连来定义, 如int[] arrayDemo, 不能使用“String args[]”这种方式。
- 包名统一使用小写, 单数形式; 类名如果有复数含义,可以使用复数形式;例如:包名com.alibaba.ai.util, l类名MessageUtils。
- 任何二目、三目运算符的左右两边都需要加一个空格, 注意一目运算++ 是不需要加空格的。
- 单行字符数限制不超过120个, 单个方法的总行数不超过80行。
- 序列化类新增属性时, 请不要修改serialVersionUID字段, 避免反序列化失败; 如果完全不兼容升级, 避免反序列化混乱, 那么请修改serialVersionUID值。
- 慎用Object的clone方法/BeanUtil的copy方法来拷贝对象, 若想实现深拷贝需要重写clone方法实现属性对象的拷贝。
- ArrayList的subList的类型是java.util.RandomAccessSubList, 是ArrayList的一个视图, 不能强转成ArrayList; 对于SubList子列表的所有操作最终会反映到原列表上; 对原列表的修改, 会导致子列表的遍历、增加、删除均会产生ConcurrentModificationException异常; 同时, subList没有实现Serializable接口, 若RPC接口的List类型参数接受了SubList类型的实参,则在RPC调用时会报出序列化异常。比如我们常用的guava中的Lists.partition,切分后的子list实际都是SubList类型,在传给RPC接口之前,需要用new ArrayList()包一层,否则会报序列化异常。
- 使用集合转数组的方法, 必须使用集合的toArray(T[] array), 传入的是类型完全一样的数组, 大小就是list.size()。
- 方法内部, 抛出异常实例对象为throw; 方法签名中, 抛给调用者的关键字为throws。
- 注意checked/unchecked异常, 见下图Java 异常类层次结构, unchecked异常包括Error、RuntimeException, checked异常必须被显式地捕获或者传递。
- Hashtable/ConcurrentHashMap的K/V都不允许为null, HashMap的K/V都允许为null, TreeMap的K不允许为null、V允许为null。
- FixedThreadPool和SingleThreadPool允许的请求队列长度为Integer.MAX.VALUE, 可能会堆积大量的请求, 从而导致OOM; CachedThreadPool和ScheduledThreadPool允许的创建线程数量为Integer.MAX.VALUE, 可能会创建大量的线程, 从而导致OOM。
- 不要在视图模板中(vm)中加入变量声明, 逻辑运算符, 更不要在vm中加入任何复杂的逻辑, 视图的职责是展示, 不要抢模型和控制器的活。
异常日志
- 应用中不可直接使用日志系统(Log4j、Logback)中的API, 而应使用门面模式的日志框架(SLF4J、JCL)。
- 对trace/debug/info级别的日志输出, 必须使用条件输出形式或者使用占位符的方式。
单元测试
- 好的单元测试必须遵守AIR原则: A->Automatic(自动化), I->Independent(独立性), R->Repeatable(可重复)。
- 编写单元测试代码遵守BCDE原则, 以保证被测试模块的交付质量: B->Border 边界测试; C->Correct 正确的输入, 预期的结果; D->Design 与设计文档相结合, 来编写单元测试; E->Error 强制错误信息输入, 预期的结果。
- 语句覆盖是最弱的一种度量方式; 即使是路径覆盖也不能保证程序完全没问题; 条件覆盖率!=分支覆盖率; 条件覆盖, if里面的每个判断条件, 如if(A && B), 当A/B为true/false、false/true时该语句的条件覆盖率100%; 分支覆盖, if逻辑/没走if逻辑, 当A/B为true/true、false/true时分支覆盖率100%。
安全规约
- 水平权限漏洞一般出现在一个用户对象关联多个其他对象(订单、地址等)、并且要实现对关联对象的CRUD的时候。开发容易习惯性的在生成CRUD表单(或AJAX请求)的时候根据认证过的用户身份来找出其有权限的被操作对象id,提供入口,然后让用户提交请求,并根据这个id来操作相关对象。在处理CRUD请求时,往往默认只有有权限的用户才能得到入口,进而才能操作相关对象,因此就不再校验权限了。可悲剧的是大多数对象的ID都被设置为自增整型,所以攻击者只要对相关id加1、减1、直至遍历,就可以操作其他用户所关联的对象了。
- Web应用必须正确配置 Robots文件,非 SEO URL必须配置为禁止爬虫访问。SEO-Search Engine Optimization。
MySQL数据库
- 如果存储的字符串长度几乎相等, 使用char定长字符串类型
- varchar是可变长字符串, 长度不要超过5000, 如果存储长度大于此值, 定义字段类型为text, 独立出来一张表, 用主键来对应。
- 字段允许适当冗余, 以提高查询性能, 但必须考虑数据一致。冗余字段应遵循:不是频繁修改的字段、不是varchar超长字段、更不能是text字段。
- 表的命名最好是加上“业务名称_表的作用”。
- 表必备三字段:id, gmt_create, gmt_modified。
- 需要join的字段, 数据类型必须绝对一致; 多表关联查询时, 保证被关联的字段需要有索引; 超过三个表禁止join。
- varchar字段上建立索引时, 必须指定索引长度。
- 页面搜索严禁左模糊或者全模糊, 如果需要请走搜索引擎来解决。
- 索引中有范围查找, 那么索引有序性无法利用, 如: WHERE a > 10 ORDER BY b, WHERE a IN(1, 2, 3) ORDER BY b, 则索引a_b无法排序; 如果在WHERE和ORDER BY的栏位上应用表达式(函数)时,则无法利用索引来实现order by的优化。
- WHERE条件列可以不按照索引定义的顺序出现,只要出现的索引列在索引定义顺序的列上能连起来就行,但是order by列不同,出现顺序一定得按照索引定义的顺序,否则无法使用索引进行排序; order by子句和查找型查询的限制是一样的,需要满足索引的最左前缀的要求,否则mysql都需要执行排序操作,而无法使用索引排序。
- 建组合索引的时候, 区分度最高的在最左边, 如WHERE a=? and b=?, 当a列值几乎接近于唯一 , 那么只需要单建idx_a索引即可; 建索引时, 请把等号条件的列前置, 如WHERE a>? and b=? 那么即使a的区分度更高, 也必须把b放在索引的最前列。
- MySQL涉及的索引从数据结构角度来看涉及到B-Tree、Hash、R-Tree、Full-text, 从物理存储角度, 聚集索引(clustered)、非聚集索引(non-clustered); 聚簇索引(Clustered Indexes),主键就是聚集索引。
- 聚簇索引保证关键字的值相近的元组存储的物理位置也相同(所以字符串类型不宜建立聚簇索引,特别是随机字符串,会使得系统进行大量的移动操作),且一个表只能有一个聚簇索引。
- MySQL中, InnoDB引擎表是(聚集)索引组织表, 而MylSAM引擎表则是堆组织表。
- 二级索引又称辅助索引、非聚集索引(no-clustered index)。然而二级索引的叶子节点不保存记录中的所有列,其叶子节点保存的是<健值,(记录)地址>。好似聚集索引中非叶子节点保存的信息(叶子节点保存的数据本身),不同的是二级索引保存的是记录地址,而聚集索引保存的是下一层节点地址。
- 当一列的值全是NULL时, count(col)的返回结果为0, 但sum(col)的返回结果为NULL, 因此使用sum()时需要注意NPE问题。
- NULL与任何值的直接比较都为NULL。
- iBATIS自带的queryForList(String statementName, int start, int size)不推荐使用, 其实现方式是在数据库取到statementName对应的SQL语句的所有记录, 再通过subList取start, size的集合。
工程结构
- GAV: GroupID->com.{公司/BU}.业务线.[子业务线], 最多4级; ArtifactID->产品线名-模块名; Version->主版本号.次版本号.修订号。
- 线上应用不要依赖SNAPSHOT版本(安全包除外)。不依赖SNAPSHOT版本是保证应用发布的幂等性, 另外, 也可以加快编译时的打包构建。
- dependency:resolve 打印出已解决依赖列表, dependency:tree 打印层级依赖关系, 可以用excludes排除jar包。
- 二方库里可以定义枚举类型, 参数可以使用枚举类型, 但是接口返回值不允许使用枚举类型或者包含枚举类型的POJO对象, 会有反序列化的问题。
如果本文档有什么错误, 欢迎大家指出。
原文地址:https://blog.csdn.net/maomaotracy/article/details/80786610