1 [Obligatoire] Les noms dans le code ne peuvent pas commencer par un trait de soulignement ou un signe dollar, ni se terminer par un trait de soulignement. ou un signe dollar.
Contre exemple : _nam / __name / $Object / name_ / name$ / Object$
2 [Obligatoire] Il est strictement interdit d'utiliser un mélange de pinyin et d'anglais pour nommer dans le code, et il n'est pas permis d'utiliser le chinois directement.
Explication : Une orthographe et une grammaire anglaises correctes peuvent faciliter la compréhension des lecteurs et éviter toute ambiguïté. Notez que même la dénomination pure en pinyin doit être évitée.
Contre-exemple : DaZhePromotion [Discount] / getPingfenByName() [Rating] / int A variable = 3
Exemple positif : alibaba / taobao / youku / hangzhou et d'autres noms courants au niveau international peuvent être considérés comme le même anglais.
3. [Obligatoire] Le nom de la classe doit utiliser le style UpperCamelCase et doit suivre la casse camel, avec les exceptions suivantes : (nom associé au modèle de domaine) DO / BO / DTO / VO, etc.
Exemple positif : MarcoPolo / UserDO / Les variables et les variables locales utilisent toutes le style lowerCamelCase et doivent suivre la casse camel.
Exemple positif : localValue / getHttpMessage() / inputUserId
5. [Obligatoire] Les noms de constantes doivent être en majuscules et les mots doivent être séparés par des traits de soulignement. ne déteste pas les noms longs.
Exemple positif : MAX_STOCK_COUNT
6 [Obligatoire] Le nom de la classe abstraite commence par Abstract ou Base ; le nom de la classe de test porte le nom de la classe à tester. Commence par le nom de la classe et se termine par Test.
7. [Obligatoire] Les crochets font partie du type de tableau. Le tableau est défini comme suit : String[] args;
Contre-exemple : Ne pas utiliser String args[] pour définir.
8. [Obligatoire] Ne pas ajouter de variables de type booléen dans la classe POJO, sinon certaines analyses du framework provoqueront des erreurs de sérialisation.
Contre-exemple : L'attribut défini comme type de données de base booléen isSuccess ; sa méthode est également isSuccess(). Lorsque le framework RPC effectue une analyse inverse, il "pense" que le nom de l'attribut correspondant est success, ce qui entraîne. échec d’obtention de l’attribut et une exception est levée.
9. [Obligatoire] Utilisez des lettres minuscules dans les noms de packages, avec un seul mot anglais avec une sémantique naturelle entre les séparateurs de points. Les noms de packages utilisent toujours la forme singulière, mais si le nom de classe a une signification plurielle, le nom de classe peut utiliser la forme plurielle.
Exemple positif : le nom du package de classe de l'outil d'application est com.alibaba.open.util et le nom de la classe est MessageUtils (cette règle fait référence à la structure du framework Spring)
10 [Obligatoire] Éviter complètement. abréviations irrégulières, pour ne pas manquer le sens du texte.
Contre-exemple : AbstractClass "abréviation" est nommé AbsClass ; la condition "abréviation" est nommée condi. Une telle abréviation arbitraire réduit sérieusement la lisibilité du code.
11. [Recommandation] Si des modèles de conception sont utilisés, il est recommandé de refléter les modèles spécifiques dans le nom de la classe.
Explication : refléter le modèle de conception dans le nom aidera les lecteurs à comprendre rapidement les idées de conception architecturale.
Contre-exemple : Définition de la méthode d'interface : public abstract void f(); : Les interfaces du JDK8 autorisent les implémentations par défaut, cette méthode par défaut est donc une implémentation par défaut précieuse pour toutes les classes d'implémentation.
Exemple positif : CacheServiceImpl implémente l'interface CacheService.
2) [Recommandation] S'il s'agit d'un nom d'interface qui décrit des capacités, utilisez l'adjectif correspondant comme nom d'interface (généralement sous la forme de –able).
Exemple positif : AbstractTranslator implémente Translatable.
14. [Référence] Il est recommandé d'ajouter le suffixe Enum au nom de la classe d'énumération. Les noms des membres de l'énumération doivent être en majuscules et les mots doivent être séparés par des traits de soulignement. Explication : les énumérations sont en fait des classes constantes spéciales, et le constructeur est obligé d'être privé par défaut.
Exemple positif : Nom de l'énumération : DealStatusEnum, nom du membre : SUCCESS / UNKOWN_REASON.
1) Les méthodes permettant d'obtenir un seul objet sont préfixées par get.
2) Les méthodes pour obtenir plusieurs objets sont préfixées par list.
3) La méthode d'obtention des valeurs statistiques est préfixée par count.
4) La méthode d'insertion est préfixée par save (recommandé) ou insert.
5) La méthode de suppression est préfixée par Remove (recommandé) ou delete.
6) La méthode de modification est préfixée par update.
B) Convention de dénomination du modèle de domaine
1) Objet de données : xxxDO, xxx est le nom de la table de données.
2) Objet de transfert de données : xxxDTO, xxx est le nom lié au domaine d'activité.
3) Objet d'affichage : xxxVO, xxx est généralement le nom de la page web.
4) POJO est le nom collectif de DO/DTO/BO/VO, et il est interdit de le nommer comme xxxPOJO.
1. [Obligatoire] Aucune valeur magique (c'est-à-dire des constantes non définies) n'est autorisée à apparaître directement dans le code.
Contre-exemple : String key="Id#taobao_"+tradeId;
cache.put(key, value);
2 [Obligatoire] Lorsque long ou Long est initialement attribué. , il doit utiliser un L majuscule et non un l minuscule. Les lettres minuscules peuvent facilement être confondues avec le chiffre 1, provoquant des malentendus.
Explication : Long a = 2l ; Est-ce un 21 numérique ou un Long type 2 ?
3 [Recommandation] N'utilisez pas de classe constante pour conserver toutes les constantes. leurs fonctions, entretenues séparément. Par exemple : les constantes liées au cache sont placées sous la classe : CacheConsts ; les constantes liées à la configuration du système sont placées sous la classe : ConfigConsts.
Remarque : Pour une classe de constantes vaste et complète, vous devez utiliser la fonction de recherche pour localiser la constante modifiée, ce qui n'est pas propice à la compréhension et à la maintenance.
4. [Recommandé] Il existe cinq niveaux de réutilisation des constantes : les constantes partagées entre les applications, les constantes partagées au sein des applications, les constantes partagées au sein des sous-projets, les constantes partagées au sein des packages et les constantes partagées au sein des classes.
1) Constantes partagées entre applications : placées dans une bibliothèque tierce, généralement dans le répertoire des constantes de client.jar.
2) Constantes partagées dans l'application : placées dans le répertoire des constantes dans les modules de la bibliothèque.
Contre-exemple : les variables faciles à comprendre doivent également être définies uniformément comme constantes partagées au sein de l'application. Deux maîtres de siège ont défini des variables représentant "oui" dans deux classes :
Dans la classe A : public static final String YES = "yes";
Dans la classe B : public static final String YES = "y"; A.YES.equals(B.YES), la valeur attendue est vraie, mais la valeur réelle le retour est faux, provoquant des problèmes en ligne.
3) Constantes partagées au sein du sous-projet : c'est-à-dire dans le répertoire des constantes du sous-projet actuel.
4) Constantes partagées au sein du package : c'est-à-dire dans un répertoire de constantes séparé sous le package actuel.
5) Constantes partagées au sein de la classe : définition finale statique privée directement à l'intérieur de la classe.
5. [Recommandé] Si la valeur de la variable ne change que dans une plage, utilisez la classe Enum. S'il existe des attributs étendus autres que des noms, la classe Enum doit être utilisée. Les nombres dans l'exemple suivant sont des informations étendues, indiquant le jour de la semaine.
Exemple positif : public Enum{ LUNDI(1), MARDI(2), MERCREDI(3), JEUDI(4), VENDREDI(5), SAMEDI(6), DIMANCHE(7);}
1. [Obligatoire] Convention sur l'utilisation des accolades. Si les accolades sont vides, écrivez simplement {} sans saut de ligne ; s'il s'agit d'un bloc de code non vide :
1) Il n'y a pas de saut de ligne avant l'accolade gauche.
2) Saut de ligne après l'accolade gauche.
3) Saut de ligne avant l'accolade droite.
4) S'il y a un autre code après l'accolade droite, il ne s'enroulera pas, cela signifie qu'il doit s'enrouler après avoir terminé l'accolade droite ;
2. [Obligatoire] Il n'y a pas d'espace entre le crochet gauche et le caractère suivant de même, il n'y a pas d'espace entre le crochet droit et le caractère précédent ; Pour plus de détails, consultez les exemples de conseils positifs sous l’article 5.
3. [Obligatoire] Des espaces doivent être ajoutés entre les mots réservés tels que if/for/while/switch/do et les crochets gauche et droit.
4. [Obligatoire] Il doit y avoir un espace autour de tout opérateur.
Explication : Les opérateurs incluent l'opérateur d'affectation =, l'opérateur logique &&, les symboles d'addition, de soustraction, de multiplication et de division, les opérateurs ternaires, etc.
5. [Obligatoire] Utilisez 4 espaces pour l'indentation et les tabulations sont interdites.
Remarque : si vous utilisez l'indentation de tabulation, vous devez définir l'indentation, vous devez définir l'indentation, vous devez définir l'indentation, vous devez définir l'indentation, vous devez définir l'indentation, vous devez définir 1 tabulation sur 4 espaces. Lorsque IDEA définit les tabulations sur 4 espaces, ne cochez pas Utiliser le caractère de tabulation dans Eclipse, vous devez cocher Insérer des espaces pour les tabulations.
Exemple positif : (impliquant les points 1 à 5)
public static void main(String args[]) {// 缩进4个空格String say = "hello";// 运算符的左右必须有一个空格int flag = 0;// 关键词if与括号之间必须有一个空格,括号内的f与左括号,0与右括号不需要空格if (flag == 0) { System.out.println(say); }// 左大括号前加空格且不换行;左大括号后换行if (flag == 1) { System.out.println("world");// 右大括号前换行,右大括号后有else,不用换行} else { System.out.println("ok");// 在右大括号后直接结束,则必须换行 } }
6. 【强制】单行字符数限不超过 120 个,超出需要换行时 个,超出需要换行时 遵循如下原则:
1) 第二行相对一缩进 4个空格,从第三行开始不再继续缩进参考示例。
2) 运算符与下文一起换行。
3) 方法调用的点符号与下文一起换行。
4) 在多个参数超长,逗号后进行换行。
5) 在括号前不要换行,见反例。
正例:
StringBuffer sb = new StringBuffer();
//超过120个字符的情况下,换行缩进4个空格,并且方法前的点符号一起换行
sb.append("zi").append("xin")...
.append("huang")...
.append("huang")...
.append("huang");
反例:
StringBuffer sb = new StringBuffer();
//超过120个字符的情况下,不要在括号前换行
sb.append("zi").append("xin")...append
("huang");
//参数很多的方法调用可能超过120个字符,不要在逗号前换行
method(args1, args2, args3, ...
, argsX);
7. 【强制】方法参数在定义和传入时,多个参数逗号后边必须加空格。
正例:下例中实参的"a",后边必须要有一个空格。
method("a", "b", "c");
8. 【强制】IDE的text file encoding设置为UTF-8; IDE中文件的换行符使用Unix格式,不要使用windows格式。
9. 【推荐】没有必要增加若干空格来使某一行的字符与上一行的相应字符对齐。
正例:
int a = 3;long b = 4L;float c = 5F; StringBuffer sb = new StringBuffer();
Remarque : ajoutez la variable sb. Si un alignement est requis, ajoutez quelques espaces à a, b et c. Lorsqu'il y a de nombreuses variables, c'est une chose fastidieuse.
10. [Recommandé] Insérez une ligne vide entre le groupe d'instructions d'exécution, le groupe d'instructions de définition de variable, une logique métier différente ou une sémantique différente dans le corps de la méthode. Il n'est pas nécessaire d'insérer des lignes vides entre la même logique métier et la même sémantique.
Remarque : Il n'est pas nécessaire d'insérer plusieurs lignes d'espaces pour les séparer.
1. [Obligatoire] Évitez d'accéder aux variables statiques ou aux méthodes statiques de cette classe via les références d'objet d'une classe, ce qui augmentera inutilement le coût d'analyse du compilateur. le nom de la classe directement Venez visiter.
2. [Obligatoire] Toutes les méthodes de remplacement doivent être annotées avec @Override.
Contre exemple : le problème de getObject() et get0object(). L'une est la lettre O et l'autre le chiffre 0. L'ajout de @Override peut déterminer avec précision si le remplacement a réussi. De plus, si la signature de la méthode est modifiée dans une classe abstraite, sa classe d'implémentation compilera et signalera immédiatement une erreur.
3. [Obligatoire] Les paramètres de variable Java ne peuvent être utilisés que s'ils ont le même type de paramètre et la même signification commerciale. Évitez d'utiliser Object.
Remarque : les paramètres des variables doivent être placés à la fin de la liste des paramètres. (Les étudiants sont encouragés à éviter autant que possible la programmation avec des paramètres variables)
Exemple positif : public User getUsers (String type, Integer... ids)
[Obligatoire] En principe, la signature de. l'interface exposée à l'extérieur n'est pas autorisée. Permet la modification des signatures de méthodes pour éviter tout impact sur les appelants de l'interface. Si l'interface est obsolète, l'annotation @Deprecated doit être ajoutée et la nouvelle interface ou le nouveau service doit être clairement indiqué.
5. [Obligatoire] Les classes ou méthodes obsolètes ne peuvent pas être utilisées.
Explication : La méthode decode(String encodeStr) dans java.net.URLDecoder est obsolète. Le decode à deux paramètres (String source, String encode) doit être utilisé. Puisque le fournisseur d'interface est clairement une interface obsolète, il est obligé de fournir une nouvelle interface en même temps qu'un appelant, il est obligé de vérifier la nouvelle implémentation de la méthode obsolète ;
6. [Obligatoire] La méthode égale de Object est susceptible de lever une exception de pointeur nul. Vous devez utiliser une constante ou un objet avec une certaine valeur pour appeler égal.
Exemple positif : "test".equals(object); Contre-exemple : object.equals("test");
Remarque : Il est recommandé d'utiliser java.util.Objects#equals ( introduit par la classe JDK7 Tool)
7. [Obligatoire] Utilisez la méthode égale pour comparer les valeurs entre tous les objets de classe de package du même type.
Explication : Pour une affectation Integer var=? entre -128 et 127, l'objet Integer est généré dans IntegerCache.cache et les objets existants seront réutilisés dans cette plage et pourront être utilisés directement == Make. un jugement, mais toutes les données en dehors de cette plage seront générées sur le tas et les objets existants ne seront pas réutilisés. C'est un gros piège. Il est recommandé d'utiliser la méthode égale pour le jugement.
8. [Obligatoire] Les normes d'utilisation pour les types de données de base et les types de données packagés sont les suivantes :
1) Tous les attributs de classe POJO doivent utiliser des types de données packagés.
2) La valeur de retour et les paramètres des méthodes RPC doivent utiliser des types de données encapsulés.
3) Toutes les variables locales [recommandé] utilisent des types de données de base.
Explication : L'attribut de classe POJO n'a pas de valeur initiale pour rappeler aux utilisateurs qu'ils doivent explicitement attribuer eux-mêmes la valeur lorsqu'ils ont besoin de l'utiliser. Tout problème NPE ou contrôle d'entreposage est assuré par l'utilisateur. Exemple positif : le résultat de la requête de la base de données peut être nul car le déballage et la réception automatiques avec des types de données de base présentent des risques NPE.
Exemple de compteur : par exemple, affichez la hausse et la baisse du volume total des transactions, c'est-à-dire plus ou moins x%, x est le type de données de base et le service RPC appelé lorsque l'appel échoue. la valeur par défaut est renvoyée et la page affiche : 0 %, ce qui est déraisonnable et doit être affiché sous forme de tiret -. Par conséquent, la valeur nulle du type de données encapsulé peut représenter des informations supplémentaires, telles que : un échec d'appel à distance et une sortie anormale.
9. [Obligatoire] Lors de la définition de classes POJO telles que DO/DTO/VO, ne définissez aucune valeur par défaut d'attribut.
Contre-exemple : La valeur par défaut de gmtCreate de la classe POJO est new Date(); cependant, cet attribut n'a pas de valeur spécifique lors de l'extraction des données, et ce champ est mis à jour lorsque d'autres champs sont mis à jour, ce qui entraîne l'heure de création doit être Passer à l'heure actuelle.
10. [Obligatoire] Lors de l'ajout de nouveaux attributs à la classe de sérialisation, veuillez ne pas modifier le champ SerialVersionUID pour éviter un échec de désérialisation ; s'il est complètement incompatible avec les mises à niveau, pour éviter le chaos de la désérialisation, veuillez modifier la valeur SerialVersionUID.
Remarque : notez qu'un SerialVersionUID incohérent générera une exception d'exécution de sérialisation.
11. [Obligatoire] Il est interdit d'ajouter une logique métier dans la méthode de construction. S'il existe une logique d'initialisation, veuillez la mettre dans la méthode init.
12. [Obligatoire] La classe POJO doit écrire la méthode toString. Lorsque vous utilisez l'outil IDE : source>generate toString, si vous héritez d'une autre classe POJO, assurez-vous d'ajouter super.toString devant.
说明:在方法执行抛出异常时,可以直接调用POJO的toString()方法打印其属性值,便于排查问题。
13. 【推荐】使用索引访问用String的split方法得到的数组时,需做最后一个分隔符后有无内容的检查,否则会有抛IndexOutOfBoundsException的风险。
说明:
String str = "a,b,c,,";
String[] ary = str.split(",");
//预期大于3,结果是3
System.out.println(ary.length);
14. 【推荐】当一个类有多个构造方法,或者多个同名方法,这些方法应该按顺序放置在一起,便于阅读。
15. 【推荐】 类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法。 说明:公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类关心,也可能是“模板设计模式”下的核心方法;而私有方法外部一般不需要特别关心,是一个黑盒实现;因为方法信息价值较低,所有Service和DAO的getter/setter方法放在类体最后。
16. 【推荐】setter方法中,参数名称与类成员变量名称一致,this.成员名=参数名。在getter/setter方法中,尽量不要增加业务逻辑,增加排查问题的难度。
反例:
public Integer getData() {if (true) {return data + 100; } else {return data - 100; } }
17. 【推荐】循环体内,字符串的联接方式,使用StringBuilder的append方法进行扩展。 反例:
String str = "start";for (int i = 0; i < 100; i++) { str = str + "hello"; }
说明:反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象,造成内存资源浪费。
18. 【推荐】final可提高程序响应效率,声明成final的情况:
1) 不需要重新赋值的变量,包括类属性、局部变量。
2) 对象参数前加final,表示不允许修改引用的指向。
3) 类方法确定不允许被重写。
19. 【推荐】慎用Object的clone方法来拷贝对象。
说明:对象的clone方法默认是浅拷贝,若想实现深拷贝需要重写clone方法实现属性对象的拷贝。
20. 【推荐】类成员与方法访问控制从严:
1) 如果不允许外部直接通过new来创建对象,那么构造方法必须是private。
2) 工具类不允许有public或default构造方法。
3) 类非static成员变量并且与子类共享,必须是protected。
4) 类非static成员变量并且仅在本类使用,必须是private。
5) 类static成员变量如果仅在本类使用,必须是private。
6) 若是static成员变量,必须考虑是否为final。
7) 类成员方法只供类内部调用,必须是private。
8) 类成员方法只对继承类公开,那么限制为protected。
说明:任何类、方法、参数、变量,严控访问范围。过宽泛的访问范围,不利于模块解耦。
思考:如果是一个private的方法,想删除就删除,可是一个public的Service方法,或者一个public的成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作用域太大,如果无限制的到处跑,那么你会担心的。
1. 【强制】关于hashCode和equals的处理,遵循如下规则:
1) 只要重写equals,就必须重写hashCode。
2) 因为Set存储的是不重复的对象,依据hashCode和equals进行判断,所以Set存储的对象必须重写这两个方法。
3) 如果自定义对象做为Map的键,那么必须重写hashCode和equals。
正例:String重写了hashCode和equals方法,所以我们可以非常愉快地使用String对象作为key来使用。
2. 【强制】 ArrayList的subList结果不可强转成ArrayList,否则会抛出ClassCastException异常:java.util.RandomAccessSubList cannot be cast to java.util.ArrayList ;
说明:subList 返回的是 ArrayList 的内部类 SubList,并不是 ArrayList ,而是 ArrayList 的一个视图,对于SubList子列表的所有操作最终会反映到原列表上。
3. 【强制】 在subList场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生ConcurrentModificationException 异常。
4. 【强制】使用集合转数组的方法,必须使用集合的toArray(T[] array),传入的是类型完全一样的数组,大小就是list.size()。
反例:直接使用toArray无参方法存在问题,此方法返回值只能是Object[]类,若强转其它类型数组将出现ClassCastException错误。
正例:
List<String> list = new ArrayList<String>(2); list.add("guan"); list.add("bao"); String[] array = new String[list.size()]; array = list.toArray(array);
说明:使用toArray带参方法,入参分配的数组空间不够大时,toArray方法内部将重新分配内存空间,并返回新数组地址;如果数组元素大于实际所需,下标为[ list.size() ]的数组元素将被置为null,其它数组元素保持原值,因此最好将方法入参数组大小定义与集合元素个数一致。
5. 【强制】使用工具类Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方法,它的add/remove/clear方法会抛出UnsupportedOperationException异常。
说明:asList的返回对象是一个Arrays内部类,并没有实现集合的修改方法。Arrays.asList体现的是适配器模式,只是转换接口,后台的数据仍是数组。 String[] str = new String[] { "a", "b" }; List list = Arrays.asList(str);
第一种情况:list.add("c"); 运行时异常。
第二种情况:str[0]= "gujin"; 那么list.get(0)也会随之修改。
6. 【强制】泛型通配符 extends T>来接收返回的数据,此写法的泛型集合不能使用add方法。
说明:苹果装箱后返回一个 extends Fruits>对象,此对象就不能往里加任何水果,包括苹果。
7. 【强制】不要在foreach循环里进行元素的remove/add操作。remove元素请使用Iterator方式,如果并发操作,需要对Iterator对象加锁。
反例:
List<String> a = new ArrayList<String>(); a.add("1"); a.add("2");for (String temp : a) {if ("1".equals(temp)) { a.remove(temp); } }
说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗? 正例:
Iterator<String> it = a.iterator();while (it.hasNext()) { String temp = it.next();if (删除元素的条件) { it.remove(); } }
8. 【强制】 在JDK7版本以上,Comparator要满足自反性,传递性,对称性,不然Arrays.sort,Collections.sort会报IllegalArgumentException异常。
说明:
1) 自反性:x,y的比较结果和y,x的比较结果相反。
2) 传递性:x>y,y>z,则x>z。
3) 对称性:x=y,则x,z比较结果和y,z比较结果相同。
反例:下例中没有处理相等的情况,实际使用中可能会出现异常:
new Comparator<Student>() { @Overridepublic int compare(Student o1, Student o2) {return o1.getId() > o2.getId() ? 1 : -1; } }
9. 【推荐】集合初始化时,尽量指定集合初始值大小。 说明:ArrayList尽量使用ArrayList(int initialCapacity) 初始化。
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值组合集合。
11. 【推荐】高度注意Map类集合K/V能不能存储null值的情况,如下表格:
集合类 | Key | Value | Super | 说明 |
Hashtable | 不允许为null | 不允许为null | Dictionary | 线程安全 |
ConcurrentHashMap | 不允许为null | 不允许为null | AbstractMap | 分段锁技术 |
TreeMap | 不允许为null | 允许为null | AbstractMap | 线程不安全 |
HashMap | 允许为null | 允许为null | AbstractMap | 线程不安全 |
反例: 由于HashMap的干扰,很多人认为ConcurrentHashMap是可以置入null值,注意存储null值时会抛出NPE异常。
12. 【参考】合理利用好集合的有序性(sort)和稳定性(order),避免集合的无序性(unsort)和不稳定性(unorder)带来的负面影响。
说明:稳定性指集合每次遍历的元素次序是一定的。有序性是指遍历的结果是按某种比较规则依次排列的。如:ArrayList是order/unsort;HashMap是unorder/unsort;TreeSet是order/sort。
13. 【参考】利用Set元素唯一的特性,可以快速对一个集合进行去重操作,避免使用List的contains方法进行遍历、对比、去重操作。
1. 【强制】获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
说明:资源驱动类、工具类、单例工厂类都需要注意。
2. 【强制】创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
正例:
public class TimerTaskThread extends Thread {public TimerTaskThread(){super.setName("TimerTaskThread"); ... }
3. 【强制】线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
说明:使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
4. 【强制】线程池不允许使用 Executors去创建,而是通过ThreadPoolExecutor去创建,这样的处理方式让写同学更加明确线程池运行规则,避资源耗尽风险。
说明: Executors返回的线程池对象的弊端如下 :
1)FixedThreadPool和 SingleThread:
允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
5. 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为static变量,如果定义为static,必须加锁,或者使用DateUtils工具类。
正例:注意线程安全,使用DateUtils。亦推荐如下处理:
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() { @Overrideprotected DateFormat initialValue() {return new SimpleDateFormat("yyyy-MM-dd"); } }
说明:如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替Simpledateformatter,官方给出的解释:simple beautiful strong immutable thread-safe。
6. 【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区块,就不要锁整个方法体;能用对象锁,就不要用类锁。
7. 【强制】对多个资源、数据库表、对象同时加锁时,需要保持一致的加锁顺序,否则可能会造成死锁。
说明:线程一需要对表A、B、C依次全部加锁后才可以进行更新操作,那么线程二的加锁顺序也必须是A、B、C,否则可能出现死锁。
8. 【强制】并发修改同一记录时,避免更新丢失,要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用version作为更新依据。
说明:如果每次访问冲突概率小于20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于3次。
9. 【强制】多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
10. 【推荐】使用CountDownLatch进行异步转同步操作,每个线程退出前必须调用countDown方法,线程执行代码注意catch异常,确保countDown方法可以执行,避免主线程无法执行至countDown方法,直到超时才返回结果。
说明:注意,子线程抛出异常堆栈,不能在主线程try-catch到。
11. 【推荐】避免Random实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。
说明:Random实例包括java.util.Random 的实例或者 Math.random()实例。
正例:在JDK7之后,可以直接使用API ThreadLocalRandom,在 JDK7之前,可以做到每个线程一个实例。
12. 【推荐】通过双重检查锁(double-checked locking)(在并发场景)实现延迟初始化的优化问题隐患(可参考 The "Double-Checked Locking is Broken" Declaration),推荐问题解决方案中较为简单一种(适用于JDK5及以上版本),将目标属性声明为 volatile型。
反例:
class Foo {private Helper helper = null;public Helper getHelper() {if (helper == null)synchronized (this) {if (helper == null) helper = new Helper(); }return helper; }// other functions and members...}
13. [Référence] Volatile résout le problème de la mémoire invisible dans les multi-threads. Pour une écriture et plusieurs lectures, le problème de synchronisation des variables peut être résolu, mais s'il y a plusieurs écritures, le problème de sécurité des threads ne peut pas être résolu. S'il s'agit d'une opération count++, utilisez la classe suivante pour l'implémenter : AtomicInteger count = new AtomicInteger(); count.addAndGet(1); S'il s'agit de JDK8, il est recommandé d'utiliser l'objet LongAdder, qui a de meilleures performances qu'AtomicLong ; (réduit le nombre de tentatives de verrouillage optimiste).
14. [Référence] Lorsque HashMap a une capacité de redimensionnement insuffisante, des liens morts peuvent survenir en raison d'une concurrence élevée, provoquant une augmentation du processeur. Faites attention pour éviter ce risque pendant le processus de développement.
15. [Référence] ThreadLocal ne peut pas résoudre le problème de mise à jour des objets partagés. Il est recommandé d'utiliser la modification statique pour les objets ThreadLocal. Cette variable est commune à toutes les opérations au sein d'un thread, elle est donc définie comme une variable statique. Toutes ces instances partagent cette variable statique, ce qui signifie que lorsque la classe est utilisée pour la première fois, elle est chargée et ne constitue qu'un élément de stockage. l'espace est alloué. Les objets (tant qu'ils sont définis dans ce thread) peuvent manipuler cette variable.
1. [Obligatoire] Dans un bloc de commutation, chaque cas doit être terminé soit par coupure/retour, etc., soit par un commentaire indiquant lequel sera le programme. continuez à exécuter case ; dans un bloc switch, une instruction par défaut doit être incluse et placée à la fin, même si elle n'a pas de code.
2. [Obligatoire] Les accolades doivent être utilisées dans les instructions if/else/for/while/do, même s'il n'y a qu'une seule ligne de code, évitez d'utiliser les formes suivantes : if (condition)
3; . [Recommandé] Il est recommandé d'utiliser le moins possible else La méthode if-else peut être réécrite comme suit :
if(condition){
...
return obj;
}<.> // Ensuite, écrivez le code de logique métier else ;
Description : Si vous devez utiliser if()...else if()...else... pour exprimer la logique, [Obligatoire] ne dépassez pas 3 S'il dépasse 3 niveaux, veuillez utiliser le modèle de conception d'état.
Exemple positif : un code if-else avec plus de 3 niveaux de logique peut être implémenté à l'aide d'instructions de garde ou de modèles d'état.
4. [Recommandé] À l'exception des méthodes courantes (telles que getXxx/isXxx), n'exécutez pas d'autres instructions complexes dans des jugements conditionnels et attribuez les résultats de jugements logiques complexes à un nom de variable booléenne significatif pour améliorer la lisibilité.
//Le pseudo-code est le suivant
boolean existed = (file.open(fileName, "w") != null) && (...) || .. )( ... ) || (...)) {
...
}
5. [Recommandation] Les instructions dans le corps de la boucle doivent prendre en compte les performances. autant que possible, comme définir des objets, des variables, obtenir des connexions à la base de données et effectuer des opérations try-catch inutiles (ce try-catch peut-il être déplacé en dehors de la boucle) ?
6. [Recommandé] Protection des paramètres d'entrée d'interface Ce scénario est courant pour les interfaces utilisées pour les opérations par lots.
7. [Référence] Scénarios où la vérification des paramètres est requise dans les méthodes :
1) Méthodes appelées moins fréquemment.
2) Pour une méthode qui nécessite beaucoup de temps d'exécution, le temps de vérification des paramètres est presque négligeable. Cependant, si l'exécution intermédiaire annule ou fait une erreur en raison d'erreurs de paramètres, le gain dépasse la perte.
3) Une méthode qui nécessite une stabilité et une disponibilité extrêmement élevées.
5) Entrée des autorisations sensibles.
8. [Référence] Scénarios où la vérification des paramètres n'est pas requise dans les méthodes :
1) Il n'est pas recommandé de vérifier les paramètres des méthodes qui sont très susceptibles d'être appelées de manière cyclique. Cependant, la vérification des paramètres externes doit être notée dans la description de la méthode.
2) Les méthodes sous-jacentes sont appelées fréquemment et ne sont généralement pas vérifiées. Après tout, c'est comme la dernière étape de la filtration de l'eau pure, et il est peu probable que les erreurs de paramètres exposent à des problèmes jusqu'à la couche inférieure. Généralement, la couche DAO et la couche Service se trouvent dans la même application et déployées sur le même serveur, la vérification des paramètres DAO peut donc être omise.
3) Une méthode déclarée comme privée ne sera appelée que par votre propre code. Si vous pouvez être sûr que les paramètres transmis par le code appelant la méthode ont été vérifiés ou qu'il n'y a définitivement aucun problème, vous le faites. pas besoin de vérifier les paramètres pour le moment.
(8) Convention de commentaire
1. [Obligatoire] Les commentaires sur les classes, les attributs de classe et les méthodes de classe doivent utiliser les spécifications Javadoc, en utilisant le format /**contenu*/ et /. n’est pas autorisé.
Remarque : dans la fenêtre d'édition de l'IDE, le mode Javadoc demandera des commentaires pertinents, et le Javadoc généré peut correctement afficher les commentaires correspondants dans l'EDI, lorsque le projet appelle une méthode, la méthode, les paramètres et ; les retours peuvent être suspendus sans entrer dans la méthode et améliorer l'efficacité de la lecture.
2. [Obligatoire] Toutes les méthodes abstraites (y compris les méthodes dans les interfaces) doivent être annotées avec Javadoc En plus des valeurs de retour, des paramètres et des descriptions d'exception, elles doivent également indiquer ce que fait la méthode et quelles fonctions elle implémente. Remarque : veuillez expliquer les exigences de mise en œuvre pour les sous-classes ou les précautions d'appel.
3. [Obligatoire] Toutes les classes doivent ajouter des informations sur le créateur.
4. [Obligatoire] Commentaires sur une seule ligne à l'intérieur de la méthode, commencez une nouvelle ligne au-dessus de l'instruction commentée et utilisez // comment. Utilisez /* */ comments pour les commentaires multilignes dans les méthodes et assurez-vous de les aligner avec le code.
5. [Obligatoire] Tous les champs de type énumération doivent comporter des commentaires pour expliquer le but de chaque élément de données.
6. [Recommandation] Plutôt que de commenter dans un anglais à moitié cuit, il est préférable d'utiliser des commentaires chinois pour expliquer clairement le problème. Les noms propres et les mots-clés peuvent rester dans le texte anglais original.
Contre-exemple : "Délai d'expiration de la connexion TCP" est interprété comme "Délai d'expiration de la connexion au protocole de contrôle de transmission", ce qui est difficile à comprendre.
7. [Recommandation] Lors de la modification du code, les commentaires doivent également être modifiés en conséquence, notamment les modifications des paramètres, des valeurs de retour, des exceptions, de la logique de base, etc.
Remarque : les mises à jour du code et des annotations sont désynchronisées, tout comme les mises à jour du réseau routier et du logiciel de navigation sont désynchronisées. Si le logiciel de navigation est sérieusement en retard, le sens de la navigation sera perdu.
8. [Référence] Le code commenté doit correspondre autant que possible à la description, plutôt que d'être simplement commenté.
Remarque : Il existe deux possibilités pour que le code soit commenté :
1) La logique de ce code sera restaurée ultérieurement.
2) Ne l'utilisez jamais. S’il n’y a aucune information de remarque dans le premier, il est difficile de connaître la motivation de l’annotation. Il est recommandé de supprimer directement ce dernier (le référentiel de code enregistre le code historique).
9. [Référence] Exigences pour les commentaires :
Premièrement, ils peuvent refléter avec précision les idées de conception et la logique du code
Deuxièmement, ils peuvent décrire la signification commerciale afin que d'autres programmeurs puissent le faire ; Capable de comprendre rapidement les informations derrière le code. Un gros bloc de code sans commentaires est comme un livre sacré pour le lecteur. Les commentaires sont à lire, afin que vous puissiez comprendre clairement la pensée de ce moment-là même après une longue période. Les commentaires sont également destinés à vos successeurs. , afin qu'ils puissent rapidement prendre en charge votre travail.
10. [Référence] Une bonne structure de nom et de code est explicite et les commentaires doivent être concis, précis et expressifs. Évitez un extrême des commentaires : des commentaires trop nombreux et excessifs. Une fois la logique du code modifiée, modifier les commentaires sera une charge considérable.
Contre-exemple :
// mettre l'éléphant dans le réfrigérateur
put(éléphant, réfrigérateur);
Le nom de la méthode put, ainsi que deux noms de variables significatifs, Elephant et Bridge, ont été expliqués. ce que fait, c'est qu'un code sémantiquement clair ne nécessite pas de commentaires supplémentaires.
11. [Référence] Marque de commentaire spécial, veuillez indiquer la personne qui l'a noté et l'heure de la notation. Faites attention à traiter ces marques en temps opportun et nettoyez-les fréquemment grâce à la numérisation des marques. Les défauts en ligne proviennent parfois du code situé à ces marques.
1) Éléments à faire (TODO) : (marquer la personne, marquer le temps, [temps de traitement estimé]) Indique les fonctions qui doivent être implémentées mais qui ne l'ont pas encore été. Il s'agit en fait d'une balise Javadoc. Le Javadoc actuel n'a pas encore été implémenté, mais il a été largement utilisé. Ne peut être appliqué qu'aux classes, interfaces et méthodes (car il s'agit d'une balise Javadoc). 2) Erreur, ne peut pas fonctionner (FIXME) : (marquer la personne, marquer le temps, [temps de traitement estimé]) Utilisez FIXME dans les commentaires pour marquer qu'un certain code est erroné et ne peut pas fonctionner et doit être corrigé à temps.
1. [Obligatoire] Lorsque vous utilisez des expressions régulières, faites bon usage de sa fonction de pré-compilation pour accélérer efficacement la correspondance des expressions régulières.
Remarque : Ne le définissez pas dans le corps de la méthode : Pattern pattern = Pattern.compile (rule);
2 [Obligatoire] Lorsque la vitesse appelle les attributs de la classe POJO, il est recommandé de le faire directement. utilisez le nom de l'attribut pour obtenir la valeur. Le moteur de modèle appellera automatiquement getXxx() de POJO selon la spécification. S'il s'agit d'une variable de type de données de base booléenne (le nom booléen n'a pas besoin d'être préfixé par is), le isXxx(. ) la méthode sera automatiquement appelée.
Remarque : Notez que s'il s'agit d'un objet de classe wrapper booléen, la méthode getXxx() sera appelée en premier.
3. [Obligatoire] Les variables envoyées à la page en arrière-plan doivent être ajoutées avec $!{var} - un point d'exclamation au milieu.
Explication : Si var=null ou n'existe pas, alors ${var} sera affiché directement sur la page.
4. [Obligatoire] Notez que Math.random() renvoie un type double. Notez que la plage de valeurs est 0 ≤ Pour les nombres aléatoires, n'agrandissez pas x de plusieurs fois 10, puis arrondissez-le. directement la méthode de l’objet Random.
5. [Obligatoire] Obtenez le nombre actuel de millisecondes System.currentTimeMillis(); au lieu de new Date().getTime();
Remarque : Si vous souhaitez obtenir une valeur temporelle en nanosecondes plus précise. , utilisez System.nanoTime(). Dans JDK8, il est recommandé d'utiliser la classe Instant pour des scénarios tels que le temps statistique.
6. [Recommandation] Essayez de ne pas ajouter de déclarations de variables et d'opérateurs logiques à la machine virtuelle, encore moins de logique complexe au modèle de machine virtuelle.
7. [Recommandation] La taille doit être spécifiée lors de la construction ou de l'initialisation de toute structure de données pour éviter une croissance illimitée de la structure de données et une consommation de mémoire.
8. [Recommandation] Pour les "codes et configurations clairement hors d'usage", tels que les méthodes, variables, classes, fichiers de configuration, attributs de configuration dynamiques, etc., vous devez résolument les nettoyer du programme pour éviter causant trop de déchets.
1 [Obligatoire] Ne capturez pas les classes d'exceptions d'exécution définies dans la bibliothèque de classes Java qui héritent de RuntimeException, telles que : IndexOutOfBoundsException. / NullPointerException, ce type d'exception est évité par la pré-vérification des programmeurs pour garantir la robustesse du programme.
Exemple positif : if(obj != null) {...}
Contre-exemple : try { obj.method() } catch(NullPointerException e){...}
2. [Obligatoire] N'utilisez pas d'exceptions pour le contrôle de processus ou le contrôle conditionnel, car l'efficacité du traitement des exceptions est inférieure à celle des branches conditionnelles.
3. [Obligatoire] Essayez de récupérer une grande section de code, ce qui est irresponsable. Veuillez faire la distinction entre le code stable et le code instable lors de la capture. Le code stable fait référence à un code qui ne se trompera pas quoi qu'il arrive. Pour détecter le code instable, essayez de distinguer autant que possible le type d'exception, puis gérez l'exception correspondante.
4. [Obligatoire] Attrapez une exception afin de la gérer. Ne l'attrapez pas et ne la supprimez pas sans rien traiter. Si vous ne souhaitez pas la gérer, veuillez lancer l'exception à son appelant. L'utilisateur professionnel le plus externe doit gérer les exceptions et les convertir en contenu que les utilisateurs peuvent comprendre.
5. [Obligatoire] Placez le bloc try dans le code de transaction. Après avoir détecté l'exception, si vous devez annuler la transaction, vous devez faire attention à l'annuler manuellement.
6. [Obligatoire] Le bloc final doit fermer l'objet ressource et l'objet flux, et essayer-catch s'il y a une exception.
Remarque : si JDK7, vous pouvez utiliser la méthode try-with-resources.
7. [Obligatoire] Return ne peut pas être utilisé dans le bloc final. Après le retour dans le bloc final, la méthode termine l'exécution et l'instruction return dans le bloc try ne sera pas exécutée.
8. [Obligatoire] Les exceptions de capture et les exceptions de lancement doivent correspondre exactement, ou l'exception de capture doit être la classe parent de l'exception de lancement.
Explication : Si l'adversaire est censé lancer une balle d'hortensia mais reçoit en réalité un lancer du poids, une situation inattendue se produira.
9. [Recommandation] La valeur de retour de la méthode peut être nulle. Il n'est pas obligatoire de renvoyer une collection vide ou un objet vide. Des commentaires doivent être ajoutés pour expliquer en détail dans quelles circonstances une valeur nulle sera renvoyée. L'appelant doit effectuer un jugement nul pour éviter les problèmes NPE.
Remarque : Cette spécification indique clairement que la prévention des NPE relève de la responsabilité de l'appelant. Même si la méthode appelée renvoie une collection vide ou un objet vide, ce n'est pas une situation sans souci pour l'appelant. Elle doit prendre en compte la situation où null est renvoyé dans des scénarios tels qu'un échec d'appel à distance, une exception d'exécution, etc.
10. [Recommandation] La prévention du NPE est la formation de base des programmeurs. Faites attention aux scénarios dans lesquels le NPE se produit :
1) Le type de retour est un type de données compressé, qui peut être nul. au jugement lors du renvoi d’une valeur int nulle.
Contre-exemple : public int f(){ return Integer object}; S'il est nul, il déballera automatiquement et lancera NPE.
2) Le résultat de la requête de la base de données peut être nul.
3) Même si l'élément de la collection estNotEmpty, l'élément de données récupéré peut être nul.
4) Un jugement NPE est requis pour les objets renvoyés par des appels à distance.
5) Pour les données obtenues en Session, il est recommandé de vérifier NPE pour éviter les pointeurs nuls.
6) Les appels en cascade à obj.getA().getB().getC(); une série d'appels peuvent facilement provoquer un NPE.
11. [Recommandation] Qu'il s'agisse d'utiliser « lancer une exception » ou « retourner le code d'erreur » dans le code. Pour les interfaces ouvertes http/api en dehors de l'entreprise, le « code d'erreur » doit être utilisé dans l'application, le lancement d'exception est ; recommandé ; dans toutes les applications. La priorité est donnée à l'utilisation de la méthode Result pour les appels RPC, encapsulant isSuccess, le « code d'erreur » et les « informations brèves sur l'erreur ». Remarque : Raisons de l'utilisation de la méthode Result pour le retour de la méthode RPC :
1) En utilisant la méthode de retour d'exception, une erreur d'exécution se produira si l'appelant ne l'attrape pas.
2) Si vous n'ajoutez pas d'informations sur la pile, juste de nouvelles exceptions personnalisées et ajoutez votre propre compréhension du message d'erreur, cela ne sera pas d'une grande aide à l'appelant pour résoudre le problème. Si des informations sur la pile sont ajoutées, la perte de performances de sérialisation et de transmission des données constitue également un problème en cas d'erreurs d'appel fréquentes.
12. [Recommandé] Lors de la définition d'exceptions non cochées/cochées, évitez d'utiliser RuntimeException pour lancer directement, et il n'est pas autorisé de lancer des exceptions ou des exceptions personnalisées Throwable avec une signification commerciale. Nous recommandons les exceptions personnalisées qui ont été définies dans l'industrie, telles que : DAOException / ServiceException, etc.
13. [Référence] Évitez les codes en double (Ne vous répétez pas), c'est-à-dire le principe DRY. Remarque : copier et coller du code à volonté entraînera inévitablement une duplication du code. Lorsqu'une modification sera nécessaire à l'avenir, toutes les copies devront être modifiées, ce qui est facile à manquer. Extrayez des méthodes communes, des classes publiques abstraites ou même des modules partagés si nécessaire.
Exemple positif : il existe plusieurs méthodes publiques dans une classe, et elles doivent toutes effectuer plusieurs lignes des mêmes opérations de vérification de paramètres. À ce stade, veuillez extraire :
private boolean checkParam(DTO dto). {...}
1. [Obligatoire] L'application ne peut pas utiliser directement l'API dans le système de journalisation (Log4j, Logback), mais doit s'appuyer sur l'API dans le framework de journalisation SLF4J et utiliser le mode façade. Le cadre de journalisation est propice à la maintenance et à l’unification des méthodes de traitement des journaux pour chaque catégorie.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
[Obligatoire] Le fichier journal est Il est recommandé d'économiser au moins 15 jours, car certaines anomalies ont la particularité de se produire avec une fréquence de "semaines".
3. [Obligatoire] Méthode de dénomination pour les journaux étendus dans les applications (telles que la gestion, la surveillance temporaire, les journaux d'accès, etc.) : appName_logType_logName.log. logType : type de journal, les catégories recommandées incluent stats/desc/monitor/visit, etc. ; logName : description du journal. L'avantage de ce type de dénomination : vous pouvez savoir à quelle application appartient le fichier journal, de quel type et à quoi sert le nom du fichier, ce qui est également utile pour la classification et la recherche.
Exemple positif : surveillez séparément les exceptions de conversion de fuseau horaire dans l'application mppserver, telles que : mppserver_monitor_timeZoneConvert.log Remarque : Il est recommandé de classer les journaux d'erreurs et les journaux d'entreprise doivent être stockés séparément autant que possible. est pratique pour les développeurs de visualiser et de faciliter l'examen via les journaux. Le système est surveillé en temps réel.
4. [Obligatoire] Pour la sortie du journal au niveau trace/débogage/info, vous devez utiliser un formulaire de sortie conditionnelle ou utiliser des espaces réservés.
Description : logger.debug("Traitement du commerce avec l'identifiant : " + id + " symbole : " + symbole); Si le niveau de journalisation est averti, le journal ci-dessus ne sera pas imprimé, mais l'opération d'épissage de chaîne sera exécuté. Si le symbole est un objet, la méthode toString() sera exécutée, ce qui gaspille les ressources du système. Après avoir effectué les opérations ci-dessus, le journal final n'est pas imprimé.
Exemple positif : (condition)
if (logger.isDebugEnabled()) {
logger.debug("Traitement du commerce avec l'identifiant : " + id + " symbole : " + symbole);
}
Exemple positif : (placeholder)
logger.debug("Traitement du commerce avec l'identifiant : {} symbole : {} ", id, symbole);
[Obligatoire] Éviter la duplication À imprimer journaux et gaspiller de l'espace disque, assurez-vous de définir additivity=false dans log4j.xml.
Exemple positif :
6. [Obligatoire] Les informations anormales doivent inclure deux types d'informations : les informations sur la scène du crime. et des informations sur la pile d'exceptions. Sinon, jetez-le.
Exemple positif : logger.error (divers paramètres ou objets toString + "_" + e.getMessage(), e);
7 [Recommandé] Vous pouvez utiliser le niveau de journal d'avertissement pour enregistrer l'utilisateur. entrée En cas d'erreurs de paramètres, les utilisateurs ne pourront pas éviter les plaintes. Faites attention au niveau de sortie du journal. Le niveau d'erreur enregistre uniquement les informations d'erreur importantes telles que les erreurs de logique système et les exceptions. Si cela n'est pas nécessaire, veuillez ne pas saisir le niveau d'erreur dans ce scénario.
8. [Recommandé] Enregistrez soigneusement les journaux. Il est interdit de générer des journaux de débogage dans l'environnement de production ; de générer des journaux d'informations de manière sélective ; si vous utilisez warn pour enregistrer des informations sur le comportement de l'entreprise lors de son premier lancement, vous devez faire attention à la quantité de journaux générés pour éviter de saturer le disque du serveur, et n'oubliez pas de supprimer ces journaux d'observation à temps.
Remarque : La sortie d'un grand nombre de journaux invalides n'est pas propice à l'amélioration des performances du système et ne permet pas de localiser rapidement les points d'erreur. Lorsque vous enregistrez des journaux, pensez : est-ce que quelqu'un lit vraiment ces journaux ? Que pouvez-vous faire après avoir vu ce journal ? Cela peut-il apporter des avantages au dépannage ?
1 [Obligatoire] Les champs qui expriment la notion de oui ou de non doivent être nommés en utilisant is_xxx, et le. type de données Il s'agit d'un tinyint non signé (1 signifie oui, 0 signifie non). Cette règle s'applique également à la création de tables ODPS.
Remarque : Si un champ est un nombre non négatif, il doit être non signé.
2. [Obligatoire] Les noms de tables et de champs doivent utiliser des lettres minuscules ou des chiffres au début, et seuls les chiffres entre deux traits de soulignement sont interdits. La modification des noms de champs de base de données est très coûteuse car la pré-version n'est pas possible, les noms de champs doivent donc être soigneusement examinés.
Exemple positif : getter_admin, task_config, level3_name
Contre-exemple : GetterAdmin, taskConfig, level_3_name
3 [Obligatoire] N'utilisez pas de noms au pluriel dans les noms de table. Remarque : Le nom de la table ne doit représenter que le contenu de l'entité dans la table et ne doit pas représenter le nombre d'entités. Le nom de la classe DO correspondante est également au singulier, ce qui est cohérent avec les habitudes d'expression.
4. [Obligatoire] Désactivez les mots réservés, tels que desc, range, match, delay, etc. Veuillez vous référer aux mots réservés officiels de MySQL.
5. [Obligatoire] Le nom d'index unique est uk_field name ; le nom d'index commun est idx_field name. Remarque : uk_ est une clé unique ; idx_ est l'abréviation d'index.
6. [Obligatoire] Le type décimal est décimal, et float et double sont interdits.
Remarque : Il existe un problème de perte de précision lors du stockage de float et double, et il est possible d'obtenir des résultats incorrects lors de la comparaison des valeurs. Si la plage des données stockées dépasse la plage des décimales, il est recommandé de diviser les données en nombres entiers et décimaux et de les stocker séparément.
7. [Obligatoire] Si les longueurs des chaînes stockées sont presque égales, utilisez le type de chaîne char de longueur fixe.
8. [Obligatoire] Varchar est une chaîne de longueur variable, aucun espace de stockage n'est alloué à l'avance et la longueur ne doit pas dépasser 5000. Si la longueur de stockage est supérieure à cette valeur, définissez le type de champ comme texte, créez une table séparée et utilisez la clé primaire pour correspondre, afin d'éviter d'affecter l'efficacité de l'index des autres champs.
9. [Obligatoire] La table doit avoir trois champs : id, gmt_create, gmt_modified.
Remarque : l'identifiant doit être la clé primaire, le type est bigint non signé, incrémenté automatiquement pour une seule table et la taille du pas est de 1. Les types de gmt_create et gmt_modified sont tous des types date_time.
10. [Recommandation] Il est préférable de nommer la table avec « nom commercial_fonction de la table ». Exemple positif : Tiger_task / Tiger_reader / mpp_config
11 [Recommandation] Le nom de la bibliothèque et le nom de l'application doivent être aussi cohérents que possible.
12. [Recommandation] Si vous modifiez la signification d'un champ ou ajoutez le statut représenté par un champ, vous devez mettre à jour les commentaires du champ en temps opportun.
13. [Recommandé] Autorisez une redondance appropriée dans les champs pour améliorer les performances, mais la synchronisation des données doit être prise en compte. Les champs redondants doivent suivre :
1) Champs qui ne sont pas fréquemment modifiés. 2) Ce n'est pas un champ varchar super long, encore moins un champ de texte.
Exemple positif : le nom de la catégorie de produits est fréquemment utilisé, la longueur du champ est courte et le nom est fondamentalement inchangé. Le nom de la catégorie peut être stocké de manière redondante dans la table associée pour éviter les requêtes associées.
14. [Recommandation] Le partitionnement de bases de données et de tables n'est recommandé que si le nombre de lignes dans une seule table dépasse 5 millions ou si la capacité d'une seule table dépasse 2 Go.
Remarque : Si le volume de données ne devrait pas atteindre ce niveau dans trois ans, veuillez ne pas diviser la base de données en tableaux lors de la création du tableau.
15. [Référence] Une longueur de stockage de caractères appropriée permet non seulement d'économiser de l'espace dans la table de base de données et du stockage d'index, mais, plus important encore, d'améliorer la vitesse de récupération.
Exemple positif : L'âge d'une personne est un tinyint non signé (indiquant la plage 0-255, la durée de vie d'un être humain ne dépassera pas 255 ans la tortue doit être smallint, mais si c'est le cas) ; l'âge du soleil, il doit être int ; si les âges de toutes les étoiles sont additionnés, alors bigint doit être utilisé.
1. [Obligatoire] Les champs ayant des caractéristiques uniques en entreprise, même s'il s'agit de champs combinés, doivent être intégrés dans un index unique.
Remarque : Ne pensez pas que l'index unique affecte la vitesse d'insertion. Cette perte de vitesse peut être ignorée, mais l'amélioration de la vitesse de recherche est évidente, même s'il existe un contrôle de somme de contrôle très complet ; la couche application, tant qu'il n'y a pas d'index uniques, selon la loi de Murphy, doit contenir des données sales.
2. [Obligatoire] Il est interdit de rejoindre plus de trois tables. Les types de données des champs qui doivent être joints doivent être absolument cohérents ; lors de l'interrogation de corrélations multi-tables, assurez-vous que les champs corrélés doivent avoir des index.
Explication : Même si vous rejoignez une table double, vous devez faire attention aux index de table et aux performances SQL.
3. [Obligatoire] Lors de la création d'un index sur un champ varchar, la longueur de l'index doit être spécifiée. Il n'est pas nécessaire d'indexer l'intégralité du champ. La longueur de l'index est déterminée en fonction de la distinction réelle du texte.
Remarque : La longueur et la distinction de l'index sont une paire de contradictions. Généralement, pour les données de type chaîne, la distinction atteindra 90 % pour un index d'une longueur de 20. Vous pouvez utiliser count. (gauche distincte (nom de la colonne, déterminé par la distinction de la longueur de l'index))/count(*).
4. [Obligatoire] Le flou à gauche ou le flou complet est strictement interdit dans la recherche de pages. Si nécessaire, veuillez utiliser les moteurs de recherche pour résoudre le problème.
Description : Le fichier d'index a la fonctionnalité de correspondance de préfixe la plus à gauche de B-Tree. Si la valeur à gauche est indéterminée, cet index ne peut pas être utilisé.
5. [Recommandation] S'il y a un ordre par scénario, veuillez faire attention à l'ordre de l'index. Le dernier champ trié par fait partie de l'index combiné et est placé à la fin de l'ordre de combinaison d'index pour éviter file_sort et affecter les performances des requêtes.
Exemple positif : où a=? et b=? order by c; Index : a_b_c
Contre-exemple : s'il y a une recherche par plage dans l'index, alors l'ordre de l'index ne peut pas être utilisé, tel que : WHERE a> ;10 ORDER BY b; L'index a_b ne peut pas être trié.
6. [Recommandé] Utilisez des index de couverture pour effectuer des opérations de requête afin d'éviter les opérations de retour de table.
Explication : Si un livre a besoin de connaître le titre du chapitre 11, ouvrira-t-il la page correspondant au chapitre 11 ? Parcourez simplement le répertoire. Ce répertoire sert d'index de couverture.
Exemple positif : les types d'index qui peuvent être créés : index de clé primaire, index unique, index ordinaire et index de couverture sont un effet d'une requête. Avec le résultat d'explication, la colonne supplémentaire apparaîtra : using. indice.
7. [Recommandation] Utilisez une corrélation retardée ou une sous-requête pour optimiser les scénarios multi-pagination.
Explication : MySQL ne saute pas la ligne de décalage, mais prend les lignes offset+N, puis renvoie la ligne de décalage avant d'abandonner, et renvoie N lignes. Lorsque le décalage est particulièrement important, l'efficacité est très faible. , ou Contrôlez le nombre total de pages renvoyées ou effectuez des réécritures SQL sur les pages qui dépassent un certain seuil.
Exemple positif : localisez d'abord rapidement le segment d'identifiant qui doit être obtenu, puis associez : SELECT a.* FROM table 1 a, (sélectionnez l'identifiant dans la table 1 où condition LIMIT 100000,20) b où a.id= b.id
8. [Recommandé] L'objectif de l'optimisation des performances SQL : atteindre au moins le niveau de plage, l'exigence est le niveau de référence, si cela peut être const, c'est mieux.
Explication :
1) Consts Il y a au plus une ligne correspondante (clé primaire ou index unique) dans une seule table, et les données peuvent être lues pendant la phase d'optimisation.
2) ref fait référence à l'utilisation d'un index normal.
3) range effectue une recherche par plage sur l'index.
Contre-exemple : le résultat de la table d'explication, type=index, est une analyse complète du fichier physique d'index, qui est très lente. Ce niveau d'index est inférieur à la plage et est éclipsé par une table complète. balayage.
9. [Recommandation] Lors de la construction d'un index combiné, le plus différencié se trouve à l'extrême gauche. Exemple positif : si où a=? et b=?, la colonne a est presque proche d'une valeur unique, alors il vous suffit de créer un seul index idx_a.
Remarque : Lorsqu'il existe une condition de jugement mixte de signe non égal et de signe égal, lors de la construction de l'index, veuillez placer la colonne de la condition de signe égal devant. Par exemple : où a>? et b=? Alors, même si a a un degré de distinction plus élevé, b doit être placé au premier plan de l'index.
10. [Référence] Évitez les malentendus extrêmes suivants lors de la création d'un index :
1) Malentendu qu'une requête nécessite un index.
2) Croire à tort que les index vont consommer de l'espace et ralentir sérieusement les mises à jour et les nouveaux ajouts.
3) On croit à tort que les index uniques doivent être résolus en "vérifiant d'abord puis en insérant" au niveau de la couche d'application.
1. [Obligatoire] Ne pas utiliser count (nom de colonne) ou count (constante) au lieu de count(*) est la norme définie. par SQL92 La syntaxe de comptage des lignes n'a rien à voir avec la base de données ou NULL ou non NULL.
Remarque : count(*) comptera les lignes avec des valeurs NULL, tandis que count(column name) ne comptera pas les lignes avec des valeurs NULL dans cette colonne.
2. [Obligatoire] count(distinct col) Calculez le nombre de nombres distincts dans la colonne sauf NULL. Notez que count(distinct col1, col2) renvoie 0 si l'une des colonnes est entièrement NULL, même si l'autre colonne a des valeurs différentes.
3. [Obligatoire] Lorsque les valeurs d'une certaine colonne sont toutes NULL, le résultat de retour de count(col) est 0, mais le résultat de retour de sum(col) est NULL, vous devez donc faire attention. au problème NPE lors de l'utilisation de sum().
Exemple positif : Vous pouvez utiliser la méthode suivante pour éviter le problème NPE de somme : SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;
4. Obligatoire] utilisez ISNULL() pour déterminer s'il s'agit d'une valeur NULL. Remarque : Une comparaison directe de NULL avec n’importe quelle valeur renvoie NULL.
Explication : 1) NULL<>Le résultat renvoyé de NULL est NULL, pas faux.
2) Le résultat de retour de NULL=NULL est NULL, ce n'est pas vrai.
3) Le résultat renvoyé par NULL<>1 est NULL, ce n'est pas vrai.
5. [Obligatoire] Lors de l'écriture de la logique de requête de pagination dans le code, si le nombre est 0, il doit être renvoyé directement pour éviter d'exécuter des instructions de pagination ultérieures.
6. [Obligatoire] Les clés étrangères et les cascades ne sont pas autorisées. Tous les concepts de clés étrangères doivent être résolus au niveau de la couche application. Remarque : (Explication du concept) student_id dans la table des étudiants est la clé primaire, puis student_id dans la table des notes est la clé étrangère. Si le student_id dans la table des étudiants est mis à jour et le student_id dans la table des notes est mis à jour en même temps, il s'agit d'une mise à jour en cascade. Les clés étrangères et les mises à jour en cascade conviennent à une faible concurrence sur une seule machine, mais ne conviennent pas aux clusters distribués et à haute concurrence ; les mises à jour en cascade sont fortement bloquantes et risquent de provoquer des tempêtes de mises à jour de la base de données qui affectent la vitesse d'insertion de la base de données ; .
7. [Obligatoire] L'utilisation de procédures stockées est interdite. Les procédures stockées sont difficiles à déboguer et à développer et n'ont aucune portabilité.
8. [Obligatoire] Lors de la révision des données, lors de la suppression ou de la modification d'enregistrements, vous devez d'abord sélectionner pour éviter une suppression accidentelle, puis exécuter l'instruction de mise à jour uniquement après avoir confirmé qu'elle est correcte.
9. [Recommandation] Évitez le fonctionnement si cela peut être évité, vous devez évaluer soigneusement le nombre d'éléments de collecte derrière et le contrôler à moins de 1 000.
10. [Référence] S'il y a un besoin de globalisation, tous les stockages et représentations de caractères sont codés en utf-8, alors notez la méthode de comptage de caractères :
Explication : SELECT LENGTH ("Easy Work" ) ; Renvoie à 12 SELECT CHARACTER_LENGTH ("Easy Work"); Renvoie à 4 Si vous souhaitez utiliser des expressions, utilisez utfmb4 pour le stockage et faites attention à la différence entre celui-ci et l'encodage utf-8.
11. [Référence] TRUNCATE TABLE est plus rapide que DELETE et utilise moins de ressources système et du journal des transactions. Cependant, TRUNCATE n'a aucune transaction et ne déclenche pas de déclencheurs, ce qui peut provoquer des accidents. Par conséquent, il n'est pas recommandé d'utiliser cette instruction. dans le code de développement.
Explication : TRUNCATE TABLE est fonctionnellement identique à l'instruction DELETE sans clause WHERE.
1. [Obligatoire] Dans les requêtes de table, n'utilisez pas * car la liste des champs de la requête doit être clairement indiquée.
Explication :
1) Augmentez le coût d'analyse de l'analyseur de requêtes.
2) L'ajout ou la soustraction de champs est facile à être incohérent avec la configuration de resultMap.
2. [Obligatoire] L'attribut booléen de la classe POJO ne peut pas être ajouté avec is, mais le champ de la base de données doit être ajouté avec is_, ce qui nécessite un mappage entre les champs et les attributs dans resultMap.
Remarque : reportez-vous aux réglementations de définition de classe POJO et de définition de champ de base de données. Il est nécessaire d'ajouter un mappage dans sql.xml.
3. [Obligatoire] N'utilisez pas resultClass comme paramètre de retour Même si tous les noms d'attributs de classe correspondent aux champs de la base de données, ils doivent quand même être définis, à l'inverse, chaque table doit en avoir un correspondant ;
Description : Configurez la relation de mappage pour découpler les champs des classes DO pour une maintenance facile.
4. [Obligatoire] Veuillez faire attention à l'utilisation des paramètres dans la configuration XML : #{}, #param# N'utilisez pas ${}. Cette méthode est sujette à l'injection SQL.
5. [Obligatoire] Le queryForList(String StatementName, int start, int size) fourni avec iBATIS n'est pas recommandé.
Explication : La méthode d'implémentation consiste à obtenir tous les enregistrements de l'instruction SQL correspondant à StatementName dans la base de données, puis à obtenir le sous-ensemble de début et de taille via la sous-liste qui s'est produite en ligne pour cette raison.
Exemple positif : introduisez #start#, #size#
dans sqlmap.xml Map
map.put("start" , start);
map.put("size", size);
6. [Obligatoire] Il n'est pas autorisé d'utiliser directement HashMap et Hashtable comme sortie du jeu de résultats de la requête.
7. [Obligatoire] Lors de la mise à jour de l'enregistrement de la table de données, vous devez également mettre à jour la valeur du champ gmt_modified correspondant de l'enregistrement à l'heure actuelle.
8. [Recommandé] N'écrivez pas une interface de mise à jour de données volumineuse et complète. Transmettez-la en tant que classe POJO, qu'il s'agisse de votre propre champ de mise à jour cible, mettez à jour l'ensemble de tables c1=value1, c2=value2, c3. =valeur3. Lors de l'exécution de SQL, essayez de ne pas mettre à jour les champs non modifiés. Premièrement, c'est sujet aux erreurs. Deuxièmement, c'est inefficace. Troisièmement, binlog augmente le stockage.
9. [Référence] N'abusez pas des transactions @Transactional. Les transactions affecteront le QPS de la base de données. De plus, lorsque des transactions sont utilisées, diverses solutions de restauration doivent être envisagées, notamment la restauration du cache, la restauration du moteur de recherche, la compensation des messages, la correction statistique, etc.
10. [Référence] La valeur compareValue dans
1 [Recommandé] Par défaut, la couche supérieure de la figure dépend de la couche inférieure et de la flèche. La relation indique une dépendance directe, telle que : La couche d'interface ouverte peut s'appuyer sur la couche Web ou s'appuyer directement sur la couche Service, et ainsi de suite :
Couche d'interface ouverte : Elle peut directement encapsuler l'interface de Service et l'exposer dans un Interface RPC ; encapsulez-le dans une interface http via la couche de contrôle de passerelle, etc.
Couche d'affichage du terminal : Les modèles de chaque terminal restituent et exécutent la couche d'affichage. Actuellement, les principaux sont le rendu rapide, le rendu JS, le rendu JSP, la couche d'affichage mobile, etc.
Couche Web : principalement transmission du contrôle d'accès, vérification de divers paramètres de base, ou simplement traitement des services non réutilisés, etc.
Couche de service : une couche de service de logique métier relativement spécifique.
Couche gestionnaire : une couche de traitement métier générale, qui présente les caractéristiques suivantes :
1) La couche encapsulée par la plateforme tierce, prétraitant les résultats renvoyés et convertissant les informations d'exception
2) L'absorption des capacités générales de la couche Service, telles que les solutions de mise en cache et le traitement général du middleware 3) Interagir avec la couche DAO pour encapsuler les capacités commerciales générales de DAO ; Couche DAO : couche d'accès aux données, qui interagit avec MySQL, Oracle et Hbase sous-jacents pour les données.
Interfaces externes ou plateformes tierces : y compris les interfaces ouvertes RPC d'autres départements, les plateformes de base et les interfaces HTTP d'autres entreprises.
2. [Référence] (Protocole de gestion des exceptions hiérarchiques) Dans la couche DAO, il existe de nombreux types d'exceptions générées. Il est impossible d'intercepter des exceptions précises. Utilisez la méthode catch(Exception e) et lancez une nouvelle DAOException(. e). Il n'est pas nécessaire d'imprimer les journaux, car les journaux doivent être capturés et écrits dans des fichiers journaux au niveau de la couche Gestionnaire/Service. Si le même serveur imprime à nouveau les journaux, les performances et le stockage seront gaspillés. Lorsqu'une exception se produit dans la couche Service, les informations du journal doivent être enregistrées sur le disque et les informations sur les paramètres doivent être incluses autant que possible, ce qui équivaut à protéger la scène du crime. Si la couche Manager et le Service sont déployés sur la même machine, la méthode de journalisation est cohérente avec le traitement de la couche DAO. S'ils sont déployés séparément, la méthode de journalisation est cohérente avec le Service. La couche Web ne doit jamais continuer à générer des exceptions.
Comme elle est déjà au niveau supérieur, il n'y a aucun moyen de continuer à gérer les exceptions. Si vous réalisez que cette exception entraînera un échec de rendu normal de la page, vous devez sauter. directement à une page d'erreur conviviale et faites de votre mieux pour afficher un message d'erreur convivial. La couche d'interface ouverte doit gérer les exceptions et les renvoyer sous forme de codes d'erreur et de messages d'erreur.
3. [Référence] Spécification du modèle de domaine hiérarchique :
DO (Data Object) : correspond à la structure de la table de la base de données un à un et transmet les objets de la source de données vers le haut via la couche DAO.
DTO (Data Transfer Object) : Objet de transfert de données, un objet transféré en externe par Service et Manager.
BO (Business Object) : Objet métier. Un objet qui encapsule la logique métier et peut être généré par la couche Service.
QUERY : Objet de requête de données, chaque couche reçoit des requêtes de requête de la couche supérieure. Remarque : il est interdit à l'encapsulation de requêtes avec plus de 2 paramètres d'utiliser la classe Map pour la transmission.
VO (View Object) : Objet de couche d'affichage, généralement un objet transmis par le Web à la couche du moteur de rendu du modèle.
1) Format GroupID : com.{Société/BU}.Business Line.[Sous-Business Line], jusqu'à 4 niveaux.
Description : {Entreprise/BU} Par exemple : alibaba/taobao/tmall/aliexpress et les autres niveaux de sous-activité de la BU sont facultatifs ;
Exemple positif : com.taobao.jstorm ou com.alibaba.dubbo.register
2) Format ArtifactID : nom de la ligne de produit-nom du module. La sémantique n'est ni répétée ni omise. Rendez-vous d'abord au centre d'entrepôt pour vérifier.
Exemple positif : dubbo-client / fastjson-api / jstorm-tool 3) Version : Veuillez vous référer aux détails ci-dessous.
2. [Obligatoire] Méthode de dénomination du numéro de version de la bibliothèque tierce : numéro de version majeure, numéro de révision mineure
1) Numéro de version majeure : considéré comme une modification d'API incompatible ou une fonctionnalité ajoutée. fonctionnalités qui changent la direction du produit.
2) Numéro de version mineure : traité comme un ajout fonctionnel rétrocompatible (nouvelles classes, interfaces, etc.).
3) Numéro de révision : corrigez les bugs, améliorez les fonctions sans modifier les signatures de méthode et maintenez la compatibilité API.
Remarque : le numéro de version de départ doit être : 1.0.0, et non 0.0.1
3 [Obligatoire] Les applications en ligne ne s'appuient pas sur la version SNAPSHOT (à l'exception des packages de sécurité officiellement publiés) ; bibliothèques La méthode de mise à niveau du numéro de version RELEASE +1 doit être utilisée, et le numéro de version ne peut pas être écrasé et mis à niveau. Vous devez vous rendre à l'entrepôt central pour vérification.
Remarque : Ne pas s'appuyer sur la version SNAPSHOT garantit l'idempotence de la version de l'application. De plus, cela peut également accélérer le packaging et la construction lors de la compilation.
4. [Obligatoire] L'ajout ou la mise à niveau de la bibliothèque tierce conservera les résultats d'arbitrage des autres packages jar, à l'exception des points de fonction. S'il y a des changements, ils doivent être clairement évalués et vérifiés. Il est recommandé de comparer les informations avant et après dependency:resolve. Si les résultats de l'arbitrage sont complètement incohérents, utilisez la commande dependency:tree pour rechercher les différences et effectuer
6. [Obligatoire] Lorsque vous utilisez un groupe de bibliothèques tiers, une variable de version unifiée doit être définie pour éviter l'incohérence du numéro de version.
Description : Dépend de springframework-core, -context, -beans. Ils sont tous de la même version. Vous pouvez définir une variable pour enregistrer la version : ${spring.version}. Lors de la définition des dépendances, faites référence à ceci. version.
7. [Obligatoire] Il est interdit d'avoir le même GroupId, le même ArtifactId, mais des Versions différentes dans les dépendances pom des sous-projets.
Remarque : lors du débogage local, le numéro de version spécifié par chaque sous-projet sera utilisé, mais lors de la fusion dans une guerre, un seul numéro de version peut apparaître dans le répertoire final lib. Il y a eu des précédents où le débogage hors ligne était correct mais des problèmes survenaient lors de la mise en ligne.
8. [Recommandation] Placez les déclarations de dépendance dans tous les fichiers pom dans le bloc d'instructions
Remarque :
9. [Recommandation] La bibliothèque tierce devrait essayer de ne pas avoir d'éléments de configuration, et au moins ne pas ajouter d'éléments de configuration supplémentaires.
10. [Référence] Afin d'éviter les conflits de dépendances lors de l'application de bibliothèques tierces, les éditeurs de bibliothèques tierces doivent suivre les principes suivants :
1) Le principe de simplicité et de contrôlabilité. Supprimez toutes les API et dépendances inutiles, y compris uniquement l'API de service, les objets de modèle de domaine nécessaires, les classes Utils, les constantes, les énumérations, etc. Si vous comptez sur d'autres bibliothèques tierces, essayez de les introduire via le système fourni, permettant aux utilisateurs des bibliothèques tierces de s'appuyer sur des numéros de version spécifiques. Il n'y a pas d'implémentation spécifique du journal et vous comptez uniquement sur le framework de journalisation.
2) Principe de traçabilité stable. Les modifications apportées à chaque version doivent être enregistrées, qui gère la bibliothèque tierce et où se trouve le code source, tous doivent être facilement accessibles. Le comportement des bibliothèques publiques tierces ne devrait pas changer à moins que l'utilisateur ne mette activement à niveau la version.
1. [Recommandé] Pour les serveurs à haute concurrence, il est recommandé de réduire le délai d'attente time_wait du protocole TCP. Remarque : Par défaut, le système d'exploitation fermera les connexions dans l'état time_wait après 240 secondes. En cas d'accès simultané élevé, le serveur peut ne pas être en mesure d'établir de nouvelles connexions car il y a trop de connexions dans time_wait, vous devez donc ajuster cette valeur. sur le serveur.
Exemple positif : Sur le serveur Linux, veuillez modifier la valeur par défaut (secondes) en changeant le fichier /etc/sysctl.conf : net.ipv4.tcp_fin_timeout = 30
2. valeur Le nombre maximum de descripteurs de fichiers (File Descriptor, en abrégé fd) pris en charge par le serveur.
Remarque : La conception des systèmes d'exploitation grand public est de gérer les connexions TCP/UDP de la même manière que les fichiers, c'est-à-dire qu'une connexion correspond à un fd. Le nombre par défaut de FD pris en charge par les serveurs Linux grand public est de 1 024. Lorsque le nombre de connexions simultanées est important, il est facile de provoquer des erreurs « ouvrir trop de fichiers » en raison d'un nombre insuffisant de FD, entraînant l'échec de l'établissement de nouvelles connexions. Il est recommandé d'augmenter plusieurs fois le nombre maximum de handles pris en charge par le serveur Linux (en fonction de la quantité de mémoire sur le serveur).
3. [Recommandé] Définissez le paramètre -XX:+HeapDumpOnOutOfMemoryError sur la JVM pour permettre à la JVM de générer des informations de vidage lorsqu'elle rencontre un scénario de MOO.
Remarque : le MOO se produit avec probabilité, et même un cas se produit régulièrement tous les quelques mois. Les informations sur site lorsqu'il se produit sont très précieuses pour le dépannage.
4. [Référence] Utilisez forward pour la redirection interne du serveur ; utilisez la classe d'outils d'assemblage d'URL pour générer des adresses de redirection externes, sinon cela entraînera une maintenance d'URL incohérente et des risques de sécurité potentiels.
1. [Obligatoire] Les pages ou fonctions appartenant à l'utilisateur doivent subir une vérification de contrôle d'autorisation. Remarque : Cela empêche les utilisateurs de pouvoir accéder et utiliser les données d'autres personnes à volonté sans effectuer une vérification horizontale des autorisations, comme consulter et modifier les commandes d'autres personnes.
2. [Obligatoire] L'affichage direct des données utilisateur sensibles est interdit et les données d'affichage doivent être désensibilisées. Remarque : Lorsque vous consultez votre numéro de téléphone portable personnel, il s'affichera sous la forme : 158****9119, masquant les 4 chiffres du milieu pour éviter toute fuite de confidentialité.
3. [Obligatoire] Les paramètres SQL saisis par l'utilisateur doivent être strictement limités par la liaison des paramètres ou les valeurs du champ METADATA pour empêcher l'injection SQL et empêcher l'épissage de chaînes SQL d'accéder à la base de données.
4. [Obligatoire] La validité de tous les paramètres transmis par l'utilisateur doit être vérifiée. Remarque : Ignorer la vérification des paramètres peut entraîner :
Une taille de page excessive entraînant un débordement de mémoire
Un ordre malveillant en provoquant une requête de base de données lente
Une redirection arbitraire
Une injection SQL
Une injection de séquence inverse
Déni de service de chaîne source d'entrée régulière Description ReDoS : Java Le code JavaJava utilise des expressions régulières pour vérifier les entrées du client. Certaines méthodes d'écriture régulières n'ont aucun problème à vérifier les entrées de l'utilisateur ordinaire, mais si l'attaquant utilise une chaîne spécialement construite pour vérifier, cela peut conduire à un effet de boucle infinie.
5. [Obligatoire] Il est interdit de générer des données utilisateur qui n'ont pas été filtrées en toute sécurité ou qui n'ont pas été correctement échappées vers la page HTML.
6. [Obligatoire] Les soumissions de formulaire et AJAX doivent effectuer un filtrage de sécurité CSRF. Description : CSRF (Cross-site request forgery) est une vulnérabilité de programmation courante. Pour les applications/sites Web présentant des vulnérabilités CSRF, les attaquants peuvent construire l'URL à l'avance. Dès que l'utilisateur victime y accède, l'arrière-plan modifiera les paramètres utilisateur dans la base de données en conséquence à l'insu de l'utilisateur.
7. [Obligatoire] Lors de l'utilisation des ressources de la plateforme, telles que les messages texte, les e-mails, les appels téléphoniques, les commandes et les paiements, des restrictions anti-relecture correctes, telles que les limites de quantité, le contrôle de la fatigue et la vérification du code de vérification, doivent être mises en œuvre. pour éviter d'être abusé. Brosse, perte en capital.
Remarque : Si un code de vérification est envoyé au téléphone mobile lors de l'inscription, s'il n'y a pas de limite sur le nombre et la fréquence, cette fonction peut être utilisée pour harceler d'autres utilisateurs et provoquer un gaspillage des ressources de la plateforme SMS.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!