本文共 4782 字,大约阅读时间需要 15 分钟。
类名使用 UpperCamelCase 风格,但 DO / BO / DTO / VO / AO / PO / UID 除外,使用 UserDO 而非 UserDo,常量命名全部大写,单词间用下划线隔开;
抽象类命名使用 Abstract 或 Base 开头,异常类命名使用 Exception 结尾,测试类命名,以要测试的类名称开始,以 Test 结尾,如果模块、接口、类、方法使用了设计模式,在命名时需体现出具体模式;
POJO 类中布尔类型的变量,都不要加 is 前缀,避免部分框架解析时,is 造成的序列化错误;
包名统一使用小写,点分隔符之间,有且仅有一个英语单词;
Service / DAO 层方法命名规约;
获取单个对象的方法,使用 get 前缀 获取多个对象的方法,使用 list 前缀,复数形式结尾,如 listObjects 获取统计值的方法,使用 count 做前缀 插入的方法,使用 save/insert 做前缀 删除的方法,使用 remove/delete 做前缀 修改的方法,使用 update 做前缀
数据对象:xxxDO,xxx 为数据表名 数据传输对象:xxxDTO,xxx 为业务领域相关的名称 展示对象:xxxVO,xxx 为网页名称 POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO
左,右小括号,和字符之间不出现空格,左大括号前需要空格, if / for / while / switch / do 等保留字与括号之间都必须加空格;
任何赋值运算符 =,逻辑运算符 &&,加减乘除等运算符,左右两边都需要加一个空格;
注释的双斜线与注释内容之间,有且仅有一个空格,方法参数在定义和传入时,多个参数逗号后边必须加空格;
public static void main(String[] args) { // 缩进 4 个空格 String say = "hello"; // 运算符的左右必须有一个空格 int flag = 0; // 关键词 if 与括号之间必须有一个空格,括号内的 f 与左括号,0 与右括号不需要空格 // 左大括号前加空格且不换行,左大括号后换行 if (flag == 0) { System.out.println(say); // 右大括号前换行,右大括号后有 else,不用换行 } }
包装类对象的值比较,使用 equals 方法,其实 Integer 在-128 至 127 范围内,是会缓存在 IntegerCache.cache,这个区间内是可以直接使用 == 比较, 但是该区间外,使用双等,结果是不相等, 所以建议统一使用 equals 方法进行比较;
重写 equals,就必须重写 hashCode,因为 Set / HashMap 存储的不重复的对象,是依据 hashCode 和 equals 联合进行判断的;
基本数据类型和包装数据类型,包装类型的 null,可以表示除 0 以外的意义,如调用失败等;
所有的 POJO 类属性,必须使用包装数据类型 RPC 方法的返回值和参数,必须使用包装数据类型。 所有的局部变量使用基本数据类型
定义 POJO 类时,不要设定任何属性默认值,序列化类,新增属性时,请不要修改 serialVersionUID 字段;
POJO 类必须重写 toString 方法,推荐使用 IDE 中工具生成,如果继承另一个 POJO 类,注意添加 super.toString;
使用String 的 split 方法时,需要检查,最后一个分隔符后有无内容,否则会有抛 IndexOutOfBoundsException 的风险;
String str = "a,b,c,,"; String[] ary = str.split(","); // 预期大于 3,结果是 3,a b c,匹配的空白将被丢弃,空字符串不会被丢弃 System.out.println(ary.length); str = "a,b,c, , "; // 结果就是 5, a b c和两个空格字符串
集合转数组,使用 toArray(T[] array),传入的是类型,大小完全一样的数组,而不使用无参的 toArray();
Arrays.asList() 方法,将数组转换成集合,无法使用修改方法 add / remove / clear ,会抛出异常;
泛型通配符 <? extends T>,接收返回的数据时,不能使用 add 方法,泛型通配符 <? super T>,不能使用 get 方法;
不要在 foreach 循环里,操作 remove/add ,如果需要使用 Iterator,并发操作时,需要对 Iterator 对象加锁;
集合初始化时,指定集合初始值大小为 initialCapacity = (需要存储的元素个数 / 负载因子) + 1;
TreeMap 的 key 不允许为 null, value 允许为 null, HashMap key 允许为 null , value 允许为 null,set 类似;
利用 Set 元素唯一的特性,可以快速对集合进行去重操作,避免使用 List 的 contains 方法进行遍历、对比、去重操作;
线程池不允许使用 Executors 创建,而通过 ThreadPoolExecutor 创建;
SimpleDateFormat 是非线程安全的类,建议使用 ThreadLocal 封装,在 JDK 8 中,使用 DateTimeFormatter 代替 SimpleDateFormat,使用 Instant 代替 Date,LocalDateTime 代替 Calendar;
隔离级别,非串行化,只能解决第一类更新丢失,回滚丢失的问题,而无法解决第二类更新丢失,所以并发修改同一记录时,避免更新丢失,需要加锁。应用层加锁,或者缓存加锁,或者数据库层使用乐观锁,或悲观锁,如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数一般大于 3 次;
?? 可重复读,可以解决更新丢失吗 ??JDK7 之后,并发场景,使用随机数 ThreadLocalRandom;
单例模式,双重检查锁模型,有缺陷,推荐通过将目标属性,声明为 volatile 解决;
switch 语句,每个 case 通过 break/return 来终止,或者注释说明,程序执行到哪一个 case 为止,且要求必须包含一个 default 语句放在最后,即使空代码;
高并发场景下,避免使用 == 判断,作为中断或退出的条件,改用 >,< 的区间判断;
条件判断中,避免使用 ! 逻辑运算符,异常,也不要用来做流程控制,能提前检查的异常,提前检查,而不是使用 try-catch;
处理 NPE,注意 NPE 产生的场景,可以使用 JDK 8 的 Optional 来防止 NPE;
基本数据类型,自动拆箱有可能产生 NPE 数据库的查询结果可能为 null 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null 远程调用返回对象时,一律要求进行空指针判断,防止 NPE Session 中获取的数据,建议 NPE 检查,避免空指针 级联调用 obj.getA().getB().getC() 时,易产生 NPE。
避免重复打印日志,浪费磁盘空间,在 log4j.xml 中设置 additivity=false;
表单、AJAX 提交必须执行 CSRF 安全验证;
数组库字段,表达是与否概念,必须使用 is_xxx 命名,数据类型是 unsigned tinyint,但 POJO 中禁止 is开头,所以,需要在 resultMap 中,设置从 is_xxx 到 xxx 的映射关系;
任何字段,如果为非负数,必须是 unsigned,数据库名,表名,字段名,都不允许出现大写字母;
主键索引,命名 pk_字段名,唯一索引,命名 uk_字段名,普通索引,命名 idx_字段名;
如果存储的字符串,长度几乎相等,建议使用 char 定长字符串类型;
单表行数超过 500 万行,或者容量超过 2GB,才推荐进行分库分表;
tinyInt,smallint,int,bigint,分别是 1,2,4,8个字节;
业务上具有唯一特性的字段,即使是多个字段的组合,也必须建成唯一索引,构成数据库约束,索引影响了 insert 速度,这个损耗几乎可以忽略;
超过三个表禁止 join,需要 join 的字段,数据类型必须绝对一致,多表关联查询时,保证被关联的字段有索引;
在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引;
如果有 order by 的场景,注意利用索引的有序性;
MySQL 分页,limit offset n,并不会跳过 offset 行,而是先取 offset+n 行,返回时,放弃前 offset 行,返回 n 行,这种方式效率低,建议分页,先获取上一页分页字段的最大值,通过 where 条件,来获取下一页数据;
SQL 性能优化的目标,至少要达到 range 级别;
不要使用 count(列名) 或 count(常量)来替代 count(),count() 会统计值为 null 的行,而 count(列名) 不会统计列值为 null 的行,如果 col1 的值全是 null,sum(col) 返回结果为 null,count(distinct col1, col2) 或者 count(distinct col2, col1),无论另一列有不同的值,也返回为 0;
使用 ISNULL() 来判断是否为 null 值,注意 null 与任何值比较都为 null;
不得使用外键,外键概念在应用层解决;
in 操作尽量避免,如果使用,需要评估 in 的集合元素数量,控制在 1000 个之内;
sql.xml 中配置参数,使用 #{},#param#,不要使用 ${},容易出现 SQL 注入;
maven 坐标,GroupID 格式,com.{公司 / BU }.业务线 [.子业务线],最多 4 级,ArtifactID 格式,产品线名-模块名;
高并发服务器,建议调小 tcp 协议的超时时间 time_wait,linux 上通过修改 /etc/sysctl.conf 文件来变更,缺省值 240 秒后,才会关闭处于 time_wait 状态的连接,这在高并发访问下,可能导致无法建立新的连接,建议调小此等待值;
net.ipv4.tcp_fin_timeout = 30
调大服务器所支持的最大文件句柄数,主流操作系统,将一个 TCP/UDP 连接对应一个文件句柄,linux中默认支持最大文件句柄 1024,所以在高并发下,可能出现文件句柄不足,即 open too many files 的错误,建议调高数倍,具体值和内存相关;
JVM 参数设置 -XX:+HeapDumpOnOutOfMemoryError,使得 OOM 时输出 dump 信息,且 Xms 和 Xmx 设置一样大小,避免 GC 后调整堆大小,带来的压力;
转载地址:http://asfin.baihongyu.com/