[Java] Manual de desarrollo de Java de Alibaba


Prefacio

提示:仅供学习参考使用

Manual de desarrollo de Java de Alibaba, siga las reglas de desarrollo tanto como sea posible en el desarrollo de Java, será de gran ayuda para la codificación ~

El contenido de este artículo es un intercambio de tecnología por parte del Departamento de Tecnología del Grupo Alibaba. Los derechos de autor pertenecen al Grupo Alibaba. Es solo para comunicación, aprendizaje e investigación. El uso comercial está prohibido. ¡Los infractores serán procesados!


1. Convenciones de programación

(1) Estilo de nombre

  1. [Obligatorio] Los nombres en el código no pueden comenzar ni terminar con un guión bajo o un signo de dólar.

    反例: _name / __name / $Object / name_ / name$ / Object$

  2. [Obligatorio] Está estrictamente prohibido utilizar una mezcla de pinyin e inglés para nombrar en el código, y no está permitido utilizar chino directamente.
    Explicación: La ortografía y la gramática inglesas correctas pueden facilitar la comprensión de los lectores y evitar la ambigüedad. Tenga en cuenta que
    se deben evitar incluso los nombres puros en pinyin.
    正例: alibaba / taobao / youku / hangzhou 等国际通用的名称, 可视同英文。
    反例: DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3

  3. [Obligatorio] El nombre de la clase utiliza el estilo UpperCamelCase y debe seguir las mayúsculas y minúsculas camel, con las siguientes excepciones: DO / BO /
    DTO / VO / AO
    正例: MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
    反例: macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

  4. [Obligatorio] Los nombres de métodos, nombres de parámetros, variables miembro y variables locales usan el estilo lowerCamelCase y deben seguir el
    formato camel.
    正例: localValue / getHttpMessage() / inputUserId

  5. [Obligatorio] Los nombres constantes deben estar en letras mayúsculas y las palabras deben estar separadas por guiones bajos. Trate de expresar una semántica completa y clara y no se sienta insatisfecho con los nombres largos.
    正例: MAX_STOCK_COUNT
    反例: MAX_COUNT

  6. [Obligatorio] El nombre de la clase abstracta comienza con Abstract o Base; el nombre de la clase de excepción termina con Exception; el
    nombre de la clase de prueba comienza con el nombre de la clase que se va a probar y termina con Test.

  7. [Obligatorio] Los corchetes son parte del tipo de matriz. La matriz se define de la siguiente manera: String[] args;
    Contraejemplo: use String args[] para definir.

  8. [Obligatorio] No lo agregue a variables de tipo booleano en la clase POJO; de lo contrario, algún análisis del marco provocará errores de serialización.
    Ejemplo de contador: el atributo definido como el tipo de datos básico booleano isDeleted, su método también es isDeleted (). Cuando el marco RPC realiza un análisis inverso, "piensa" que el nombre del atributo correspondiente se elimina, lo que hace que no se obtenga el atributo. y luego lanzar una excepción
    con frecuencia.

  9. [Obligatorio] Los nombres de los paquetes deben estar en minúsculas y debe haber una y solo una palabra en inglés con semántica natural entre los separadores de puntos. Los nombres de los paquetes siempre usan
    la forma singular, pero si el nombre de la clase tiene un significado plural, el nombre de la clase puede usar la forma plural.
    Ejemplo positivo: el nombre del paquete de la clase de herramienta de la aplicación es com.alibaba.open.util y el nombre de la clase es MessageUtils (esta regla se refiere a la
    estructura del marco Spring)

  10. 【Obligatorio】Acabar con abreviaturas completamente irregulares para evitar perder el significado del texto.
    Ejemplo contrario: la "abreviatura" de AbstractClass se denomina AbsClass y la condición "abreviatura" se denomina condi. Este tipo de
    abreviaturas arbitrarias reducen seriamente la legibilidad del código.

  11. [Recomendado] Para lograr el objetivo de la autoexplicación del código, al nombrar cualquier elemento de programación personalizado, utilice una
    combinación de palabras lo más completa posible para expresar su significado.
    正例: 从远程仓库拉取代码的类命名为 PullCodeFromRemoteRepository。
    反例: 变量 int a; 的随意命名方式。

  12. [Recomendado] Si los módulos, interfaces, clases y métodos utilizan patrones de diseño, refleje los patrones específicos al nombrarlos.
    Nota: Reflejar el patrón de diseño en el nombre ayudará a los lectores a comprender rápidamente el concepto de diseño arquitectónico.
    正例: public class OrderFactory; public class LoginProxy; public class ResourceObserver;

  13. [Recomendación] No agregue ningún modificador a los métodos y propiedades en la clase de interfaz (no agregue público), mantenga el código conciso
    y agregue comentarios Javadoc válidos. Trate de no definir variables en la interfaz, si debe definir variables, deben estar
    relacionadas con los métodos de la interfaz y son constantes básicas para toda la aplicación.
    正例: 接口方法签名: void f(); 接口基础常量表示: String COMPANY = "alibaba";
    反例: 接口方法定义: public abstract void f();
    Nota: Las interfaces en JDK8 permiten implementaciones predeterminadas, por lo que este método predeterminado es una implementación predeterminada valiosa
    para todas las clases de implementación.

  14. Hay dos conjuntos de reglas para nombrar interfaces y clases de implementación:
    1) [Obligatorio] Para las clases de Servicio y DAO, según el concepto de SOA, los servicios expuestos deben ser interfaces y las
    clases de implementación interna se distinguen de las interfaces por el sufijo de impl.
    正例: CacheServiceImpl 实现 CacheService 接口。

2) [Recomendado] Si se trata de un nombre de interfaz que describe capacidades, utilice el adjetivo correspondiente como nombre de la interfaz (normalmente en forma de –able).
正例: AbstractTranslator 实现 Translatable。

  1. [Referencia] Se recomienda que el nombre de la clase de enumeración tenga el sufijo Enum. Los nombres de los miembros de la enumeración deben estar en letras mayúsculas y las palabras deben estar separadas por guiones bajos.
    Nota: La enumeración es en realidad una clase constante especial y el constructor está obligado a ser privado de forma predeterminada.
    正例: 枚举名字为 ProcessStatusEnum 的成员名称: SUCCESS / UNKOWN_REASON。

  2. [Referencia] Convención de nomenclatura de cada capa:
    A) Convención de nomenclatura de métodos de capa de servicio/DAO
    1) Los métodos para obtener un único objeto tienen el prefijo get.
    2) Los métodos para obtener múltiples objetos tienen el prefijo lista.
    3) El método para obtener valores estadísticos tiene el prefijo recuento.
    4) El método de inserción tiene el prefijo guardar/insertar.
    5) El método de eliminación tiene el prefijo eliminar/eliminar.
    6) El método de modificación tiene el prefijo actualización.
    B) Convención de nomenclatura del modelo de dominio
    1) Objeto de datos: xxxDO, xxx es el nombre de la tabla de datos.
    2) Objeto de transferencia de datos: xxxDTO, xxx es el nombre relacionado con el campo comercial.
    3) Objeto de visualización: xxxVO, xxx es generalmente el nombre de la página web.
    4) POJO es el nombre colectivo de DO/DTO/BO/VO, y está prohibido nombrarlo xxxPOJO.

(2) Definición constante

  1. [Obligatorio] No se permite que aparezcan valores mágicos (es decir, constantes indefinidas) directamente en el código.
    反例: String key = "Id#taobao_" + tradeId; cache.put(key, value);

  2. [Obligatorio] Al inicializar long o Long, use L mayúscula en lugar de L minúscula. Las minúsculas se pueden confundir fácilmente con el número 1
    , lo que provoca malentendidos.
    Explicación: Long a = 2l; ¿Se escribe 21 como número o 2 como Long?

  3. [Recomendación] No utilice una clase constante para mantener todas las constantes, clasifíquelas según sus funciones y manténgalas por separado.
    Nota: Para una clase de constantes grande y completa, debe utilizar la función de búsqueda para localizar las constantes modificadas, lo que no favorece la comprensión ni el mantenimiento.
    正例: 缓存相关常量放在类 CacheConsts 下; 系统配置相关常量放在类 ConfigConsts 下。

  4. [Recomendación] Hay cinco niveles de reutilización de constantes: constantes compartidas entre aplicaciones, constantes compartidas dentro de aplicaciones, constantes compartidas dentro de subproyectos, constantes compartidas dentro de paquetes y constantes
    compartidas dentro de clases.
    1) Constantes compartidas entre aplicaciones: colocadas en una biblioteca de terceros, generalmente en el directorio de constantes en client.jar.
    2) Constantes compartidas dentro de la aplicación: ubicadas en una biblioteca, generalmente en el directorio de constantes de los módulos.
    反例:Las variables fáciles de entender también deben definirse uniformemente como constantes compartidas dentro de la aplicación. Los dos ingenieros de asedio definieron
    variables que representan "sí" en dos clases:
    Clase A: cadena final estática pública YES = "sí";
    Clase B: estática pública final String YES = “y”;
    A.YES.equals(B.YES), se esperaba que fuera verdadero, pero en realidad devolvió falso, lo que provocó problemas en línea.
    3) Constantes compartidas dentro del subproyecto: es decir, en el directorio de constantes del subproyecto actual.
    4) Constantes compartidas dentro del paquete: es decir, en un directorio de constantes separado en el paquete actual.
    5) Constantes compartidas dentro de la clase: definición final estática privada directamente dentro de la clase.

  5. [Recomendado] Si el valor de la variable solo cambia dentro de un rango y tiene atributos extendidos más allá del nombre, defínalo como una clase de enumeración.
    Los números en el ejemplo positivo a continuación son información ampliada que indica el día de la semana.
    正例: Enum público {LUNES(1), MARTES(2), MIÉRCOLES(3), JUEVES(4), VIERNES(5), SÁBADO(6),DOMINGO(7);}

(3) Formato de código

  1. [Obligatorio] Convenio sobre el uso de brackets. Si las llaves están vacías, simplemente escriba {} sin saltos de línea; si es
    un bloque de código no vacío:
    1) No hay ningún salto de línea antes de la llave izquierda.
    2) Nueva línea después del corchete izquierdo.
    3) Nueva línea antes de la llave de cierre.
    4) Si hay código else después de la llave derecha, no habrá salto de línea; la llave derecha que indica terminación debe ir seguida de un salto de línea.

  2. [Obligatorio] No hay espacio entre el paréntesis izquierdo y el carácter; de manera similar, no hay espacio entre el paréntesis derecho y el carácter. Para obtener más información, consulte
    los consejos de ejemplo correctos debajo del Artículo 5.
    反例:si (espacio a == b espacio)

  3. [Obligatorio] Se deben agregar espacios entre palabras reservadas como if/for/ while/switch/do y paréntesis.

  4. [Obligatorio] Se debe agregar un espacio a los lados izquierdo y derecho de cualquier operador binario o ternario.
    Nota: Los operadores incluyen operador de asignación =, operador lógico &&, símbolos de suma, resta, multiplicación y división, etc.

  5. [Obligatorio] Utilice 4 espacios para sangría y prohíba el uso de caracteres de tabulación.
    Nota: Si se utiliza sangría de tabulación, una tabulación debe establecerse en 4 espacios. Cuando IDEA establece tabulaciones en 4 espacios,
    no marque Usar carácter de tabulación; en eclipse, debe marcar Insertar espacios para tabulaciones.
    正例:(implica 1-5 puntos)

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");
// 在右大括号后直接结束,则必须换行
}
}
  1. [Obligatorio] Debe haber exactamente un espacio entre la doble barra del comentario y el contenido del comentario.
    正例:// Contenido del comentario, tenga en cuenta que hay un espacio entre // y el contenido del comentario.

  2. [Obligatorio] El número de caracteres en una sola línea está limitado a no más de 120. Si excede el límite, se requieren saltos de línea. Al dividir líneas, siga los siguientes principios: 1) La segunda línea tiene una sangría de 4 espacios en relación
    con la primera línea. A partir de la tercera línea, no se requiere más sangría. Consulte el ejemplo.
    2) El operador está envuelto junto con lo siguiente.
    3) El símbolo de punto de la llamada al método se incluye junto con lo siguiente.
    4) Al llamar a un método, si es necesario ajustar varios parámetros, hágalo después de una coma.
    5) No ajuste las líneas antes de los paréntesis; consulte el contraejemplo.
    正例:

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);
  1. [Obligatorio] Al definir y pasar parámetros de método, se deben agregar espacios después de las comas de varios parámetros.
    正例:En el siguiente ejemplo, la "a" del parámetro real debe ir seguida de un espacio.
