一、编程规约(强制)
1、命名规范
不能以美元符合和下划线开始和结束 所有的命名都不能使用全拼音或者拼音和英文结合的方式 类名使用大驼峰的命名规则,除了 DO、PO、DTO、BO、VO、UID 等 方法名、参数名、成员变量、局部变量都统一使用第一个英文字母小写后面的每一个完整的英文字母的第一个字母使用大写 常量命名都统一使用大写,单词之间是用下划线隔开 抽象类命名使用 Abstract 或 Base 开头;异常类命名使用 Exception 结尾,测试类命名以它要 测试的类的名称开始,以 Test 结尾。 javaBean 中的布尔类型属性禁止使用前面加 is 前缀,否则部分框假解析时会出现序列化错误。(注: 因为此时当你属性是一个isNum ,对于框架来说以为解析之后的属性只有 is 后面的东西) 包名统一使用小写,并且只能是单数 禁止父子类之间的成员变量的命名一样 禁止不规范的英文缩写
2、常量定义
使用属性 long 或者 Long 时,给属性赋值的过程必须时大写L
浮点数的后缀统一使用 D 或者 F
3、代码格式
如果大括号内为空,则中间无需换行;反之,应遵循以下原则:
1、左大括号前不换行
2、左大括号后换行
3、右大括号前换行
4、右大括号后又 else 等代码不换行
正例:
if (a == b) {
}
反例:
if ( a == b ) {
}
if for while switch do 等保留字符与左右括号都必须加空格
任何二目运算和三目运算左右两边都必须加空格
注释的双斜线与注释内容之间有且仅有一个空格
类型强制转化——正例:
double a = 3.2D;
int b = (int)a;
单行字符限制不超过120个,超出需换行:
正例:
// 超过 120 个字符的情况下,换行缩进 4 个空格,并且方法前的点号一起换行
StringBuilder builder = new StringBuilder();
builder.append("yang").append("hao")...
.append("chen")...
.append("chen")...
.append("chen");
方法参数定义时多个参数逗号之后必须加空格
4、OOP规约
不能使用一个静态类的对象去引用静态方法,而是需要通过:类名 . 静态方法
所有的重写方法都必须加注解 @Override
只有相同的业务和相同的参数类型才可进行定义可变行参数,但是可变性参数类型禁止使用 Object
外部正在调用二方库时,禁止修改二方库中方法签名;并且使用过时的接口时必须加注解 @Deprecated
禁止使用过时的类和方法
使用 equals 方法时必须以下方式使用,避免造成空指针异常。
正例:
String test = new String("test");
"test".equals(test);
所有的整形包装类对象之间进行比较时,使用 equals 方法进行比较
浮点数进行比较时,基本数据类型不能使用 == ;包装类不能使用 equals
正例:
(1)指定一个误差范围,两个浮点数的差值在此范围之内,则认为是相等的。
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");
}
(2)使用 BigDecimal 来定义值,再进行浮点数的运算操作。
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
BigDecimal x = a.subtract(b);
BigDecimal y = b.subtract(c);
if (x.compareTo(y) == 0) {
System.out.println("true");
}
BigDecimal 的等值比较使用 compareTo 方法,而不是 equals
定义DO类时,属性类型要和数据库字段;类型一致;比如:bigint ————> Long
禁止使用 BigDecimal g = new BigDecimal(0.1F);方式进行转化,因为存在精度差,应该使用
BigDecimal recommend1 = new BigDecimal("0.1");// 先转化为字符串
BigDecimal recommend2 = BigDecimal.valueOf(0.1);// 或这调用该方法
所有的 POJO 类属性必须使用包装数据类型。
RPC 方法的返回值和参数必须使用包装数据类型。
尽量使得局部变量使用基本数据类型
定义 DO / PO / DTO / VO 等 POJO 类时,不要设定任何属性默认值。(对应数据库中的实体类)
序列化类新增时,不要修改 serialVersionUID 字段,避免反序列化失败;如果出现不兼容可修改 serialVersionUID 的值
POJO 类必须写 toString 方法。使用 IDE 中的工具 source > generate toString 时,如果继
承了另一个 POJO 类,注意在前面加一下 super.toString()。
禁止在 POJO 类中,同时存在对应属性 xxx 的 isXxx() 和 getXxx() 方法。
5、日期规约
日期格式化时年份必须统一使用小写 y
正例:
/**
y 表示年份
M 表示月份
m 表示分钟
D 表示24小时制
d 表示12小时制
*/
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
获取当前的毫秒数
正例:
System.currentTimeMillis();
禁止一年的天数写死,应该进行动态的获取:
正例:
int daysOfThisYear = LocalDate.now().lengthOfYear();
不允许在程序的任何地方使用 sql jar包中的时间类
只要重新 hashCode 就必须重写 equals ;如果两个类型的 hashCode 相等,equals 不一定相等;
否则反之。
判断所有集合内部的元素是否为空,使用 isEmpty() 方法,而不是 size() == 0 的方式。
在使用 java.util.stream.Collectors 类的 toMap() 方法转为 Map 集合时,一定要使用参数类型
为 BinaryOperator,参数名为 mergeFunction 的方法,否则当出现相同 key 时会抛出
IllegalStateException 异常。
在使用 java.util.stream.Collectors 类的 toMap() 方法转为 Map 集合时,一定要注意当 value
为 null 时会抛 NPE 异常。
ArrayList 的 subList 结果不可强转成 ArrayList,否则会抛出 ClassCastException 异常:
java.util.RandomAccessSubList cannot be cast to java.util.ArrayList
使用 Map 的方法 keySet() / values() / entrySet() 返回集合对象时,不可以对其进行添加元素
操作,否则会抛出 UnsupportedOperationException 异常。
Collections 类返回的对象,如:emptyList() / singletonList() 等都是 immutable list,不可
对其进行添加或者删除元素的操作。
使用集合转数组时的方法必须使用集合的有参toArray(有参),传入的类型一致,并且数组的长度为0,在转化
时可进行动态的扩容处理
将数组转化为集合时不能使用修改集合相关的方法
泛型通配符<? extends T>来接收返回的数据,此写法的泛型集合不能使用 add 方法, 而<? super T>不能
使用 get 方法,两者在接口调用赋值的场景中容易出错。
正例:
<? extends T> 不能进行添加
<? super T> 不能使用get方法
在无泛型限制定义的集合赋值给泛型限制的集合时,在使用集合元素时,需要进行
instanceof 判断,避免抛出 ClassCastException 异常。
不要再 foreach 循环里进行元素的remove / add 操作
JDK7 版本以上 Comparator 必须满足以下条件:
1)x,y 的比较结果和 y,x 的比较结果相反。
2)x > y,y > z,则 x > z。
3)x = y,则 x,z 比较结果和 y,z 比较结果相同。
使用 Collection 接口任何实现类的 addAll() 方法时,要对输入的集合参数进行 NPE 判断。
说明:在 ArrayList#addAll 方法的第一行代码即 Object[] a = c.toArray();其中 c 为输入集合参数,如果为 null, 则直接抛出异常。
6、并发处理
获取单例对象需要保证线程安全,其中的方法也要保证线程安全;举例如下:
public class Singleton{
private volatile static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();//指令重排
}
}
}
return instance;
}
}
创建线程时需指定有意义的线程或者线程池的名字
线程必须通过线程池提供,不可以进行显示的创建
创建线程池时应该使用 ThreadPoolExecutor
线程不安全的类一般不要定义为static
必须回收自定义的 ThreadLocal 变量,否则会造成后续的业务逻辑和内存泄漏等问题
对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
7、控制语句
当 switch 语句中的参数类型为 String 时,在进入 switch 语句之前必须进行判空处理
在高并发场景中,避免使用”等于“判断作为中断或者推出的条件
8、注释规约
类、类属性、类方法的注释都必须使用 Javadoc 规范
所有的抽象方法包括接口中的方法也都必须使用javadoc注释
方法内部使用单行
所有的枚举类型字段必须要有注释
9、前后端规约
get 请求是获取
post 请求是添加
put 请求是修改
delete 请求是删除
如果后端给前端响应数据如果没有,为空,则以空数组或者空集合的方式返回
服务端发生错误,返回给前端的响应信息必须包含 http 状态码、errorCode、errorMessage、用户提示部分
1)200 OK:表明该请求被成功地完成,所请求的资源发送到客户端。
Java 开发手册(黄山版)
2)401 Unauthorized:请求要求身份验证,常见对于需要登录而用户未登录的情况。
3)403 Forbidden:服务器拒绝请求,常见于机密信息或复制其它登录用户链接访问服务器的情况。
4)404 NotFound:服务器无法取得所请求的网页,请求资源不存在。
5)500 InternalServerError:服务器内部错误
如果需要使用大场景,服务端一律使用 String
HTTP 请求通过 URL 传递参数时,不能超过 2048 字节。
Ngnix 默认是1MB,tomcat 默认是2mb
翻页场景中,用户输入参数小于1,前端返回第一页参数给后端;后端发现用户输入的
参数大于总页数,直接返回最后一页
服务器内部重定向必须使用 forward;外部重定向地址必须使用 URL 统一代理模块生成,否则会因线上采用
HTTPS 协议而导致浏览器提示“不安全”,并且还会带来 URL 维护不一致的问题
10、其他
使用正则表达式时,应该利用好其预编译功能
后台输送给页面的变量必须加 $!{var} ————中间感叹号
禁止将 Math.random() 这个方法以乘法的方式进行放大,直接使用 Random 对象的 nextInt 和 nextLong
枚举类中的属性字段必须是私有且不可变的
二、异常日志
1、错误码
错误码不体现版本号和错误等级等信息
如果全部正常,但不得不填充错误码时返回五个0:00000
错误码是字符串类型,并且共五位,分成两个部分:错误产生来源 + 四位数字编号
A ———— 当前用户
B ———— 当前系统
C ———— 第三方服务
错误码不能直接输出用户信息
2、异常处理
java类库中出现运行时异常,尽可能去发现并改正,不应该进行 try···catch 方式来处理
异常捕获后不要用来做流程控制、条件控制
catch 时需分清稳定代码和不稳定代码
事务场景中,如果遇到了异常,抛出后被catch后,如果需要回滚,一定要注意手动回滚事务
不要在 finally 块中使用 return
###### 在调用 RPC、二方包、或动态生成类的相关方法时,捕捉异常使用 Throwable 类进行拦截。
3、日志规约
应用中不可直接使用日志系统(Log4j、Logback)中的 API,而应依赖使用日志框架(SLF4J、
JCL—Jakarta Commons Logging)中的 API,使用门面模式的日志框架,有利于维护和各个类的日志处理
方式统一
日志文件至少保存 15 天,因为有些异常具备以“周”为频次发生的特点。对于当天日志,以 “应用名.log”来
保存,保存在/{统一目录}/{应用名}/logs/目录下,过往日志格式为:
{logname}.log.{保存日期},日期格式:yyyy-MM-dd
日志的命名规则:appName_logType_logName.log
字符串变量之间的拼接使用占位符的方式
避免重复打印日志,浪费磁盘空间,务必在日志配置文件中设置 additivity=false(避免重复打印)
生产环境下禁止使用 System.out System.err 等
异常信息应该包括两类信息:案发现场信息和异常堆栈信息。 如果不处理就通过关键字 throws 往上抛
日志打印时禁止用JSON工具将对象转换为String
三、单元测试
单元测试必须遵守 AIR 原则:
A ———— 自动化
I ———— 独立性
R ———— 可重复
单元测试保证测试粒度足够小
四、安全规约
隶属于用户个人的页面或者功能必须进行权限控制校验 用户输入的sql参数严格使用参数绑定或者METADATA字段值限定,防止sql注入,禁止字符串拼接sql 表单、AJAX 提交必须执行 CSRF 安全验证 在使用平台资源,譬如短信、邮件、电话、下单、支付,必须实现正确的防重放的机制,如数量 限制、疲劳度控制、验证码校验,避免被滥刷而导致资损。 对于文件上传功能,需要对于文件大小、类型进行严格检查和控制。 配置文件中的密码需要加密