1.所有的局部变量都使用基本数据类型进行定义
2.对象的基本概念
2.1 VO:view Object用于展示层使用的对象模型
2.2 DTO:Data Transfer object数据传输对象
2.3 DO:Domain Object现实世界中抽象出来的有形或者无形的业务实体
3.实现序列化接口的时候,不修改ServialVersionUID的字段内容
4.字符串规范:当需要使用for循环拓展字符串长度的时候,优先使用StringBuilder,可以减少大量的内存损耗
5.实体类的setter方法不能被重写
6.ArrayList中的subList方法返回的是ArrayLsit中的内部类,所以此时不能将subList方法的返回值使用ArrayList来进行接收,会出现ClassCastException(备注:未知类型尽量不要进行强转)
7.集合的toArray方法,返回值是一个Object[],所以不能任意强转成为已知类型的数组,需要使用泛型定义该集合,并且集合长度就是该数组的长度,此时才能正常进行转换
8.数组Array.asList方法只是把格式改成了集合的形式,本质上依旧是数组,不能使用集合的增加或者删除等方法
9.集合进行初始化的时候要初始化容量,因为集合的加载因子默认情况下是0.75,假若没有指定,一味的加入元素,会导致Map不断resize,此时需要重新创建hash表,严重影响了性能
10.注意在Hashtable/ConcurrentHashMap,TreeMap/HashMap,这四种集合当中,只有HashMap的key值允许为Null,其他的情况要慎用,HashTable和ConcurrentHashMap都是线程安全的,ConcurrentHashMap使用了锁分段技术,所以相对来说,相同时间内可以比HashTable处理更多的数据
11.利用Set的唯一特性可以快速的对集合去重,尽量不要使用List中的contains来进行比较
12.并发编程处理
12.1 创建线程或线程池的时候需要制定有意义的线程名称,方便出错的时候进行回测
12.2 线程资源都必须通过线程池进行提供,不允许在应用中自行显示创建线程
12.3 线程池不允许使用Executor去创建,而是通过ThreadPoolExcutor的方式
12.4 在FixThreadPool和SingleThreadPool如果配置了允许请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,最终导致了OOM的结果,相同的CachedThreadPool和ScheduledPool允许创建线程数量为Integer.MAX_VALUE,此时就会出现大量线程,从而导致OOM
结论:如果要解决OOM问题,可以在线程队列和线程缓存当中配置,允许的创建最大的线程数量和线程请求的队列最长的长度
- 12.5 SimpleDateFormat是线程不安全的,如果需要初始化格式一般不要把它定义为静态的,必须要加锁,或者使用DateUtils
处理方式:
private static final ThreadLocal df = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
从jdk1.8开始可以开始使用Instant代理Date,使用LocalDateTime代替Calendar,使用DateTimeFormarter代替SimpleDateFormat,相对来说这些是更加线程安全的类
12.6 高并发的时候,锁的机制要尽量的小,能用区块锁就不用方法锁能用方法锁就不要用类锁,能用无所的就不要用有锁的集合
扫描二维码关注公众号,回复: 6461213 查看本文章12.7 对于多个资源,数据库表,对象同时进行加锁的嘶吼,需要保持一致的加锁顺序,否则就会导致死锁的发生
12.8 并发修改统一记录的时候避免脏读,所以要尽量使用锁机制,应用层加lock或者sychroinzed,缓存加锁,或者是使用乐观锁version
12.9 在并发场景下,通过使用double-checked
locking实现延迟初始化的优化问题隐患
- 使用HashMap是在容量不够的时候进行resize时由于高并发肯能出现死链,导致CPU飙升,在开发过程中可以使用其他数据结构或者加锁来规避此类风险
13.控制语句规范
13.1 switch语句必须要有一个default语句放在最后,即便在这一行什么代码都没有
13.2 尽量不要过多的使用if-else if– else这样的情况,最多尽可能不要超过3层,可以多使用if+retur的情况
13.3 当if语句的判定条件过长的时候,那就需要使用一个final修饰的boolean来进行接收对应的判断条件
13.4 循环体内尽量不要使用try-catch
14.其它备注
14.1 Math.random()方法返回的是double类型,并且取值范围是0到1,可以取到0值的情况,所以需要避免取到了0值的问题
14.2 取整数随机数可以使用Ramdom对象中的nextInt或者是nextLong的方法
14.3 根据MVC理论,不要子啊视图模板中加入任何复杂的逻辑,(但有些判断情况若后端难以处理,还是可以交给前端进行处理)
14.4 Try-catch-finally需要对资源对象进行关闭,流对象进行关闭,在jdk1.7开始,就可以使用try-with-resource的方式来进行了
14.5 NPE问题就是空指针异常的问题
15.防止NPE问题的基本办法
15.1 返回Integer对象,但是接收类型是int,那么此时在进行过自动解箱的时候回抛出NPE
15.2 数据库的查询结果肯能唯爱null的时候,返回的结果也可能为空指针
15.3 集合的元素及时isNotEmpty,取出的数据元素也可能为null
15.4 远程调用返回对象的时候,一律要做非空判断
15.5 从Session中获取的数据时长会有一些位置的因素导致为空,所以需要非空检查
15.6 级联调用容易产生NPE,例如:obj.getA()..getB().getC()
使用JDK8中的Optional类来进行防治NPE问题,可以使用ofNullable().orElse的方式来进行判定方法如果需要的返回值为空的时候可以返回orElse方法中的参数作为默认值
16.尽量避免出现重复代码(Don’t Repeat Yourself),即是DRY原则
17.日志记录相关
17.1 不可直接使用日志系统(Log4j,Logback)中的API,而应该以来使用日志框架SLF4中的API
17.2 日志记录最低15天
17.3 为了避免重复打印日志而浪费内存,如果使用了log4j.xml中需要设计additivity=false
17.4 使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时无所适从
18.单元测试
-
18.1 好的单元测试必须遵守AIR原则,单元测试哈哈在线上运行的时候,感觉要像空气一样,并不存在,但在测试质量的保障上,确实非常关键的
A:Automatic(自动化)
I:Independent(独立性)
R:Repeatable(可重复)
18.2 单元测试应该是要可以完全自动化执行的,保持单元测试的独立性
18.3 单元测试当中要保证测试的粒度是足够小的
-
18.4 单元测试的代码要符合BCDE的原则
B:border,边界值测试,包括循环边界,特殊取值,特殊时间点,数据顺序等
C:Correct,正确的输入,并且得到预期的结果
D:Design,与设计文档相结合,来编写对应的单元测试
E:Error,强制错误信息输入,非法数据,异常流程,非业务允许输入等的测试,并且得到对应的预期结果
18.5 测试删除一行数据之前应该是先执行导入数据或者程序导入的方式来进行执行的,不能在数据库当中进行手动操作直接增加一条数据来进行执行
19.安全规约
19.1 用户个人页面或者功能 必须进行权限校验
19.2 敏感数据例如身份证号码或者是电话号码都不能直接展示给用户
19.3 用户请求传入的任何参数必须做有效性验证
-
19.4 忽略了参数校验可能导致
PageSize过大导致内存溢出
恶意order by 导致数据库慢查询
任意重定向
SQL注入
反序列化注入
19.5 禁止向html页面输出未经过安全过滤或者未正确转义的用户数据
19.6 提交必须执行CSRF安全过滤
19.7 在使用平台资源的时候,譬如短信,邮件,电话,下单,支付,必须实现正确的防止重放限制,如数量限制,疲劳度控制,验证码校验,避免被滥用,资源损耗
19.8 发帖,评论,发送即时消息等用户生成内容必须实时防刷,文本内容违禁词过滤等风险
20.MySQL数据库
- 20.1 表达是与否必须使用is_***的方式命名,并且数据类型是unsigned
tinyint,1表示是,2表示否
20.2 表名不使用复数名词
20.3 主键索引名为pk_字段名,唯一索引名uk_字段名,普通索引名则为idx_字段名
20.4 小数类型为decimal,禁止使用float或者是double
20.5 单表行数超过500万或者是单表容量超过了2GB,才推荐进行分库分表
20.6 唯一索引会影响插入的速度,但是这部分可以忽略不计,但是唯一索引提升的查询速度是可以提升很多的
20.7 超过三个表就尽量不要使用join,使用join的时候数据类型必须保持完全的一致
20.8 在varchar字段上建立索引时必须要指定索引长度,没必要对全字段建立索引,根据实际文本区分决定索引长度即可,一般来说字符串类型的数据,长度为20的索引,区分度会高达90%以上,但是索引长度过长,索引的效果就会变得很低效了
20.9 页面搜索严禁使用左模糊查询或者是全模糊查询,这种情况下是不会进行索引查询的
20.10 尽量避免在where子句中使用!=或者是<>的操作,这样的情况引擎将会放弃使用索引而进行全表扫描
20.11 进行查询操作的时候,除非需要查询所有,否则尽量避免全表扫描的情况发生
20.12 使用复合索引的时候区分度高的再最左边
20.13 要防止因字段类型不同造成的隐式转换从而导致了索引的失效
20.14 不要使用count(列名)或者是count(常量)来代替count(),因为count()是会统计null的值,,但是count(列名是不会统计null的值的数量的
20.15 Count(distinct col)可以用于计算除了null以外的不重复的行数
20.16 使用isnull()来判断是否为null值
20.17 不得使用级联和外键,一切外键概念必须在应用层解决.外键和级联更新适用于单机低并发,不适用于分布式,高并发集群当中,级联更新是强阻塞,存在数据库更新风暴的风险,外键影响数据库的插入速度.级联就是表A跟表B有任意一个字段做了外键关联,此时A中的字段更新了,那么会锁住AB表,并且把B表中的字段也进行更新后放开锁
20.18 禁止使用存储过程,存储过程难以调试和拓展,更没有移植性.存储过程是数据库当中一组为了完成特定的功能的SQL语句集,是数据库当中的一个重要的对象
20.19 数据进行订正时,删除或者修改之前,请先进行select,避免出现错误更新或者是错误删除的情况
20.20 In操作能避免则避免,如果实在避免不了,需要仔细评估in边的集合元素数量,控制在1000个以内
20.21 In关键字和or关键字都会使用索引,但是子查询不会使用到索引
21.ORM映射相关
21.1 实体类当中Boolean属性的字段名称不能加上is为前缀,但是数据库当中Boolean类型必须使用is_作为前缀
21.2 不允许直接拿HashMap与HashTable作为查询结果的返回接受数据集,因为当数据量过大的时候Map集合中的resize方法需要重新建立Hash表,此时会浪费大量的性能,导致CPU突然暴涨
21.3 Update语句中不需要更新的字段不要写进去,因为更新无改动字段,一是容易出错,二是效率低,三是增加了mysql中binlog的存储
22.工程规范
22.1 pom.xml中的版本必须都保持一致
22.2 高并发服务器建议调小TCP协议的time_wait超时时间,,操作系统默认情况下是240秒后关闭处于time_wait状态的连接,在高并发的访问下,服务器会因为time_wait的连接数太多,可能导致无法建立新的连接,所以需要在服务器上调小这个等待值
è在 linux 服务器上请通过变更/etc/sysctl.conf 文件去修改该缺省值(秒):net.ipv 4.tcp_fin_timeout = 30
21.3 给JVM设置-XX :+ HeapDumpOnOutOfMemoryError,配置于启动类上,让JVM碰到OOM场景时输出dump信息
21.4 在线上生产环境时,JVM的Xms和Xmx设置一样大小的内存容量,避免在你GC后调整堆大小带来的压力
转载于:https://www.jianshu.com/p/7a3b8f0d786c