method("a", "b", "c");
  1. [Obligatorio] La codificación del archivo de texto del IDE está configurada en UTF-8; los caracteres de nueva línea de los archivos en el IDE usan el formato Unix,
    no usan el formato de Windows.

  2. [Recomendación] No es necesario agregar una cantidad de espacios para alinear los caracteres de una línea determinada con los caracteres correspondientes de la línea anterior.
    正例:

int a = 3;
long b = 4L;
float c = 5F;
StringBuffer sb = new StringBuffer();


Nota: Si agrega la variable sb, si se requiere alineación, deberá agregar algunos espacios a a, b y c. Esto es engorroso cuando hay muchas variables .


  1. [Recomendado] Inserte una línea en blanco entre el grupo de declaraciones de ejecución, el grupo de declaraciones de definición de variable, la lógica empresarial diferente o la semántica diferente en el cuerpo del método . No es necesario insertar líneas en blanco entre la misma lógica y semántica empresarial.
    Nota: No es necesario insertar varias líneas en blanco para separarlas.

(4) protocolo POO

  1. [Obligatorio] Evite acceder a variables estáticas o métodos estáticos de esta clase a través de referencias de objetos de una clase, lo que aumentará innecesariamente los costos de análisis del compilador
    . Simplemente use el nombre de la clase para acceder a ellos directamente.

  2. [Obligatorio] Todos los métodos primordiales deben anotarse con @Override.
    Descripción: Problemas con getObject() y get0object(). Una es la letra O y la otra es el número 0. Agregar @Override
    puede determinar con precisión si la anulación fue exitosa. Además, si la firma del método se modifica en una clase abstracta, su clase de implementación se compilará inmediatamente
    e informará un error.

  3. [Obligatorio] Los parámetros variables de Java solo se pueden utilizar si tienen el mismo tipo de parámetro y el mismo significado comercial. Evite el uso de Objeto.
    Nota: Los parámetros variables deben colocarse al final de la lista de parámetros. (Se anima a los estudiantes a evitar la programación de parámetros variables tanto como sea posible)
    正例: public User getUsers(String type, Integer... ids) {...}

  4. [Obligatorio] Las interfaces que se llaman externamente o en las que dependen bibliotecas de terceros no pueden modificar la firma del método para evitar cualquier impacto en la persona que llama a la interfaz
    . Se debe agregar la anotación @Deprecated si la interfaz está obsoleta y se debe indicar claramente la nueva interfaz o el nuevo servicio.

  5. [Obligatorio] No se pueden utilizar clases o métodos obsoletos. Nota: El método decodificar (String encodeStr) en java.net.URLDecoder está obsoleto. Se debe utilizar
    la decodificación de dos parámetros (String source, String encode).
    Dado que el proveedor de la interfaz es claramente una interfaz obsoleta,
    está obligado a proporcionar una nueva interfaz al mismo tiempo; como llamador, está obligado a verificar la nueva implementación del método obsoleto.

  6. [Obligatorio] El método igual de Object es propenso a generar una excepción de puntero nulo. Debe usar una constante o un objeto con un cierto valor para llamar
    a iguales.
    正例:"test".equals(object);
    反例:object.equals("test");
    Nota: Se recomienda utilizar java.util.Objects#equals (clase de herramienta introducida por JDK7)

  7. [Obligatorio] Todas las comparaciones de valores entre objetos de clase de empaquetado del mismo tipo deben utilizar el método igual.
    Nota: Para la asignación Integer var =? en el rango de -128 a 127, el objeto Integer se genera en IntegerCache.cache y los objetos existentes se reutilizarán. Los valores enteros en este rango se pueden juzgar directamente usando ==, pero esto
    rango Todos los demás datos se generarán en el montón y los objetos existentes no se reutilizarán. Este es un gran error. Se
    recomienda utilizar el método igual para juzgar.

  8. Los estándares de uso para tipos de datos básicos y tipos de datos empaquetados son los siguientes:
    1) [Obligatorio] Todos los atributos de clase POJO deben utilizar tipos de datos empaquetados.
    2) [Obligatorio] El valor de retorno y los parámetros del método RPC deben utilizar tipos de datos ajustados.
    3) [Recomendado] Utilice tipos de datos básicos para todas las variables locales.
    Nota: El atributo de clase POJO no tiene un valor inicial para recordar a los usuarios que deben asignar explícitamente el valor ellos mismos cuando necesiten usarlo. Cualquier
    problema de NPE o control de almacenamiento está garantizado por el usuario.
    Ejemplo positivo: el resultado de la consulta de la base de datos puede ser nulo porque el unboxing y la recepción automática con tipos de datos básicos tienen riesgos de NPE.
    Ejemplo de contador: por ejemplo, muestra el aumento y la caída del monto total de la transacción, es decir, más o menos x%, x es el tipo de datos básico y, cuando la llamada no tiene éxito, el servicio RPC devuelto es el valor predeterminado
    y la página muestra 0%, lo cual no es razonable. Debería aparecer como un guión. Por lo tanto, el valor nulo del
    tipo de datos ajustado puede representar información adicional, como: falla de llamada remota y salida anormal.

  9. [Obligatorio] Al definir clases POJO como DO/DTO/VO, no establezca ningún valor predeterminado de atributo.
    反例:El valor predeterminado de gmtCreate de la clase POJO es new Date(); sin embargo, este atributo no tiene un valor específico establecido durante la extracción de datos
    . Este campo también se actualiza cuando se actualizan otros campos, lo que hace que la hora de creación se modifique al tiempo actual.

  10. [Obligatorio] Al agregar nuevos atributos a la clase de serialización, no modifique el campo serialVersionUID para evitar fallas de deserialización; si es
    completamente incompatible con las actualizaciones para evitar el caos de deserialización, modifique el valor serialVersionUID.
    Nota: Tenga en cuenta que serialVersionUID incoherente generará una excepción de tiempo de ejecución de serialización.

  11. [Obligatorio] Está prohibido agregar cualquier lógica de negocios en el método de construcción. Si hay lógica de inicialización, colóquela en el método init.

  12. [Obligatorio] La clase POJO debe escribir el método toString. Cuando utilice la herramienta IDE: fuente> generar toString
    , si hereda otra clase POJO, asegúrese de agregar super.toString al frente.
    Nota: Cuando se produce una excepción durante la ejecución del método, puede llamar directamente al método toString() de POJO para imprimir los valores de sus atributos para facilitar
    la resolución de problemas.

  13. [Recomendación] Cuando utilice el índice para acceder a la matriz obtenida mediante el método de división de String, debe verificar si hay contenido después del último delimitador;
    de lo contrario, existe el riesgo de generar IndexOutOfBoundsException.
    ilustrar:

String str = "a,b,c,,";
String[] ary = str.split(",");
// 预期大于 3,结果是 3
System.out.println(ary.length

);

  1. [Recomendación] Cuando una clase tiene múltiples constructores, o múltiples métodos con el mismo nombre, estos métodos deben colocarse juntos para
    facilitar la lectura. Esta regla tiene prioridad sobre la Regla 15.

  2. [Recomendación] El orden de definición de los métodos dentro de una clase es: método público o método protegido > método privado >
    método getter/setter.
    Nota: Los métodos públicos son los métodos que más preocupan a quienes llaman y mantienen la clase, y se muestran mejor en la primera pantalla; aunque los métodos protegidos solo interesan a las subclases, también pueden ser métodos centrales en el "modo de diseño de plantilla"
    . "; aunque los métodos privados generalmente no son externos. Requiere especial atención porque es una
    implementación de caja negra; debido a que el valor de la información transportada es bajo, todos los métodos getter/setter de Service y DAO se colocan al
    final del cuerpo de la clase.

  3. [Recomendación] En el método de establecimiento, el nombre del parámetro debe ser coherente con el nombre de la variable miembro de la clase, esto es nombre del miembro = nombre del parámetro. En
    los métodos getter/setter, no agregue lógica empresarial para aumentar la dificultad de resolución de problemas.
    反例:

public Integer getData() {
    
    
if (true) {
    
    
return this.data + 100;
} else {
    
    
return this.data - 100;
}
}
  1. [Recomendado] Utilice el método append de StringBuilder para expandir el método de conexión de cadena dentro del cuerpo del bucle.
    Nota: El archivo de código de bytes descompilado muestra que cada bucle creará un nuevo objeto StringBuilder, luego realizará la
    operación de agregar y finalmente devolverá el objeto String a través del método toString, lo que resultará en un desperdicio de recursos de memoria.
    反例:
String str = "start";
for (int i = 0; i < 100; i++) {
    
    
str = str + "hello";
}
  1. [Recomendación] final puede declarar clases, variables miembro, métodos y variables locales. La palabra clave final no se utiliza en las siguientes situaciones:
    1) Clases que no se pueden heredar, como: clase String.
    2) No se permite la modificación de objetos de dominio referenciados, como variables de dominio de clases POJO.
    3) Métodos que no se pueden anular, como: métodos de establecimiento de clases POJO.
    4) No se permiten variables locales que se reasignen durante la operación.
    5) Evite la reutilización del contexto de una variable. Utilice la descripción final para forzar la redefinición de una variable para facilitar una mejor
    reconstrucción.

  2. [Recomendado] Utilice el método de clonación de Objeto con precaución para copiar objetos.
    Nota: El método de clonación de un objeto tiene como valor predeterminado una copia superficial. Si desea implementar una copia profunda, debe anular el método de clonación para copiar el objeto de atributo
    .

  3. [Recomendación] Control de acceso estricto a los miembros y métodos de la clase:
    1) Si no se permite la creación de objetos externos directamente a través de new, entonces el constructor debe ser privado.
    2) No se permite que las clases de herramientas tengan constructores públicos o predeterminados.
    3) Las variables miembro de clase no estáticas y compartidas con subclases deben estar protegidas.
    4) Las variables miembro no estáticas de clase solo se usan en esta clase y deben ser privadas.
    5) Si las variables miembro estáticas de la clase solo se usan en esta clase, deben ser privadas.
    6) Si es una variable miembro estática, debes considerar si es definitiva.
    7) Los métodos de los miembros de la clase son solo para llamadas internas dentro de la clase y deben ser privados.
    8) Los métodos de los miembros de la clase sólo son públicos para las clases heredadas, por lo que están restringidos a protegidos.
    Nota: El alcance de acceso de cualquier clase, método, parámetro o variable está estrictamente controlado. Un alcance de acceso demasiado amplio no favorece el desacoplamiento de módulos.
    Pensando: si es un método privado, elimínelo si lo desea, pero si es un método de servicio público o
    una variable miembro pública, elimínelo y le sudarán un poco las palmas. Las variables son como sus propios hijos, trate de mantenerlas a la
    vista. Si el alcance de una variable es demasiado grande y puede funcionar sin restricciones, entonces se preocupará.

(5) Procesamiento de cobranza

  1. [Obligatorio] Con respecto al procesamiento de hashCode y iguales, siga las siguientes reglas:
    1) Siempre que se reescriba igual, se debe reescribir hashCode.
    2) Debido a que Set almacena objetos únicos y se juzga en función de hashCode y iguales,
    los objetos almacenados en Set deben anular estos dos métodos.
    3) Si se utiliza un objeto personalizado como clave del Mapa, se deben reescribir hashCode e iguales.
    Nota: String anula el código hash y los métodos iguales, por lo que podemos usar objetos String
    como claves.

  2. [Obligatorio] El resultado de la sublista de ArrayList no se puede convertir a ArrayList; de lo contrario, se generará una ClassCastException
    , es decir, java.util.RandomAccessSubList no se puede convertir a java.util.ArrayList.
    Nota: subList devuelve la clase interna SubList de ArrayList. no ArrayList es una vista de ArrayList. Todas las operaciones en la sublista SubList eventualmente se reflejarán en la lista original.

  3. [Obligatorio] En el escenario de sublista, preste mucha atención a la modificación del número de elementos en la colección original, lo que provocará
    excepciones ConcurrentModificationException al atravesar, agregar o eliminar sublistas.

  4. [Obligatorio] Para usar el método de convertir un conjunto en una matriz, debe usar el toArray (T [] matriz) del conjunto. La entrada es una
    matriz de exactamente el mismo tipo y el tamaño es list.size () .
    Nota: Cuando se utiliza el método toArray con parámetros, si el espacio de la matriz asignado por los parámetros de entrada no es lo suficientemente grande, el método toArray reasignará el
    espacio de memoria internamente y devolverá la nueva dirección de la matriz; si los elementos de la matriz son más grandes de lo que realmente son requerido, el subíndice es [list.size()]
    los elementos de la matriz se establecerán en nulo y otros elementos de la matriz conservarán sus valores originales, por lo que es mejor definir el tamaño del grupo de parámetros del método de manera consistente con el
    número de elementos de la colección.
    正例:

List<String> list = new ArrayList<String>(2);
list.add("guan");
list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);

