【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator 方式,如果并发操作,需要对 Iterator 对象加锁。
反例:
List a = new ArrayList();
a.add(“1”);
a.add(“2”);
for (String temp : a) {
if(“1”.equals(temp)){
a.remove(temp);
} }
说明:这个例子的执行结果会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结
果吗?
正例:
Iterator it = a.iterator(); while(it.hasNext()){
String temp = it.next(); if(删除元素的条件){
it.remove();
}
}
-
【强制】Map/Set 的 key 为自定义对象时,必须重写 hashCode 和 equals。
正例:String 重写了 hashCode 和 equals 方法,所以我们可以非常愉快地使用 String 对象作 为 key 来使用。
10.【推荐】使用 entrySet 遍历 Map 类集合 KV,而不是 keySet 方式进行遍历。
说明:keySet 其实是遍历了 2 次,一次是转为 Iterator 对象,另一次是从 hashMap 中取出 key 所对应的 value。而 entrySet 只是遍历了一次就把 key 和 value 都放到了 entry 中,效率更 高。如果是 JDK8,使用 Map.foreach 方法。
正例:values()返回的是 V 值集合,是一个 list 集合对象;keySet()返回的是 K 值集合,是 一个 Set 集合对象;entrySet()返回的是 K-V 值组合集合。 -
【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为 static,必须加锁,或者使用 DateUtils 工具类。
正例:注意线程安全,使用 DateUtils。亦推荐如下处理:
private static final ThreadLocal df = new ThreadLocal() { @Override
protected DateFormat initialValue() {
return new SimpleDateFormat(“yyyy-MM-dd”);
} };
说明:如果是 JDK8 的应用,可以使用 instant 代替 Date,Localdatetime 代替 Calendar, Datetimeformatter 代替 Simpledateformatter,官方给出的解释:simple beautiful strong
immutable thread-safe。
注意,子线程抛出异常堆栈,不能在主线程 try-catch 到。
JDK8,推荐使用 LongAdder 对象,比 AtomicLong 性能更好(减少乐观锁的重试次数)。
避免用 Apache Beanutils 进行属性的 copy。
说明:Apache BeanUtils 性能较差,可以使用其他方案比如 Spring BeanUtils, Cglib BeanCopier。 -
【强制】有 try 块放到了事务代码中,catch 异常后,如果需要回滚事务,一定要注意手动回 滚事务。
-
【强制】不能在 finally 块中使用 return,finally 块中的 return 返回后方法结束执行,不
会再执行 try 块中的 return 语句 -
【强制】应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架 SLF4J 中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
-
【强制】表名、字段名必须使用小写字母或数字;禁止出现数字开头,禁止两个下划线中间只 出现数字。数据库字段名的修改代价很大,因为无法进行预发布,所以字段名称需要慎重考虑。 正例:getter_admin,task_config,level3_name 反例:GetterAdmin,taskConfig,level_3_name
-
【强制】varchar 是可变长字符串,不预先分配存储空间,长度不要超过 5000,如果存储长度 大于此值,定义字段类型为 TEXT,独立出来一张表,用主键来对应,避免影响其它字段索引 效率。
10.【推荐】表的命名最好是加上“业务名称_表的作用”,避免上云梯后,再与其它业务表关联
时有混淆。
正例:tiger_task / tiger_reader / mpp_config
14.【推荐】单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。 说明:如果预计三年后的数据量根本达不到这个级别,请不要在创建表时就分库分表。 反例:某业务三年总数据量才 2 万行,却分成 1024 张表,问:你为什么这么设计?答:分 1024 张表,不是标配吗? -
【强制】业务上具有唯一特性的字段,即使是组合字段,也必须建成唯一索引。 说明:不要以为唯一索引影响了 insert 速度,这个速度损耗可以忽略,但提高查找速度是明
显的;另外,即使在应用层做了非常完善的校验和控制,只要没有唯一索引,根据墨菲定律, 必然有脏数据产生。 -
【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度。
-
【强制】在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度。 说明:索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分 度会高达 90%以上,可以使用 **count(distinct left(列名, 索引长度))/count(*)**的区分度来 确定。
-
【强制】页面搜索严禁左模糊或者全模糊,如果需要请走搜索引擎来解决。 说明:索引文件具有 B-Tree 的最左前缀匹配特性,如果左边的值未确定,那么无法使用此索 引。
-
【推荐】利用延迟关联或者子查询优化超多分页场景。
说明: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* -
【强制】不要使用 count(列名)或 count(常量)来替代 count(),count()就是 SQL92 定义的 标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。 -
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
11.【参考】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE 无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。 说明:TRUNCATE TABLE 在功能上与不带 WHERe 子句的 DELETE 语句相同。 -
【强制】xml 配置中参数注意使用:#{},#param# 不要使用${} 此种方式容易出现 SQL 注入。
开放接口层:可直接封装 Service 接口暴露成 RPC 接口;通过 Web 封装成 http 接口;网关控 制层等。
Web 层绝不应该继续往上抛异常,因为已 经处于顶层,无继续处理异常的方式,如果意识到这个异常将导致页面无法正常渲染,那么就 应该直接跳转到友好错误页面,尽量加上友好的错误提示信息。开放接口层要将异常处理成错 误码和错误信息方式返回。
-
【强制】二方库的新增或升级,保持除功能点之外的其它 jar 包仲裁结果不变。如果有改变, 必须明确评估和验证,建议进行 dependency:resolve 前后信息比对,如果仲裁结果完全不一 致,那么通过 dependency:tree 命令,找出差异点,进行排除 jar 包。
-
【强制】依赖于一个二方库群时,必须定义一个统一版本变量,避免版本号不一致。
说明:依赖 springframework-core,-context,-beans,它们都是同一个版本,可以定义一个 变量来保存版本:${spring.version},定义依赖的时候,引用该版本。
在本地调试时会使用各子项目指定的版本号,但是合并成一个 war,只能有一个版本号 出现在最后的 lib 目录中。曾经出现过线下调试是正确的,发布到线上出故障的先例。
md5 操作:commons-codec
工具集合:Guava 包
数组操作:ArrayUtils(org.apache.commons.lang3.ArrayUtils)
集合操作:CollectionUtils(org.apache.commons.collections4.CollectionUtils)
除上面以外还有 NumberUtils、DateFormatUtils、DateUtils 等优先使用 org.apache.commons.lang3 这个包下的,不要使用 org.apache.commons.lang 包下面 的。原因是 commons.lang 这个包是从 JDK1.2 开始支持的所以很多 1.5/1.6 的特性是不 支持的,例如:泛型。
正例:在 linux 服务器上请通过变更/etc/sysctl.conf 文件去修改该缺省值(秒):
net.ipv4.tcp_fin_timeout = 30
- 【推荐】调大服务器所支持的最大文件句柄数(File Descriptor,简写为 fd)。 说明:主流操作系统的设计是将 TCP/UDP 连接采用与文件一样的方式去管理,即一个连接对应 于一个 fd。主流的 linux 服务器默认所支持最大 fd 数量为 1024,当并发连接数很大时很容易
因为 fd 不足而出现“open too many files”错误,导致新的连接无法建立。 建议将 linux
服务器所支持的最大句柄数调高数倍(与服务器的内存数量相关)。
1、内部跳转的时候实际上是通过服务器端将请求转发到另外的页面或者servlet中,这个时候跳转到的目标页面或者servlet可以获取到请求对象,
也可以获取到请求中的属性和参数。而外部跳转的时候实际上是第一次请求后,服务器端向客户端发送了一个指令,让客户端再次请求了一次服务器端,这个时候服务器第二次拿到的request对象已经不是第一次请求的request对象了,所以无法获取到第一次请求里的参数和属性。
2、内部跳转的url地址栏不会发生变化,外部跳转url则会发生变化
服务器内部重定向使用forward;外部重定向需要使用URL Broker(代理)来完成,这样这可以避免线上使用的HTTPS在浏览器中显示“不安全”,还会带来URL维护不一致问题。例如:可以使用Nginx转发重定向,来避免问题的出现
Web应用程序就是典型的多任务应用,每个用户请求页面时,我们都会创建一个任务
这种在一个线程中,横跨若干方法调用,需要传递的对象,我们通常称之为上下文(Context),它是一种状态,可以是用户身份、任务信息等。
Java标准库提供了一个特殊的ThreadLocal,它可以在一个线程中传递同一个对象。
ThreadLocal实例通常总是以静态字段初始化如下:
实际上,可以把ThreadLocal看成一个全局Map
正向代理与反向代理的区别
正向代理是客户端与正向代理客户端在同一局域网,客户端发出请求,正向代理 替代客户端向服务器发出请求。服务器不知道谁是真正的客户端,正向代理隐藏了真实的请求客户端。
反向代理:服务器与反向代理在同一个局域网,客服端发出请求,反向代理接收请求 ,反向代理服务器会把我们的请求分转发到真实提供服务的各台服务器Nginx就是性能非常好的反向代理服务器,用来做负载均衡。
不能为目录创建硬链接。只能为文件创建硬链接。
- 如何在Linux中列出和挂载设备?
要列出挂载点,请运行以下命令:
df -aTh
要查找有关系统上安装点的更多信息,请执行以下命令:
findmnt
此外,您可以使用下面的 cat 命令
cat /proc/self/mounts
此外,您可以使用 mount 命令,如图所示
mount -l
如何检查某项服务是否在运行?
要检查服务是否正在运行,请使用以下语法:
systemctl status service_name
例如,要检查 Postfix 是否正在运行,请运行以下命令:
systemctl status postfix
- 如何在重启时启动服务?
要在重新启动运行时启动服务,请使用以下语法:
systemctl enable service_name
例如,要在重新启动时启动 httpd Web 服务器,请运行
systemctl enable httpd
- 如何启动和停止服务?
要在 systemd 系统中启动服务,请运行以下命令:
systemctl start service_name
例如,要启动 ssh 服务,请运行以下命令:
systemctl start sshd
要停止服务,请运行:
systemctl stop service_name
要停止 ssh 运行:
systemctl stop sshd
如何查看磁盘使用情况?
使用该df命令检查硬盘驱动器上使用的空间和剩余空间/可用空间。
此外,使用该du命令检查特定文件和目录的使用情况。
用户需要在建表的时候加上分区参数,对应用是透明的无需修改代码
对用户来说,分区表是一个独立的逻辑表,但是底层由多个物理子表组成,实现分区的代码实际上是通过对一组底层表的对象封装,但对SQL层来说是一个完全封装底层的黑盒子。MySQL实现分区的方式也意味着索引也是按照分区的子表定义,没有全局索引
分区
就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的
分表
就是把一张表按一定的规则分解成N个具有独立存储空间的实体表。系统读写时需要根据定义好的规则得到对应的字表明,然后操作它。