反例:Hay un problema con el uso directo del método sin parámetros toArray. El valor de retorno de este método solo puede ser la clase Object[]. Si fuerza la conversión de una
matriz de otros tipos, se producirá un error ClassCastException.

  1. [Obligatorio] Cuando utilice la clase de herramienta Arrays.asList() para convertir una matriz en una colección, no puede utilizar sus métodos relacionados con la modificación de la colección
    . Sus métodos agregar/eliminar/borrar generarán una excepción UnsupportedOperationException.
    Nota: El objeto de retorno de asList es una clase interna de Arrays y no implementa el método de modificación de la colección. Arrays.asList
    incorpora el modo adaptador, que solo convierte la interfaz y los datos de fondo siguen siendo una matriz.
    String[] str = new String[] { “you”, “wu” };
    List list = Arrays.asList(str);
    El primer caso: list.add(“yangguanbao”); Excepción de tiempo de ejecución.
    El segundo caso: str[0] = “gujin”; entonces list.get(0) también se modificará en consecuencia.

  2. [Obligatorio] El comodín genérico <? extends T> se usa para recibir los datos devueltos. El método add no se puede usar para la colección genérica escrita de esta manera
    , y el método get no se puede usar para <? super T>. Es fácil cometer errores al llamar asignaciones como interfaces.
    Nota: Ampliemos el principio PECS (Producer Extends Consumer Super): Primero, si lee contenido desde el exterior con frecuencia
    , es adecuado usar <? extends T>. En segundo lugar, si lo inserta con frecuencia, <? super T> es adecuado.

  3. [Obligatorio] No realice operaciones de eliminación/adición de elementos en el bucle foreach. Utilice el
    método Iterator para eliminar elementos. Si opera al mismo tiempo, debe bloquear el objeto Iterator.
    正例:

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    
    
String item = iterator.next();
if (删除元素的条件) {
    
    
iterator.remove();
}
}

反例:

List<String> a = new ArrayList<String>();
list.add("1");
list.add("2");
for (String item : list) {
    
    
if ("1".equals(item)) {
    
    
list.remove(item);
}
}

Nota: El resultado de la ejecución del código anterior definitivamente superará las expectativas de todos, así que intente reemplazar "1" con "2", ¿será el mismo
resultado?

  1. [Obligatorio] En la versión JDK7 y superior, Comparator debe cumplir las siguientes tres condiciones; de lo contrario, Arrays.sort y
    Collections.sort informarán una excepción IllegalArgumentException.
    Nota: Las tres condiciones son las siguientes
    : 1) Los resultados de la comparación de xey son opuestos a los resultados de la comparación de yyx.
    2) x>y, y>z, luego x>z.
    3) x = y, entonces los resultados de la comparación de x y z son los mismos que los resultados de la comparación de y y z.
    反例:El siguiente ejemplo no maneja situaciones de igualdad y pueden ocurrir excepciones en el uso real:
    new Comparator() { @Override public int compare(Estudiante o1, Estudiante o2) { return o1.getId() > o2.getId() ? 1 : -1; } };




  2. [Recomendado] Al inicializar la colección, especifique el tamaño del valor inicial de la colección.
    Nota: HashMap se inicializa usando HashMap(int capacidadinicial),
    正例:capacidadinicial = (número de elementos a almacenar/factor de carga) + 1. Tenga en cuenta que el factor de carga (es decir,
    el factor de carga) está predeterminado en 0,75. Si el valor inicial no se puede determinar temporalmente, configúrelo en 16 (es decir, el valor predeterminado).
    Ejemplo contrario: HashMap necesita colocar 1024 elementos. Dado que el tamaño inicial de la capacidad no está establecido, a medida que los elementos continúan aumentando, la capacidad se ve obligada a expandirse
    7 veces. Resize necesita reconstruir la tabla hash, lo que afecta seriamente el rendimiento. .

  3. [Recomendado] Utilice EntrySet para recorrer la colección de clases de mapas KV en lugar de keySet. Nota: El conjunto de claves en realidad se recorre dos veces, una para convertirlo en un objeto Iterador y la otra para recuperar el valor correspondiente a la clave
    del hashMap .
    El conjunto de entrada solo lo atraviesa una vez y coloca tanto la clave como el valor en la entrada, lo cual es
    más eficiente. Si es JDK8, utilice el método Map.foreach.
    正例:value() devuelve un conjunto de valores V, que es un objeto de colección de lista; keySet() devuelve un conjunto de valores K, que es
    un objeto de colección Set; EntrySet() devuelve un conjunto de combinación de valores KV.

  4. [Referencia] Haga un uso razonable del orden (clasificación) y la estabilidad (orden) del conjunto para evitar los efectos negativos del desorden (desclasificación) y la
    inestabilidad (desorden) del conjunto.
    Nota: Orden significa que los resultados del recorrido se organizan secuencialmente de acuerdo con ciertas reglas de comparación.
    Estabilidad significa que el orden de los elementos de la colección es cierto cada vez que se recorre . Por ejemplo: ArrayList es ordenar/desordenar; HashMap es desordenar/desordenar; TreeSet es
    ordenar/ordenar.

  5. [Referencia] Utilizando las características únicas del elemento Set, puede realizar rápidamente operaciones de deduplicación en una colección, evitando el uso del
    método contiene de Lista para operaciones de recorrido, comparación y deduplicación.

(6) Procesamiento concurrente

  1. [Obligatorio] La obtención de un objeto singleton debe garantizar la seguridad de los subprocesos, y los métodos también deben garantizar la seguridad de los subprocesos.
    Nota: Las clases basadas en recursos, las clases de herramientas y las clases de fábrica singleton requieren atención.

  2. [Obligatorio] Especifique un nombre de subproceso significativo al crear un subproceso o un grupo de subprocesos para facilitar el seguimiento cuando se produzca un error.
    正例:

public class TimerTaskThread extends Thread {
    
    
public TimerTaskThread() {
    
    
super.setName("TimerTaskThread");
...
}
  1. [Obligatorio] Los recursos de subprocesos deben proporcionarse a través del grupo de subprocesos y no se permite la creación explícita de subprocesos en la aplicación.
    Nota: La ventaja de utilizar un grupo de subprocesos es reducir el tiempo dedicado a crear y destruir subprocesos y la sobrecarga de los recursos del sistema, y ​​resolver el
    problema de los recursos insuficientes. Si no se utiliza el grupo de subprocesos, puede hacer que el sistema cree una gran cantidad de subprocesos similares, lo que provocará un consumo de memoria o
    problemas de "cambio excesivo".

  2. [Obligatorio] No se permite la creación de grupos de subprocesos mediante Ejecutores, sino a través de ThreadPoolExecutor, este
    método de procesamiento permite a los estudiantes que escriben conocer más claramente las reglas operativas del grupo de subprocesos y evitar el riesgo de agotamiento de recursos.
    Nota: Las desventajas del objeto del grupo de subprocesos devuelto por los Ejecutores son las siguientes:
    1) FixedThreadPool y SingleThreadPool:
    la longitud permitida de la cola de solicitudes es Integer.MAX_VALUE, lo que puede acumular una gran cantidad de solicitudes, lo que resulta en OOM.
    2) CachedThreadPool y ScheduledThreadPool:
    la cantidad de subprocesos que se permite crear es Integer.MAX_VALUE, lo que puede crear una gran cantidad de subprocesos y provocar OOM.

  3. [Obligatorio] SimpleDateFormat es una clase insegura para subprocesos. Generalmente, no debe definirse como una variable estática. Si se define como
    estática, debe bloquearse o usar la clase de herramienta DateUtils.
    Ejemplo positivo: preste atención a la seguridad de los subprocesos y utilice DateUtils. También se recomiendan los siguientes tratamientos:

private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
    
    
@Override
protected DateFormat initialValue() {
    
    
return new SimpleDateFormat("yyyy-MM-dd");
}
};

Nota: Si es una aplicación JDK8, puede usar Instant en lugar de Date, LocalDateTime en lugar de Calendar y
DateTimeFormatter en lugar de SimpleDateFormat. La explicación oficial es: simple, hermoso, fuerte,
inmutable, seguro para subprocesos.

  1. [Obligatorio] Cuando la concurrencia es alta, las llamadas sincrónicas deben considerar la pérdida de rendimiento de los bloqueos. Si puede usar estructuras de datos sin bloqueos, no use bloqueos; si puede
    bloquear bloques, no bloquee todo el cuerpo del método; si puede usar bloqueos de objetos, no use bloqueos de clases.
    Nota: Intente mantener la carga de trabajo del bloque de código bloqueado lo más pequeña posible y evite llamar a métodos RPC en el bloque de código bloqueado.

  2. [Obligatorio] Al bloquear varios recursos, tablas de bases de datos y objetos al mismo tiempo, debe mantener una secuencia de bloqueo coherente; de ​​lo contrario,
    puede producirse un punto muerto.
    Nota: El subproceso 1 debe bloquear todas las tablas A, B y C en secuencia antes de realizar la operación de actualización. Luego, el subproceso 2
    también debe bloquear las tablas A, B y C en orden; de lo contrario, puede producirse un punto muerto.

  3. [Obligatorio] Al modificar el mismo registro simultáneamente, para evitar perder actualizaciones, se requiere bloquear. Bloquee en la capa de aplicación, bloquee en el caché
    o utilice el bloqueo optimista en la capa de base de datos y utilice la versión como base de actualización.
    Nota: Si la probabilidad de cada conflicto de acceso es inferior al 20%, se recomienda utilizar el bloqueo optimista; de lo contrario, utilice el bloqueo pesimista. El número de reintentos para el bloqueo optimista
    no debe ser inferior a 3 veces.

  4. [Obligatorio] Cuando varios subprocesos procesan tareas programadas en paralelo, cuando Timer ejecuta varias TimeTasks, siempre que una de ellas no detecte la
    excepción lanzada, las otras tareas finalizarán automáticamente. El uso de ScheduledExecutorService no tiene este problema.

  5. [Recomendado] Utilice CountDownLatch para realizar operaciones asincrónicas a sincrónicas. Cada subproceso debe llamar al
    método countDown antes de salir. Preste atención a la excepción de captura en el código de ejecución del subproceso para garantizar que el método countDown se ejecute y evitar que el subproceso principal no pueda ejecutarse.
    el método de espera y el resultado no se devolverá hasta que se agote el tiempo de espera.
    Nota: Tenga en cuenta que try-catch en el hilo principal no puede alcanzar la pila de excepciones lanzada por el subproceso secundario.

  6. [Recomendación] Evite que varios subprocesos utilicen instancias aleatorias. Aunque compartir la instancia es seguro para subprocesos, provocará una
    degradación del rendimiento debido a la competencia por la misma semilla.
    Nota: Las instancias aleatorias incluyen instancias de java.util.Random o el método Math.random().
    正例:Después de JDK7, puede usar API ThreadLocalRandom directamente, pero antes de JDK7, necesita codificar para asegurarse de que
    cada hilo contenga una instancia.

  7. [Recomendación] En escenarios concurrentes, el
    problema de optimización oculto de la inicialización retrasada mediante bloqueo de doble verificación (consulte la Declaración "El bloqueo de doble verificación está roto") es la
    solución aplicable a JDK5 y superior), declare el objetivo atributo como volátil.
    Contraejemplo:

class Singleton {
    
    
private Helper helper = null;
public Helper getHelper() {
    
    
if (helper == null) synchronized(this) {
    
    
if (helper == null)
helper = new Helper();
}
return helper;
}
// other methods and fields...
}
  1. [Referencia] volátil resuelve el problema de la memoria invisible en subprocesos múltiples. Para una escritura y muchas lecturas, el problema de sincronización de variables se puede resolver,
    pero si hay muchas escrituras, el problema de seguridad del hilo no se puede resolver. Si es una operación count++, use la siguiente clase para implementarla:
    AtomicInteger count = new AtomicInteger(); count.addAndGet(1); si es JDK8, se recomienda usar
    el objeto LongAdder, que tiene mejor rendimiento que AtomicLong (reduce el número de reintentos de bloqueo optimista).

  2. [Referencia] Cuando HashMap no tiene capacidad suficiente para cambiar el tamaño, pueden ocurrir enlaces inactivos debido a la alta concurrencia, lo que hace que la CPU se sobrecargue. Durante el
    proceso de desarrollo, se pueden usar otras estructuras de datos o bloqueos para evitar este riesgo.


  3. [Referencia] ThreadLocal no puede resolver el problema de actualización de objetos compartidos, se recomienda utilizar modificación estática para objetos ThreadLocal . Esta variable se comparte para todas las operaciones dentro de un hilo, por lo que se establece como una variable estática. Todas estas instancias comparten
    esta variable estática, lo que significa que cuando la clase se usa por primera vez, se carga y solo una parte del almacenamiento se asigna espacio. Los objetos (siempre
    que estén definidos dentro de este hilo) pueden manipular esta variable

(7) Declaraciones de control

  1. [Obligatorio] Dentro de un bloque de cambio, cada caso debe terminar mediante interrupción/retorno, etc., o un comentario que indique en
    qué caso el programa continuará ejecutándose; Dentro de un bloque de cambio, se debe incluir y
    colocar una declaración predeterminada Finalmente, incluso no tiene codigo.
  2. [Obligatorio] Se deben utilizar llaves en las declaraciones if/else/for/ while/do. Incluso si solo hay una línea de código, evite
    la codificación de una sola línea: declaraciones if (condición);
  3. [Recomendación] Al expresar ramas anormales, use menos método if-else. Este método se puede reescribir como:
if (condition) {
    
    
...
return obj;
}
// 接着写 else 的业务逻辑代码;

Nota: Si debe usar if()…else if()…else… para expresar lógica, [Obligatorio] Para evitar
dificultades en el mantenimiento posterior del código, no exceda los 3 niveles.
Ejemplo positivo: se pueden implementar más de 3 niveles de código de juicio lógico if-else utilizando declaraciones de guardia, patrones de estrategia, patrones de estado, etc. Los
ejemplos de declaraciones de guardia son los siguientes:

public void today() {
    
    
if (isBusy()) {
    
    
System.out.println(“change time.);
return;
}
if (isFree()) {
    
    
System.out.println(“go to travel.);
return;
}
System.out.println(“stay at home to learn Alibaba Java Coding Guidelines.);
return;
}
  1. [Recomendación] A excepción de los métodos comunes (como getXxx/isXxx), no ejecute otras declaraciones complejas en juicios condicionales y asigne los
    resultados de juicios lógicos complejos a un nombre de variable booleana significativo para mejorar la legibilidad.
    Nota: La lógica en muchas declaraciones if es bastante compleja. El lector necesita analizar el resultado final de la expresión condicional para saber qué
    condición ejecuta qué declaración. Entonces, ¿qué pasa si el lector analiza la expresión lógica incorrectamente?
    正例:

```dart
// 伪代码如下
final boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
if (existed) {
    
    
...
}

反例:

if ((file.open(fileName, "w") != null) && (...) || (...)) {
    
    
...
}
  1. [Recomendación] Las declaraciones en el cuerpo del bucle deben considerar el rendimiento. Las siguientes operaciones deben moverse fuera del bucle tanto como sea posible, como definir objetos, variables, obtener conexiones de bases de datos
    y realizar operaciones try-catch innecesarias (¿puede esto intentar- la captura se moverá fuera del circuito? ).

  2. [Recomendado] Protección de parámetros de entrada de interfaz. Este escenario es común para interfaces utilizadas para operaciones por lotes.

  3. [Referencia] La verificación de parámetros se requiere en las siguientes situaciones:
    1) Métodos que se llaman con menos frecuencia.
    2) Un método con una gran sobrecarga de tiempo de ejecución. En este caso, el tiempo de verificación de parámetros es casi insignificante, pero si la
    ejecución intermedia retrocede o comete errores debido a errores de parámetros, la ganancia supera la ganancia.
    3) Métodos que requieren estabilidad y disponibilidad extremadamente altas.
    4) Interfaces abiertas proporcionadas al mundo exterior, ya sea una interfaz RPC/API/HTTP.
    5) Entrada de permisos sensibles.

  4. [Referencia] La verificación de parámetros no es necesaria en las siguientes situaciones:
    1) Métodos que es muy probable que se llamen en un bucle. Sin embargo, los requisitos de verificación de parámetros externos deben indicarse en la descripción del método.
    2) El método subyacente se llama con más frecuencia. Después de todo, es como el último paso de la filtración de agua pura y es poco probable
    que los errores de parámetros expongan problemas hasta la capa inferior. Generalmente, la capa DAO y la capa de Servicio están en la misma aplicación y implementadas en el mismo servidor, por lo que se
    puede omitir la verificación de parámetros DAO.
    3) Un método declarado como privado solo será llamado por su propio código. Si puede estar seguro de que los parámetros pasados ​​por el código que llama al método han sido
    verificados o definitivamente no hay problemas, no necesita verificar los parámetros en esta vez.

(8) Regulaciones de anotación

  1. [Obligatorio] Los comentarios sobre clases, atributos de clase y métodos de clase deben usar especificaciones Javadoc, no se permiten el uso de /* contenido
    /formato y // métodos xxx .
    Nota: En la ventana de edición del IDE, el modo Javadoc generará comentarios relevantes y el Javadoc generado puede generar correctamente los comentarios correspondientes
    ; en el IDE, cuando el proyecto llama a un método, el significado del método, los parámetros y el valor de retorno pueden suspenderse sin ingresar al método, lo que mejora
    la eficiencia de lectura.

  2. [Obligatorio] Todos los métodos abstractos (incluidos los métodos en las interfaces) deben comentarse con Javadoc. Además de los valores de retorno, parámetros y
    descripciones de excepciones, también debe indicar qué hace el método y qué funciones implementa.
    Nota: Explique los requisitos de implementación para subclases o las precauciones de llamada.

  3. [Obligatorio] Todas las clases deben agregar el creador y la fecha de creación.

  4. [Obligatorio] Comentarios de una sola línea dentro del método, comience una nueva línea encima de la declaración comentada y use // comentario.
    Utilice /* */ comentarios para comentarios de varias líneas dentro de los métodos y asegúrese de alinearlos con el código.

  5. [Obligatorio] Todos los campos de tipo enumeración deben tener comentarios para explicar el propósito de cada elemento de datos.

  6. [Recomendación] En lugar de comentar en inglés a medias, es mejor utilizar comentarios en chino para explicar el problema con claridad. Los nombres propios y las palabras clave
    se pueden conservar en el texto original en inglés.
    Ejemplo de contador: "Tiempo de espera de conexión TCP" se interpreta como "Tiempo de espera de conexión del Protocolo de control de transmisión", lo cual es más complicado de entender.

  7. [Recomendación] Al modificar el código, los comentarios también deben modificarse en consecuencia, especialmente
    modificaciones de parámetros, valores de retorno, excepciones, lógica central, etc.
    Nota: Las actualizaciones de código y anotaciones no están sincronizadas, al igual que las actualizaciones de la red de carreteras y del software de navegación no están sincronizadas. Si el software de navegación se retrasa seriamente, se
    perderá el significado de la navegación.

  8. [Referencia] Comente el código con cuidado. Desarrolla lo anterior en lugar de simplemente comentarlo. Si es inútil, elimínelo.
    Nota: Hay dos posibilidades para comentar el código: 1) La lógica de este código se restaurará más adelante. 2) Nunca lo uses. Si no hay
    información de comentarios en el primero, es difícil saber el motivo de la anotación. Se recomienda eliminar este último directamente (el almacén de códigos guarda el código histórico).

  9. [Referencia] Requisitos para los comentarios: primero, pueden reflejar con precisión las ideas de diseño y la lógica del código; segundo, pueden describir el significado comercial
    , para que otros programadores puedan comprender rápidamente la información detrás del código. Una gran sección de código sin ningún comentario es como un libro sagrado para el lector
    . Los comentarios son para que los lea usted mismo, de modo que pueda comprender claramente el pensamiento en ese momento incluso después de mucho tiempo; los comentarios también son para sus sucesores. para leer,
    para que puedan hacerse cargo rápidamente de su trabajo.

  10. [Referencia] Los buenos nombres y la estructura del código se explican por sí solos y los comentarios deben ser concisos, precisos y expresivos. Evite
    un extremo de los comentarios: demasiados y excesivos comentarios. Una vez modificada la lógica del código, modificar los comentarios será una carga considerable.
    反例:
    // poner elefante en refrigerador
    put(elefante, refrigerador);
    El nombre del método put, más dos nombres de variables significativos elefante y puente, ya explican lo que esto hace, y el
    código con semántica clara no requiere comentarios adicionales.

  11. [Referencia] Para marcas de comentarios especiales, indique la persona que lo marcó y la hora en que fue marcado. Preste atención a tratar estas marcas de manera oportuna y
    límpielas con frecuencia mediante el escaneo de marcas. Los fallos en línea a veces se originan en el código de estas marcas.
    1) Elementos pendientes (TODO): (marcar persona, marcar tiempo, [tiempo de procesamiento estimado])
    indica funciones que deben implementarse pero que aún no se han implementado. En realidad, esta es una etiqueta Javadoc. El Javadoc actual
    aún no se ha implementado, pero se ha utilizado ampliamente. Solo se puede aplicar a clases, interfaces y métodos (porque es una etiqueta Javadoc).
    2) Error, no puede funcionar (FIXME): (marcar persona, marcar tiempo, [tiempo de procesamiento estimado])
    Utilice FIXME en los comentarios para marcar que cierto código es incorrecto y no puede funcionar y debe corregirse a tiempo.

(9) Otros

  1. [Obligatorio] Cuando utilice expresiones regulares, haga un buen uso de su función de precompilación para acelerar de manera efectiva la coincidencia de expresiones regulares.
    Nota: No lo defina en el cuerpo del método: Patrón patrón = Patrón.compile(regla);

  2. [Obligatorio] Cuando la velocidad llama a los atributos de la clase POJO, se recomienda usar directamente el nombre del atributo para obtener el valor. El motor de plantillas llamará automáticamente a
    getXxx() del POJO de acuerdo con las especificaciones. Si es un básico booleano variable de tipo de datos (el nombre booleano no necesita tener el prefijo is
    ), el método isXxx() se llamará automáticamente.
    Nota: Tenga en cuenta que si se trata de un objeto de clase contenedora booleana, primero se llama al método getXxx().

  3. [Obligatorio] Las variables enviadas a la página en segundo plano deben agregarse !var: un signo de exclamación en el medio. Nota: Si var = null o no existe, entonces !{var} - el signo de exclamación en el medio. Descripción: Si var=null o no existe, entonces! v a r - el signo de exclamación en el medio. Descripción: Si v a r=n u ll o no existe, entonces {var} se mostrará directamente en la página.

  4. [Obligatorio] Tenga en cuenta que Math.random() devuelve un tipo doble. Tenga en cuenta que el rango de valores es 0≤x<1 (se
    puede obtener el valor cero, pero preste atención a la excepción de división por cero). Si desea obtener un número aleatorio de tipo entero, no use x, se amplía varias veces a 10 y luego
    se redondea, usando directamente el método nextInt o nextLong del objeto Random.

  5. [Obligatorio] Obtenga el número actual de milisegundos con System.currentTimeMillis(); en lugar de new Date().getTime();
    Nota: Si desea obtener un valor de tiempo de nanosegundos más preciso, utilice System.nanoTime(). En JDK8,
    se recomienda utilizar la clase Instantánea para escenarios como el tiempo estadístico.

  6. [Recomendado] No agregue ninguna lógica compleja a la plantilla de vista.
    Nota: Según la teoría MVC, la vista es responsable de la presentación y no debe asumir el trabajo del modelo y del controlador.

  7. [Recomendación] El tamaño de cualquier estructura de datos debe especificarse al construirla o inicializarla para evitar un crecimiento ilimitado de la estructura de datos y consumir la memoria.

  8. [Recomendado] Limpie oportunamente los segmentos de código o la información de configuración que ya no se utilizan.
    Nota: Limpie resueltamente el código basura o las configuraciones obsoletas para evitar programas excesivamente inflados y código redundante.
    Ejemplo positivo: para fragmentos de código que se comentan temporalmente y pueden reutilizarse más adelante, se estipula uniformemente el uso de tres
    barras (///) encima del código comentado para explicar el motivo de comentar el código.

2. Registro de excepciones

(1) Manejo de excepciones

  1. [Obligatorio] Un tipo de RuntimeException definido en la biblioteca de clases de Java se puede evitar mediante una verificación previa y no debe manejarse
    mediante captura, como: IndexOutOfBoundsException, NullPointerException, etc.
    Nota: Excepto en el caso de excepciones que no pueden pasar la verificación previa, como cuando se analiza un número de cadena transmitido externamente, se
    implementa capturando NumberFormatException.
    正例:if (obj! = null) {…}
    反例:intenta { obj.method() } catch (NullPointerException e) {…}

  2. [Obligatorio] No utilice excepciones para el control de procesos o el control condicional, porque la eficiencia del procesamiento de las excepciones es menor que la de las ramas condicionales.

  3. [Obligatorio] Intenta capturar una gran sección de código, lo cual es irresponsable. Al detectar, distinga entre código estable y
    código inestable. El código estable se refiere al código que no saldrá mal pase lo que pase. Para las capturas de código inestable, intente distinguir
    los tipos de excepción tanto como sea posible y luego maneje las excepciones correspondientes.

  4. [Obligatorio] Detecte una excepción para poder manejarla. No la detecte y la descarte sin procesar nada. Si no desea manejarla, envíe la
    excepción a quien la llama. El usuario empresarial más externo debe gestionar las excepciones y convertirlas en
    contenido que los usuarios puedan entender.

  5. [Obligatorio] Coloque un bloque de prueba en el código de transacción. Si necesita revertir la transacción después de detectar la excepción, debe prestar atención a revertir la
    transacción manualmente.

  6. [Obligatorio] El bloque finalmente debe cerrar el objeto de recurso y el objeto de transmisión, y tratar de capturar si hay una excepción.
    Nota: Si es JDK7 y superior, puede utilizar el método de prueba con recursos.

  7. [Obligatorio] El retorno no se puede utilizar en el bloque finalmente. Después de que regresa el retorno en el bloque finalmente, el método finaliza la ejecución y la
    declaración de retorno en el bloque try no se ejecutará.

  8. [Obligatorio] La excepción detectada y la excepción lanzada deben coincidir exactamente, o la excepción detectada es la clase principal de la excepción lanzada.
    Nota: Si se espera que el oponente lance una bola de hortensia pero en realidad recibe un lanzamiento de peso, ocurrirá una situación inesperada.

  9. [Recomendación] El valor de retorno del método puede ser nulo. No está obligado a devolver una colección vacía o un objeto vacío. Se deben agregar comentarios para explicar completamente
    bajo qué circunstancias se devolverá un valor nulo. La persona que llama debe realizar un juicio nulo para evitar problemas de NPE.
    Nota: Este manual deja claro que prevenir NPE es responsabilidad de quien llama. Incluso si el método llamado devuelve una colección vacía o un objeto vacío, no es una situación libre de preocupaciones para la persona que llama . Debe considerar la situación de devolver nulo
    en escenarios como falla de llamada remota, falla de serialización, excepción de tiempo de ejecución, etc.

  10. [Recomendado] Prevenir NPE es una habilidad básica para los programadores. Preste atención a los escenarios donde ocurre NPE:
    1) El tipo de retorno es un tipo de datos básico. Cuando el retorno envuelve un objeto de tipo de datos, el unboxing automático puede causar NPE.
    Ejemplo de contador: public int f() {devolver objeto entero}, si es nulo, automáticamente se desempaquetará y arrojará NPE.
    2) El resultado de la consulta de la base de datos puede ser nulo.
    3) Incluso si los elementos de la colección son NotEmpty, los elementos de datos extraídos pueden ser nulos.
    4) Cuando las llamadas remotas devuelven objetos, siempre se requiere un juicio de puntero nulo para evitar NPE.
    5) Para los datos obtenidos en la Sesión, se recomienda marcar NPE para evitar punteros nulos.
    6) Llamadas en cascada a obj.getA().getB().getC(); una serie de llamadas pueden causar fácilmente NPE.
    正例:Utilice la clase opcional de JDK8 para evitar problemas de NPE.

  11. [Recomendación] Distinga entre excepciones no marcadas/marcadas al definir, evite lanzar directamente una nueva RuntimeException ()
    y no permita lanzar Exception o Throwable. Se deben usar excepciones personalizadas con significado comercial. Recomendamos
    excepciones personalizadas que se hayan definido en la industria, como: DAOException / ServiceException, etc.

  12. [Referencia] Ya sea que se utilice "lanzar excepción" o "devolver código de error" en el código, se debe usar "código de error" para las interfaces abiertas http/api fuera de la empresa; se recomienda lanzar excepciones dentro de la aplicación; se da prioridad al
    cruce -La aplicación RPC llama al modo Resultado y encapsula
    el método isSuccess(), el "código de error" y la "información breve del error".
    Nota: Razones para utilizar el método Resultado para la devolución del método RPC:
    1) Al utilizar el método de devolución de excepción, se producirá un error de tiempo de ejecución si la persona que llama no lo detecta.
    2) Si no agrega información de la pila, sino que simplemente crea una nueva excepción personalizada y agrega su propio mensaje de error, no será
    de mucha ayuda para que el final de la llamada resuelva el problema. Si se agrega información de la pila, la
    pérdida de rendimiento de la serialización y transmisión de datos también es un problema en el caso de errores de llamadas frecuentes.

  13. [Referencia] Evite el código duplicado (No se repita), es decir, el principio DRY.
    Nota: Copiar y pegar código a voluntad conducirá inevitablemente a la duplicación del código. Cuando sea necesario realizar modificaciones en el futuro, es necesario modificar todas las copias
    , lo cual es fácil de pasar por alto. Si es necesario, extraiga métodos comunes, clases públicas abstractas o incluso compóngalas en componentes.
    Ejemplo positivo: hay varios métodos públicos en una clase y todos necesitan realizar varias filas de las mismas operaciones de verificación de parámetros. En este momento, extraiga:
    checkParam booleano privado (DTO dto) {…}

(2) Protocolo de registro

  1. [Obligatorio] Las aplicaciones no pueden usar directamente la API en el sistema de registro (Log4j, Logback), pero deben confiar en la
    API en el marco de registro SLF4J. El uso del marco de registro en modo fachada favorece el mantenimiento y la unificación de los métodos de procesamiento de registros para cada clase. .
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
  1. [Obligatorio] Se recomienda guardar los archivos de registro durante al menos 15 días, debido a que algunas excepciones tienen la característica de ocurrir semanalmente.

  2. [Obligatorio] Método de denominación para registros extendidos en aplicaciones (como administración, monitoreo temporal, registros de acceso, etc.):
    appName_logType_logName.log. logType: tipo de registro, las categorías recomendadas incluyen
    estadísticas/desc/monitor/visita, etc.; logName: descripción del registro. La ventaja de este tipo de denominación: puede saber
    a qué aplicación, tipo y propósito pertenece el archivo de registro a través del nombre del archivo, lo que también es útil para la clasificación y la búsqueda.
    正例:Las excepciones de conversión de zona horaria se monitorean por separado en la aplicación mppserver, como:
    mppserver_monitor_timeZoneConvert.log
    Descripción: se recomienda clasificar los registros, como almacenar registros de errores y registros comerciales por separado, lo cual es conveniente para que los desarrolladores lo vean, y también es conveniente para
    el monitoreo oportuno del sistema a través de registros.

  3. [Obligatorio] Para la salida del registro a nivel de seguimiento/depuración/información, debe utilizar salida condicional o marcadores de posición
    .
    Descripción: logger.debug ("Procesando comercio con id: " + id + " y símbolo: " + símbolo);
    si el nivel de registro es de advertencia, el registro anterior no se imprimirá, pero se realizará la operación de empalme de cadenas. Si El símbolo es un objeto.
    Se ejecutará el método toString (), lo que desperdicia recursos del sistema. Después de realizar las operaciones anteriores, el registro final no se imprime.
    正例: (条件)

if (logger.isDebugEnabled()) {
    
    
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
}

正例: (占位符)

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
  1. [Obligatorio] Para evitar imprimir registros repetidamente y desperdiciar espacio en el disco, asegúrese de configurar additivity=false en log4j.xml.
    正例: <logger name="com.taobao.dubbo.config" additivity="false">

  2. [Obligatorio] La información de excepción debe incluir dos tipos de información: información de la escena del crimen e información de la pila de excepciones. Si no se procesa, se
    lanzará hacia arriba mediante la palabra clave throws.
    正例: logger.error(各类参数或者对象 toString + "_" + e.getMessage(), e);

  3. [Recomendado] Registre los registros con cuidado. Está prohibido generar registros de depuración en el entorno de producción; generar registros de información de forma selectiva; si utiliza
    advertencia para registrar información sobre el comportamiento empresarial cuando se inicia por primera vez, debe prestar atención a la cantidad de salida del registro para evitar que el disco del servidor se rompa
    , y recuerde borrar estas observaciones en el registro de tiempo.
    Nota: Generar una gran cantidad de registros no válidos no contribuye a mejorar el rendimiento del sistema ni a localizar rápidamente puntos de error. Al registrar registros,
    piense: ¿Alguien realmente está leyendo estos registros? ¿Qué puedes hacer después de ver este registro? ¿Puede aportar beneficios a la resolución de problemas?

  4. [Referencia] Puede utilizar el nivel de registro de advertencia para registrar los errores de los parámetros de entrada del usuario para evitar perderse cuando los usuarios se quejan
    . Preste atención al nivel de salida del registro: el nivel de error solo registra información de error importante, como errores lógicos del sistema y excepciones. A menos que
    sea necesario, no ingrese el nivel de error en este escenario.

3. Pruebas unitarias

  1. [Obligatorio] Las buenas pruebas unitarias deben cumplir con los principios de AIR.
    Nota: Cuando la prueba unitaria se ejecuta en línea, parece que no existe aire (AIR), pero es
    muy importante garantizar la calidad de la prueba. Desde una perspectiva macro, una buena prueba unitaria tiene las características de automatización, independencia y ejecución repetible.
    A: Automático
    I: Independiente
    R: Repetible

  2. [Obligatorio] Las pruebas unitarias deben ser completamente automatizadas y no interactivas. Los marcos de prueba generalmente se ejecutan con regularidad y el
    proceso de ejecución debe estar completamente automatizado para que sea significativo. Una prueba cuyo resultado requiere revisión manual no es una buena prueba unitaria.
    No se permite el uso de System.out para la verificación humana en pruebas unitarias , y se debe usar afirmar para la verificación.

  3. [Obligatorio] Mantener la independencia de las pruebas unitarias. Para garantizar que las pruebas unitarias sean estables, confiables y fáciles de mantener, los casos de prueba unitaria
    no deben llamarse entre sí ni pueden depender del orden de ejecución.
    反例: method2 需要依赖 method1 的执行, 将执行结果做为 method2 的输入。

  4. [Obligatorio] Las pruebas unitarias se pueden ejecutar repetidamente y no pueden verse afectadas por el entorno externo.
    Nota: Las pruebas unitarias generalmente se colocan en integración continua y las pruebas unitarias se ejecutarán cada vez que se registre el código. Si
    una sola prueba depende del entorno externo (red, servicio, middleware, etc.), fácilmente conducirá a la falta de disponibilidad del mecanismo de integración continua. Ejemplo positivo: para no verse afectado por el entorno externo, es necesario cambiar la dependencia SUT a inyección al diseñar el código y utilizar un marco DI como
    Spring para inyectar una implementación local (memoria) o una implementación simulada durante la prueba. .

  5. [Obligatorio] Para las pruebas unitarias, asegúrese de que la granularidad de la prueba sea lo suficientemente pequeña como para ayudar a identificar problemas. La granularidad de medición única es como máximo el nivel de clase
    , generalmente a nivel de método.
    Nota: Solo con una pequeña granularidad de prueba se puede localizar la ubicación del error lo más rápido posible cuando ocurre un error.
    Las pruebas únicas no son responsables de verificar la lógica de interacción entre clases o sistemas , ese es el dominio de las pruebas de integración.

  6. [Obligatorio] El código incremental del negocio principal, las aplicaciones principales y los módulos principales garantiza que se aprueben las pruebas unitarias.
    Nota: El nuevo código debe agregarse a la prueba unitaria de manera oportuna. Si el nuevo código afecta la prueba unitaria original, corríjalo a tiempo.

  7. [Obligatorio] El código de prueba unitaria debe escribirse en el siguiente directorio del proyecto: src/test/java. No está permitido escribirlo en el directorio de código comercial.
    Nota: Este directorio se omitirá al compilar el código fuente y el marco de prueba unitaria escanea este directorio de forma predeterminada.

  8. [Recomendación] El objetivo básico de las pruebas unitarias: la cobertura de la declaración alcanza el 70%, la cobertura de la declaración y la cobertura de la rama del módulo principal deben
    alcanzar el 100%
    Nota: La capa DAO y la capa de Administrador mencionadas en las capas de aplicación de la especificación de ingeniería, Servicios con alta reutilización deben
    probarse unitariamente.

  9. [Recomendación] Cumpla con los principios BCDE al escribir el código de prueba unitaria para garantizar la calidad de entrega del módulo probado.
    B: Frontera, prueba de valores de frontera, incluidos límites de bucle, valores especiales, puntos de tiempo especiales, orden de datos, etc.
    C: Corrija, corrija la entrada y obtenga los resultados esperados.
    D: Diseño, combinado con documentos de diseño, para escribir pruebas unitarias.
    E: Error, forzar la entrada de información de error (como datos ilegales, procesos anormales, entradas no permitidas por el negocio, etc.) y obtener los
    resultados esperados.

  10. [Recomendación] Para consultas, actualizaciones, eliminaciones y otras operaciones relacionadas con la base de datos, no puede asumir que los datos en la base de datos existen ni
    operar directamente la base de datos para insertar datos en ella. Utilice un programa para insertar o importar datos para preparar el datos.
    反例:Para la prueba unitaria de eliminar una determinada fila de datos, en la base de datos, primero agregue manualmente una fila como objetivo de eliminación. Sin embargo, los nuevos
    datos en esta fila no cumplen con las reglas de inserción comercial, lo que genera resultados de prueba anormales.

  11. [Recomendado] Para pruebas unitarias relacionadas con la base de datos, puede configurar un mecanismo de reversión automática para evitar causar datos sucios en la base de datos. O
    tenga sufijos y sufijos claros para los datos generados por la prueba unitaria.
    正例:En las pruebas unitarias internas de RDC, utilice el prefijo RDC_UNIT_TEST_ para identificar los datos.

  12. [Recomendación] Para el código que no se puede probar, se recomienda realizar la refactorización necesaria para que el código sea comprobable y evitar
    escribir código de prueba no estándar para cumplir con los requisitos de la prueba.

  13. [Recomendación] Durante la etapa de revisión del diseño, los desarrolladores deben determinar el alcance de las pruebas unitarias junto con los evaluadores. Es mejor que las pruebas unitarias
    cubra todos los casos de prueba (UC).

  14. [Recomendación] Las pruebas unitarias son un método de garantía de calidad. No se recomienda complementar los casos de prueba unitaria después de que se publique el proyecto. Se recomienda completar las
    pruebas unitarias antes de enviar el proyecto para pruebas.

  15. [Referencia] Para que las pruebas unitarias sean más convenientes, el código comercial debe evitar las siguientes situaciones:
    hacer demasiadas cosas en el método constructor.
    Hay demasiadas variables globales y métodos estáticos.
    Hay demasiadas dependencias externas.
    Hay demasiadas declaraciones condicionales.
    Nota: Se recomienda utilizar declaraciones de guardia, patrones de estrategia, patrones de estado, etc. para reconstruir declaraciones condicionales de múltiples capas.

  16. [Referencia] No tenga el siguiente malentendido sobre las pruebas unitarias:
    eso es lo que hacen los compañeros de prueba. Este artículo es un manual de desarrollo y el contenido de este artículo es muy relevante para los estudiantes de desarrollo.
    El código de prueba unitaria es redundante. El funcionamiento general del automóvil está fuertemente relacionado con si la prueba de cada componente de la unidad es normal.
    El código de prueba unitaria no requiere mantenimiento. Después de un año y medio, las pruebas unitarias están casi en estado de abandono.
    Las pruebas unitarias no tienen relación dialéctica con las fallas en línea. Unas buenas pruebas unitarias pueden evitar en gran medida los fallos en línea.

4. Normas de seguridad

  1. [Obligatorio] Las páginas o funciones pertenecientes al usuario deben someterse a una verificación de control de permisos.
    Descripción: evita que las personas puedan acceder, modificar y eliminar los datos de otras personas a voluntad sin realizar una verificación de permisos horizontal, como ver el contenido de los mensajes privados de otras personas
    y modificar las órdenes de otras personas.

  2. [Obligatorio] Está prohibida la visualización directa de datos confidenciales del usuario y los datos mostrados deben estar insensibilizados.
    Nota: Al visualizar un número de teléfono móvil personal, se mostrará como: 158****9119, ocultando los 4 dígitos del medio para evitar fugas de privacidad.

  3. [Obligatorio] Los parámetros SQL ingresados ​​por el usuario deben estar estrictamente limitados por el enlace de parámetros o los valores del campo METADATA para evitar la inyección de SQL y
    prohibir que el SQL de empalme de cadenas acceda a la base de datos.

  4. [Obligatorio] Se debe verificar la validez de cualquier parámetro ingresado por el usuario.
    Nota: Ignorar la verificación de parámetros puede llevar a:
    tamaño de página excesivo causando desbordamiento de memoria
    orden malicioso al causar consulta lenta a la base de datos redirección
    arbitraria inyección
    SQL inyección
    de deserialización
    cadena fuente de entrada regular denegación de servicio ReDoS
    Descripción: El código Java usa expresiones regulares para verificar la entrada del cliente, algunas regulares Los métodos de escritura no tienen problemas para verificar la entrada del usuario normal,
    pero si el atacante usa una cadena especialmente construida para la verificación, puede generar un bucle infinito.

  5. [Obligatorio] Está prohibido enviar datos de usuario que no hayan sido filtrados de seguridad o que no hayan sido filtrados correctamente a la página HTML.

  6. [Obligatorio] El envío de formularios y AJAX debe implementar el filtrado de seguridad CSRF.
    Descripción: CSRF (falsificación de solicitudes entre sitios) es una vulnerabilidad de programación común. Para
    aplicaciones/sitios web con vulnerabilidades CSRF, los atacantes pueden construir la URL con anticipación. Tan pronto como el usuario víctima accede a ella, el fondo
    modificará los parámetros del usuario en la base de datos en consecuencia sin el conocimiento del usuario.


  7. [Obligatorio] Al utilizar recursos de la plataforma, como mensajes de texto, correos electrónicos, llamadas telefónicas, pedidos y pagos, se deben implementar restricciones anti-repetición correctas, como límites de cantidad, control de fatiga y verificación de código de verificación, para evitar abusos y pérdidas. de fondos.
    Nota: Si se envía un código de verificación al teléfono móvil durante el registro, si no hay límite en el número y la frecuencia, esta función se puede utilizar para acosar a otros
    usuarios y provocar un desperdicio de recursos de la plataforma de SMS.

  8. [Recomendación] Escenarios en los que el contenido generado por el usuario, como publicar, comentar y enviar mensajes instantáneos, debe implementar
    estrategias de control de riesgos, como el anti-cepillado y el filtrado de palabras prohibidas en el contenido de texto.

5. Base de datos MySQL

(1) Normas de creación de tablas.

  1. [Obligatorio] Los campos que expresan el concepto de sí o no deben nombrarse de la manera is_xxx y el tipo de datos es tinyint sin signo
    (1 significa sí, 0 significa no).
    Nota: Cualquier campo debe estar sin firmar si es un número no negativo.
    正例:El nombre del campo que expresa eliminación lógica es_deleted, 1 significa eliminado, 0 significa no eliminado.

  2. [Obligatorio] Los nombres de tablas y campos deben usar letras minúsculas o números. Está prohibido comenzar con números y está prohibido tener solo números entre dos guiones bajos
    . La modificación de los nombres de los campos de la base de datos es muy costosa porque no es posible la publicación previa, por lo que los nombres de los campos deben considerarse cuidadosamente.
    Nota: MySQL no distingue entre mayúsculas y minúsculas en Windows, pero sí lo hace de forma predeterminada en Linux. Por lo tanto, no se permiten letras mayúsculas en
    los nombres de bases de datos, nombres de tablas y nombres de campos para evitar complicaciones innecesarias.
    正例: aliyun_admin, rdc_config, level3_name
    反例: AliyunAdmin, rdcConfig, level_3_name

  3. [Obligatorio] No utilice sustantivos en plural en los nombres de las tablas.
    Nota: El nombre de la tabla solo debe representar el contenido de la entidad en la tabla, no el número de entidades. El nombre de la clase DO correspondiente también está en forma singular
    , lo que se ajusta a la convención de expresión.

  4. [Obligatorio] Deshabilite las palabras reservadas, como desc, rango, coincidencia, retrasado, etc. Consulte las palabras reservadas oficiales de MySQL.

  5. [Obligatorio] El nombre del índice de clave principal es pk_field name; el nombre del índice único es uk_field name; el nombre del índice común es idx_field name.
    Nota: pk_ es la clave principal; uk_ es la clave única; idx_ es la abreviatura de index.

  6. [Obligatorio] El tipo decimal es decimal y están prohibidos flotante y doble. Nota: Existe un problema de pérdida de precisión al almacenar float y double, y es posible obtener resultados incorrectos
    al comparar valores .
    Si el rango de datos almacenados excede el rango decimal, se recomienda dividir los datos en números enteros y decimales y almacenarlos por separado.

  7. [Obligatorio] Si las longitudes de las cadenas almacenadas son casi iguales, utilice el tipo de cadena char de longitud fija.

  8. [Obligatorio] varchar es una cadena de longitud variable. No se asigna espacio de almacenamiento por adelantado. La longitud no debe exceder 5000. Si la
    longitud mayor que este valor, defina el tipo de campo como texto, cree una tabla separada y use la clave principal debe corresponder para evitar afectar la eficiencia de la indexación de otros campos
    .

  9. [Obligatorio] La tabla debe tener tres campos: id, gmt_create, gmt_modified.
    Nota: La identificación debe ser la clave principal, el tipo es bigint sin firmar, incremento automático para una sola tabla y el tamaño del paso es 1. Los tipos gmt_create y
    gmt_modified son ambos tipos date_time: el primero representa la creación activa en tiempo presente y el participio pasado del segundo representa la
    actualización pasiva.

  10. [Recomendación] Es mejor nombrar la tabla con "nombre comercial_función de la tabla".
    正例: alipay_task / force_project / trade_config

5. Base de datos MySQL

(1) Normas de creación de tablas.

  1. [Obligatorio] Los campos que expresan el concepto de sí o no deben nombrarse de la manera is_xxx y el tipo de datos es tinyint sin signo
    (1 significa sí, 0 significa no).
    Nota: Cualquier campo debe estar sin firmar si es un número no negativo.
    正例: 表达逻辑删除的字段名 is_deleted, 1 表示删除, 0 表示未删除。

  2. [Obligatorio] Los nombres de tablas y campos deben usar letras minúsculas o números. Está prohibido comenzar con números y está prohibido tener solo números entre dos guiones bajos
    . La modificación de los nombres de los campos de la base de datos es muy costosa porque no es posible la publicación previa, por lo que los nombres de los campos deben considerarse cuidadosamente.
    Nota: MySQL no distingue entre mayúsculas y minúsculas en Windows, pero sí lo hace de forma predeterminada en Linux. Por lo tanto, no se permiten letras mayúsculas en
    los nombres de bases de datos, nombres de tablas y nombres de campos para evitar complicaciones innecesarias.
    正例: aliyun_admin, rdc_config, level3_name
    反例: AliyunAdmin, rdcConfig, level_3_name

  3. [Obligatorio] No utilice sustantivos en plural en los nombres de las tablas.
    Nota: El nombre de la tabla solo debe representar el contenido de la entidad en la tabla, no el número de entidades. El nombre de la clase DO correspondiente también está en forma singular
    , lo que se ajusta a la convención de expresión.

  4. [Obligatorio] Deshabilite las palabras reservadas, como desc, rango, coincidencia, retrasado, etc. Consulte las palabras reservadas oficiales de MySQL.

  5. [Obligatorio] El nombre del índice de clave principal es pk_field name; el nombre del índice único es uk_field name; el nombre del índice común es idx_field name.
    Nota: pk_ es la clave principal; uk_ es la clave única; idx_ es la abreviatura de index.

  6. [Obligatorio] El tipo decimal es decimal y están prohibidos flotante y doble. Nota: Existe un problema de pérdida de precisión al almacenar float y double, y es posible obtener resultados incorrectos
    al comparar valores .
    Si el rango de datos almacenados excede el rango decimal, se recomienda dividir los datos en números enteros y decimales y almacenarlos por separado.

  7. [Obligatorio] Si las longitudes de las cadenas almacenadas son casi iguales, utilice el tipo de cadena char de longitud fija.

  8. [Obligatorio] varchar es una cadena de longitud variable. No se asigna espacio de almacenamiento por adelantado. La longitud no debe exceder 5000. Si la
    longitud mayor que este valor, defina el tipo de campo como texto, cree una tabla separada y use la clave principal debe corresponder para evitar afectar la eficiencia de la indexación de otros campos
    .

  9. [Obligatorio] La tabla debe tener tres campos: id, gmt_create, gmt_modified.
    Nota: La identificación debe ser la clave principal, el tipo es bigint sin firmar, incremento automático para una sola tabla y el tamaño del paso es 1. Los tipos gmt_create y
    gmt_modified son ambos tipos date_time: el primero representa la creación activa en tiempo presente y el participio pasado del segundo representa la
    actualización pasiva.

  10. [Recomendación] Es mejor nombrar la tabla con "nombre comercial_función de la tabla".
    正例: alipay_task / force_project / trade_config

(2) Protocolo de índice

  1. [Obligatorio] Los campos con características comerciales únicas, incluso si son una combinación de varios campos, deben integrarse en un índice único.
    Nota: No crea que el índice único afecta la velocidad de inserción. Esta pérdida de velocidad se puede ignorar, pero la mejora en la velocidad de búsqueda es
    obvia además, incluso si se realiza un control de verificación muy completo en la capa de aplicación, siempre que no existe un índice único, según la ley de Murphy ,
    se deben generar datos sucios.

  2. [Obligatorio] Está prohibido unirse a más de tres mesas. Los tipos de datos de los campos que deben unirse deben ser absolutamente consistentes; al realizar consultas relacionadas con varias tablas,
    se garantiza que los campos relacionados deben tener índices.
    Nota: Incluso al unir dos tablas, se debe prestar atención a los índices de las tablas y al rendimiento de SQL.

  3. [Obligatorio] Al crear un índice en un campo varchar, debe especificar la longitud del índice. No es necesario indexar todo el campo. La
    longitud del índice se puede determinar en función de la distinción del texto real.
    Nota: La longitud del índice y la discriminación son un par de contradicciones. Generalmente, para datos de tipo cadena, el índice con una longitud de 20 tendrá una discriminación de más del 90%. Puede usar count(distinct left(nombre de columna, longitud del índice) )/
    Se determina la discriminación del conteo (*) .

  4. [Obligatorio] El desenfoque a la izquierda o el desenfoque total está estrictamente prohibido en la búsqueda de páginas. Si es necesario, utilice el motor de búsqueda para solucionarlo.
    Nota: El archivo de índice tiene la función de coincidencia de prefijo más a la izquierda del árbol B. Si el valor de la izquierda no está determinado, este índice no se puede utilizar
    .

  5. [Recomendación] Si hay un orden por escenario, preste atención al orden del índice. El último campo ordenado por es
    parte del índice combinado y se coloca al final del orden de combinación del índice para evitar situaciones de clasificación de archivos y afectar el rendimiento de la consulta.
    正例: where a=? and b=? order by c; 索引: a_b_c
    反例: 索引中有范围查找,那么索引有序性无法利用,如: WHERE a>10 ORDER BY b; 索引 a_b 无法排序。

  6. [Recomendado] Utilice índices de cobertura para realizar operaciones de consulta y evitar devoluciones de tablas.
    Explicación: Si un libro necesita saber el título del Capítulo 11, ¿abrirá la página correspondiente al Capítulo 11? Simplemente navegue por el directorio
    . Este directorio sirve como índice de cobertura.
    正例: 能够建立索引的种类:主键索引、唯一索引、普通索引,而覆盖索引是一种查询的一种 效果,用 explain 的结果, extra 列会出现: using index。

  7. [Recomendado] Utilice correlación retardada o subconsulta para optimizar escenarios de paginación de varias páginas.
    Nota: MySQL no omite las filas de desplazamiento, sino que toma el desplazamiento + N filas, luego devuelve las filas de desplazamiento antes de darse por vencido y devuelve
    N filas. Cuando el desplazamiento es particularmente grande, la eficiencia es muy baja o el número total de páginas devueltas debe ser controlado. , o
    realizar una reescritura de SQL en el número de páginas que exceden un cierto umbral.
    正例: 先快速定位需要获取的 id 段,然后再关联: SELECT a.* FROM 表 1 a, (select id from 表 1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

  8. [Recomendación] El objetivo de la optimización del rendimiento de SQL: al menos alcanzar el nivel de rango, el requisito es el nivel de referencia, si pueden ser constantes, es
    mejor.
    Nota:
    1) Hay como máximo una fila coincidente (clave principal o índice único) en una única tabla de constantes y los datos se pueden leer durante la fase de optimización.
    2) ref se refiere al uso de un índice normal.
    3) rango realiza una búsqueda de rango en el índice.
    反例:El resultado de la tabla de explicación, tipo=índice, es un análisis completo del archivo físico del índice, que es muy lento. Este nivel de índice es
    inferior al rango y queda eclipsado por un análisis completo de la tabla.

  9. [Recomendación] Al construir un índice combinado, el que tiene mayor grado de diferenciación está en el extremo izquierdo.
    正例: Si donde a=? y b=?, la columna a está casi cerca de un valor único, entonces solo es necesario crear el índice idx_a
    .
    Nota: Cuando existe una condición de juicio mixta de signo no igual y signo igual, al construir el índice, coloque la columna de la condición de signo igual al frente. Por ejemplo: donde a>?
    y b=? Entonces, incluso si a tiene un mayor grado de distinción, b debe colocarse al frente del índice.

  10. [Recomendación] Evite la conversión implícita causada por diferentes tipos de campos, lo que resulta en fallas en el índice.

  11. [Referencia] Evite los siguientes malentendidos extremos al crear un índice:
    1) Es mejor tener exceso que falta. Se cree que una consulta requiere un índice.
    2) Es mejor tener menos que demasiado. Se cree que los índices consumirán espacio y ralentizarán seriamente las actualizaciones y nuevas incorporaciones.
    3) Resiste índices únicos. Se cree que la singularidad del negocio debe resolverse en la capa de aplicación mediante el método "verificar primero y luego insertar".

(3) declaración SQL

  1. [Obligatorio] No utilice count (nombre de columna) o count (constante) en lugar de count( ). count(
    ) es la sintaxis estándar para contar filas definida por SQL92 . No tiene nada que ver con la base de datos ni tiene nada que ver. con NULL y no NULL.
    Nota: count(*) contará filas con valor NULL, pero count(nombre de columna) no contará filas con valor NULL en esta columna.

  2. [Obligatorio] count(distinct col) Cuenta el número de filas únicas en esta columna excepto NULL. Tenga en cuenta que count(distinct
    col1, col2) devolverá 0 si una de las columnas es completamente NULL, incluso si la otra columna tiene un valor diferente .

  3. [Obligatorio] Cuando los valores de una determinada columna son todos NULL, el resultado devuelto de count(col) es 0, pero el resultado devuelto de sum(col) es NULL, por lo que debe prestar atención al problema de NPE cuando usando suma()
    .
    Ejemplo positivo: puede utilizar el siguiente método para evitar el problema de suma NPE: SELECT IF(ISNULL(SUM(g)),0,SUM(g)) FROM
    table;

  4. [Obligatorio] Utilice ISNULL() para determinar si es un valor NULL.
    Descripción: una comparación directa de NULL con cualquier valor es NULL.
    1) El resultado de retorno de NULL<>NULL es NULL, no falso.
    2) El resultado devuelto de NULL=NULL es NULL, no verdadero.
    3) El resultado de retorno de NULL <> 1 es NULL, no verdadero.

  5. [Obligatorio] Al escribir la lógica de consulta de paginación en el código, si el recuento es 0, debe devolverse directamente para evitar ejecutar declaraciones de paginación posteriores.

  6. [Obligatorio] No se permiten claves externas ni cascadas. Todos los conceptos de claves externas deben resolverse en la capa de aplicación.
    Nota: Tome la relación entre estudiantes y calificaciones como ejemplo: Student_id en la tabla de estudiantes es la clave principal y Student_id en la tabla de calificaciones
    es una clave externa. Si actualiza Student_id en la tabla de estudiantes y activa la actualización de Student_id en la tabla de calificaciones al mismo tiempo, es
    una actualización en cascada. Las claves externas y las actualizaciones en cascada son adecuadas para baja concurrencia en una sola máquina, pero no son adecuadas para clústeres distribuidos y de alta concurrencia; las actualizaciones en cascada bloquean fuertemente
    y tienen el riesgo de tormentas de actualización de la base de datos; las claves externas afectan la velocidad de inserción de la base de datos .

  7. [Obligatorio] Está prohibido utilizar procedimientos almacenados, los procedimientos almacenados son difíciles de depurar y expandir y no tienen portabilidad.

  8. [Obligatorio] Al revisar datos, eliminar o modificar registros, debe seleccionar primero para evitar una eliminación accidental y luego ejecutar la
    declaración de actualización solo después de confirmar que es correcta.

  9. [Recomendado] Si se puede evitar el funcionamiento, evítelo. Si no se puede evitar, debe evaluar cuidadosamente el número de elementos de recopilación después del funcionamiento y controlarlo
    dentro de 1000.

  10. [Referencia] Si es necesario la globalización, todo el almacenamiento y la representación de caracteres se codificarán en UTF-8. Preste atención a la
    diferencia en las funciones estadísticas de caracteres.
    Descripción:
    SELECT LENGTH ("Trabajo fácil"); Devuelve 12
    SELECT CHARACTER_LENGTH ("Trabajo fácil"); Devuelve 4
    Si necesita almacenar expresiones, seleccione utfmb4 para el almacenamiento y preste atención a la diferencia entre este y la codificación utf-8.

  11. [Referencia] TRUNCATE TABLE es más rápido que DELETE y utiliza menos recursos del sistema y del registro de transacciones. Sin embargo, TRUNCATE
    no tiene transacciones y no activa desencadenantes que puedan provocar accidentes. Por lo tanto, no se recomienda utilizar esta declaración en el código de desarrollo.
    Descripción: TRUNCATE TABLE es funcionalmente idéntico a la declaración DELETE sin una cláusula WHERE.

(4) mapeo ORM

  1. [Obligatorio] En consultas de tabla, no utilice * como lista de campos de la consulta. Debe indicar claramente qué campos son obligatorios.
    Descripción: 1) Aumentar el costo de análisis del analizador de consultas. 2) Es probable que agregar o restar campos no sea coherente con la configuración de resultMap.


  2. [Obligatorio] El atributo booleano de la clase POJO no se puede agregar con is, pero el campo de la base de datos debe agregarse con is_, lo que requiere un mapeo entre campos y atributos en resultMap .
    说明: 参见定义 POJO 类以及数据库字段定义规定,在<resultMap>中增加映射,是必须的。 在 MyBatis Generator 生成的代码中,需要进行对应的修改。

  3. [Obligatorio] No utilice resultClass como parámetro de retorno. Incluso si todos los nombres de atributos de clase corresponden a campos de la base de datos, aún deben definirse
    ; por el contrario, cada tabla debe tener uno correspondiente.
    Descripción: Configure la relación de mapeo para desacoplar campos de clases DO para facilitar el mantenimiento.

  4. [Obligatorio] Utilice los parámetros de configuración sql.xml: #{}, #param# No utilice ${}. Este método es propenso a la inyección SQL.

  5. [Obligatorio] No se recomienda el queryForList(String StatementName, int start, int size) que viene con iBATIS
    .
    Nota: El método de implementación es obtener todos los registros de la declaración SQL correspondiente al nombre de la declaración en la base de datos y luego
    obtener el subconjunto de inicio y tamaño a través de subList.
    Ejemplo positivo: Map<String, Object> map = new HashMap<String, Object>();
    map.put(“start”, start);
    map.put(“size”, size);

  6. [Obligatorio] No está permitido utilizar directamente HashMap y Hashtable como salida del conjunto de resultados de la consulta.
    Nota: resultClass="Hashtable" insertará el nombre del campo y el valor del atributo, pero el tipo del valor es incontrolable.

  7. [Obligatorio] Al actualizar un registro de la tabla de datos, el valor del campo gmt_modified correspondiente del registro también debe actualizarse a la hora actual.

  8. [Recomendación] No escriba una interfaz de actualización de datos grande y completa. Si se pasa como una clase POJO, no importa si es su propio campo de actualización de destino o no
    , actualice el conjunto de tablas c1=valor1,c2=valor2,c3=valor3; esto es incorrecto. Al ejecutar SQL
    , no actualice los campos no modificados. En primer lugar, es propenso a errores, en segundo lugar, es ineficiente y, en tercer lugar, aumenta el almacenamiento de binlog.

  9. [Referencia] No abuses de las transacciones @Transactional. Las transacciones afectarán el QPS de la base de datos. Además, cuando se utilizan transacciones, se
    deben considerar varias soluciones de reversión, incluida la reversión de caché, la reversión del motor de búsqueda, la compensación de mensajes, la corrección estadística, etc.

  10. 【referencia】<isEqual>中的 compareValue 是与属性值对比的常量,一般是数字,表示相等时带 上此条件; <isNotEmpty>表示不为空且不为 null 时执行; <isNotNull>表示不为 null 值时 执行。

6. Estructura de ingeniería

(1) Capas de aplicación

  1. [Recomendado] De forma predeterminada, la capa superior en la figura depende de la capa inferior y la relación de flecha indica una dependencia directa. Por ejemplo, la capa de interfaz abierta puede depender de la capa web
    o puede depender directamente de la capa de servicio. y así sucesivamente:
    Insertar descripción de la imagen aquí
    Capa de interfaz abierta: el método de Servicio se puede encapsular directamente Expuesto como interfaz RPC; encapsulado en una interfaz http a través de la Web; realiza
    control de seguridad de puerta de enlace, control de flujo, etc.
    Capa de visualización del terminal: la capa de visualización y representación de la plantilla de cada terminal. Actualmente, los principales son el renderizado de velocidad, el renderizado JS, el renderizado JSP, la visualización móvil, etc.
    Capa web: principalmente reenvío de control de acceso, verificación de varios parámetros básicos o simplemente procesamiento de servicios no reutilizados, etc.
    Capa de servicio: capa de servicio de lógica empresarial relativamente específica.
    Capa de administrador: una capa de procesamiento empresarial general, que tiene las siguientes características:
    1) una capa que encapsula plataformas de terceros, preprocesa los resultados de retorno y convierte información de excepciones;
    2) hunde las capacidades generales de la capa de servicio, como las soluciones de almacenamiento en caché y el middleware general. Procesamiento;
    3) Interactuar con la capa DAO y reutilizar la combinación de múltiples DAO.
    Capa DAO: capa de acceso a datos, que interactúa con MySQL, Oracle, Hbase, etc. subyacentes para obtener datos.
    Interfaz externa o plataforma de terceros: incluidas interfaces abiertas RPC de otros departamentos, plataformas básicas e interfaces HTTP de otras empresas.

  2. [Referencia] (Protocolo de manejo jerárquico de excepciones) En la capa DAO, se generan muchos tipos de excepciones. Es imposible detectar excepciones detalladas. Utilice el método catch(Exception e) y
    arroje una nueva DAOException(e) sin imprimir.
    Registros, porque los registros deben capturarse y escribirse en archivos de registro en la capa de Administrador/Servicio. Si el mismo servidor
    vuelve a escribir registros, se desperdiciará rendimiento y almacenamiento. Cuando ocurre una excepción en la capa de servicio, el registro de errores debe registrarse en el disco y la
    información de los parámetros debe incluirse tanto como sea posible, lo que equivale a proteger la escena del crimen. Si la capa de Administrador y el Servicio se implementan en la misma máquina, el método de registro es
    consistente con el procesamiento de la capa DAO. Si se implementan por separado, el método de procesamiento de registros es consistente con el Servicio. La capa web nunca debe continuar
    lanzando excepciones hacia arriba, porque ya está en el nivel superior. Si se da cuenta de que esta excepción hará que la página no se represente normalmente, debe saltar
    directamente a una página de error amigable y agregar un mensaje de error. que sea fácil de entender para los usuarios. La capa de interfaz abierta debe manejar excepciones y devolverlas como códigos de error
    y mensajes de error.

  3. [Referencia] Especificación del modelo de dominio jerárquico:
    DO (objeto de datos): corresponde a la estructura de la tabla de la base de datos uno a uno y transmite los objetos de origen de datos hacia arriba a través de la capa DAO.
    DTO (Objeto de transferencia de datos): Objeto de transferencia de datos, un objeto transferido por el Servicio o el Administrador.
    BO (Objeto de Negocio): Objeto de negocio. Un objeto que encapsula la salida de la lógica empresarial de la capa de Servicio.
    AO (Objeto de aplicación): Objeto de aplicación. El modelo abstracto de objetos reutilizados entre la capa web y la capa de servicio
    está muy cerca de la capa de presentación y tiene baja reutilización.
    VO (Ver objeto): objeto de capa de visualización, generalmente un objeto transmitido por la Web a la capa del motor de renderizado de plantillas.
    **Consulta:** Objeto de consulta de datos, cada capa recibe solicitudes de consulta de la capa superior. Tenga en cuenta que la encapsulación de consultas con más de 2 parámetros tiene prohibido
    utilizar la clase Map para la transmisión.

(2) Dependencias de bibliotecas de terceros

  1. [Obligatorio] Definir GAV para cumplir con las siguientes reglas:
    1) Formato GroupID: com.{Empresa/BU}.Línea de Negocio.[Sub-Línea de Negocio], hasta 4 niveles.
    Descripción: {Empresa/BU} Por ejemplo: alibaba/taobao/tmall/aliexpress, etc. BU nivel uno; las líneas de subnegocios son opcionales.
    正例: com.taobao.jstorm 或 com.alibaba.dubbo.register
    2) Formato ArtifactID: nombre de línea de producto-nombre de módulo. La semántica no se repite ni se omite, primero vaya al almacén central para verificar.
    正例: dubbo-client / fastjson-api / jstorm-tool
    3) Versión: Consulte a continuación las regulaciones detalladas.

  2. [Obligatorio] Método de denominación del número de versión de la biblioteca de terceros: número de versión principal, número de versión secundaria, número de revisión
    1) Número de versión principal: cambios de dirección del producto, o la API a gran escala es incompatible, o la arquitectura es incompatible con las actualizaciones.
    2) Número de versión menor: mantiene la compatibilidad relativa, agrega características funcionales importantes y tiene un impacto mínimo en las modificaciones incompatibles con la API.
    3) Número de revisión: mantenga la compatibilidad total, corrija errores, agregue funciones menores, etc.
    Nota: Tenga en cuenta que el número de versión inicial debe ser: 1.0.0, no 0.0.1. La biblioteca de clases lanzada oficialmente debe ir primero al almacén central para su verificación para que el
    número de versión tenga continuidad. El número de versión oficial no puede ser sobrescrito y actualizado. Por ejemplo, la versión actual: 1.3.3, luego el siguiente
    número de versión razonable: 1.3.4 o 1.4.0 o 2.0.0

  3. [Obligatorio] Las solicitudes en línea no dependen de la versión SNAPSHOT (excepto los paquetes de seguridad).
    Nota: No depender de la versión SNAPSHOT garantiza la idempotencia del lanzamiento de la aplicación. Además, también puede acelerar el empaquetado y la construcción durante la compilación.

  4. [Obligatorio] La adición o actualización de una biblioteca de terceros mantendrá sin cambios los resultados del arbitraje de otros paquetes jar, excepto los puntos de función. Si hay cambios,
    deben evaluarse y verificarse claramente. Se recomienda comparar la información antes y después de dependency:resolve. Si los resultados del arbitraje son completamente inconsistentes, use
    el comando dependency:tree para encontrar las diferencias y excluir el paquete jar. .

  5. [Obligatorio] Las bibliotecas de terceros pueden definir tipos de enumeración y los parámetros pueden usar tipos de enumeración, pero los valores de retorno de la interfaz no permiten el uso de
    tipos de enumeración u objetos POJO que contengan tipos de enumeración.

  6. [Obligatorio] Cuando se depende de un grupo de bibliotecas de terceros, se debe definir una variable de versión unificada para evitar inconsistencias en el número de versión.
    Nota: Depende de springframework-core, -context y -beans. Todos son la misma versión. Puede definir una
    variable para guardar la versión: ${spring.version}. Al definir dependencias, haga referencia a esta versión.

  7. [Obligatorio] Está prohibido tener el mismo GroupId, el mismo ArtifactId, pero diferentes
    Versiones en las dependencias pom de los subproyectos.
    Nota: Al depurar localmente, se utilizará el número de versión especificado por cada subproyecto, pero cuando se fusiona en una guerra, solo puede
    aparecer un número de versión en el directorio lib final. Puede haber un problema de que la depuración fuera de línea sea correcta, pero el problema ocurre cuando se lanza en línea.

  8. 【recomendar】所有 pom 文件中的依赖声明放在<dependencies>语句块中,所有版本仲裁放在 <dependencyManagement>语句块中。 说明: <dependencyManagement>里只是声明版本,并不实现引入,因此子项目需要显式的声 明依赖, version 和 scope 都读取自父 pom。而<dependencies>所有声明在主 pom 的 <dependencies>里的依赖都会自动引入,并默认被所有的子项目继承。

  9. [Recomendación] La biblioteca de terceros no debe tener elementos de configuración y al menos no debe agregar más elementos de configuración.

  10. [Referencia] Para evitar conflictos de dependencia al aplicar bibliotecas de segundas partes, los editores de bibliotecas de segundas partes deben seguir los siguientes principios:
    1) El principio de simplicidad y controlabilidad. Elimine todas las API y dependencias innecesarias, incluidas solo las API de servicio, los objetos de modelo de dominio necesarios
    , las clases de utilidades, las constantes, las enumeraciones, etc. Si depende de otras bibliotecas de terceros, intente introducirlas tal como se proporcionan, permitiendo a los usuarios de las bibliotecas de terceros
    confiar en números de versión específicos; no existe una implementación específica de registro y usted solo confía en el marco de registro.
    2) El principio de trazabilidad estable. Se deben registrar los cambios en cada versión, quién mantiene la biblioteca de terceros y dónde está el código fuente, todo debe ser de
    fácil acceso. El comportamiento de las bibliotecas públicas de terceros no debería cambiar a menos que el usuario actualice activamente la versión.

(3) servidor

  1. [Recomendación] Para servidores de alta concurrencia, se recomienda reducir el tiempo de espera time_wait del protocolo TCP.
    Nota: De forma predeterminada, el sistema operativo cerrará las conexiones en el estado time_wait después de 240 segundos. En condiciones de acceso concurrente elevado,
    es posible que el servidor no pueda establecer nuevas conexiones porque hay demasiadas conexiones en time_wait, por lo que es necesario reducir
    esto. valor de espera.
    正例: 在 linux 服务器上请通过变更/etc/sysctl.conf 文件去修改该缺省值(秒) : net.ipv4.tcp_fin_timeout = 30

  2. [Recomendado] Aumente el número máximo de identificadores de archivos (Descriptor de archivos, abreviado como fd) admitidos por el servidor.
    Nota: El diseño de los sistemas operativos convencionales es administrar las conexiones TCP/UDP de la misma manera que los archivos, es decir, una conexión corresponde a
    un fd. El número máximo de fds admitidos por los servidores Linux convencionales es 1024 de forma predeterminada. Cuando el número de conexiones simultáneas es grande, es fácil provocar un
    error de "abrir demasiados archivos" debido a fds insuficientes, lo que provoca que no se puedan establecer nuevas conexiones. .
    Se recomienda aumentar varias veces el número máximo de identificadores admitidos por el servidor Linux (en relación con la cantidad de memoria en el servidor).

  3. [Recomendado] Establezca el parámetro -XX:+HeapDumpOnOutOfMemoryError en la JVM para permitir que la salida de la JVM
    descargue información cuando encuentre un escenario OOM.
    Nota: OOM ocurre con probabilidad e incluso ocurre regularmente cada pocos meses. La información en el sitio cuando ocurre es
    muy valiosa para la resolución de problemas.


  4. [Recomendación] En un entorno de producción en línea, configure la capacidad de memoria del mismo tamaño para Xms y Xmx de JVM para evitar la presión causada por ajustar el tamaño del montón después de GC .

  5. [Referencia] Utilice forward para la redirección interna del servidor; utilice la clase de herramienta de ensamblaje de URL para generar direcciones de redirección externas; de lo contrario,
    provocará inconsistencias en el mantenimiento de la URL y posibles riesgos de seguridad.

7. Explicación de los nombres propios

  1. POJO (Objeto Java ordinario simple): En este manual, POJO se refiere específicamente a
    clases simples con solo setter/getter/toString, incluidas DO/DTO/BO/VO, etc.
  2. GAV (GroupId, ArtifactctId, Versión): coordenadas de Maven, utilizadas para identificar de forma única el paquete jar.
  3. POO (Programación orientada a objetos): este manual generalmente se refiere al método de programación de clases y objetos.
  4. ORM (Mapeo de relación de objetos): mapeo relacional de objetos, conversión entre el modelo de dominio de objetos y los datos subyacentes.
    Este artículo generalmente se refiere a iBATIS, mybatis y otros marcos.
  5. NPE (java.lang.NullPointerException): excepción de puntero nulo.
  6. SOA (Arquitectura orientada a servicios): arquitectura orientada a servicios, que puede
    distribuir, combinar y utilizar componentes de aplicaciones de grano grueso débilmente acoplados a través de la red según las necesidades, lo que es útil para mejorar la reutilización y la capacidad de mantenimiento de los componentes.
  7. Biblioteca unipartita: la biblioteca (paquete jar) de la que dependen los módulos internos del subproyecto de este proyecto.
  8. Biblioteca de segunda parte: una biblioteca (paquete jar) que la empresa publica internamente en el almacén central y en la que otras aplicaciones dentro de la empresa pueden confiar.
  9. Bibliotecas de terceros: bibliotecas de código abierto (paquetes jar) fuera de la empresa.
  10. IDE (Entorno de desarrollo integrado): una aplicación utilizada para proporcionar un entorno de desarrollo de programas, que generalmente
    incluye herramientas como editores de código, compiladores, depuradores e interfaces gráficas de usuario. Este manual generalmente se refiere a IntelliJ IDEA
    y eclipse.

Supongo que te gusta

Origin blog.csdn.net/qq_42666609/article/details/131912037
Recomendado
Clasificación