阿里巴巴 Java 开发手册部分整理

news2024/11/16 13:27:05

阿里巴巴 Java 开发手册

  • 一、编程规约
    • (一) 命名风格
    • (二) 常量定义
    • (三) 代码格式
    • (四) OOP 规约
    • (五) 集合处理
    • (六) 并发处理
    • (七) 控制语句
    • (八) 注释规约
    • (九) 其它
  • 二、异常日志
    • (一) 异常处理
    • (二) 日志规约
  • 三、单元测试
  • 四、安全规约
  • 五、MySQL 数据库
    • (一) 建表规约
    • (二) 索引规约
    • (三) SQL 语句
    • (四) ORM 映射
  • 六、工程结构
    • (一) 应用分层
    • (二) 二方库依赖
    • (三) 服务器
  • 七、设计规约

一、编程规约

(一) 命名风格

  • 【强制】包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使用
    单数形式,但是类名如果有复数含义,类名可以使用复数形式。
    正例:应用工具类包名为 com.alibaba.ai.util、类名为 MessageUtils(此规则参考 spring
    的框架结构)

  • 【参考】各层命名规约:
    A) Service/DAO 层方法命名规约
    1) 获取单个对象的方法用 get 做前缀。
    2) 获取多个对象的方法用 list 做前缀,复数形式结尾如:listObjects。
    3) 获取统计值的方法用 count 做前缀。
    4) 插入的方法用 save/insert 做前缀。
    5) 删除的方法用 remove/delete 做前缀。
    6) 修改的方法用 update 做前缀。
    B) 领域模型命名规约
    1) 数据对象:xxxDO,xxx 即为数据表名。
    2) 数据传输对象:xxxDTO,xxx 为业务领域相关的名称。
    3) 展示对象:xxxVO,xxx 一般为网页名称。
    4) POJO 是 DO/DTO/BO/VO 的统称,禁止命名成 xxxPOJO。

  • 【强制】类名使用 UpperCamelCase 风格,但以下情形例外:DO / BO / DTO / VO / AO /
    PO / UID 等。
    正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion
    反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion

  • 【推荐】不要使用一个常量类维护所有常量,要按常量功能进行归类,分开维护。
    说明:大而全的常量类,杂乱无章,使用查找功能才能定位到修改的常量,不利于理解和维护。
    正例:缓存相关常量放在类 CacheConsts 下;系统配置相关常量放在类 ConfigConsts 下。

(二) 常量定义

  • 【推荐】如果变量值仅在一个固定范围内变化用 enum 类型来定义。
    说明:如果存在名称之外的延伸属性应使用 enum 类型,下面正例中的数字就是延伸信息,表
    示一年中的第几个季节。
    正例:

    public enum SeasonEnum {
        SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4);
        private int seq;
        SeasonEnum(int seq){
          	this.seq = seq;
       		 }	
    }
    

(三) 代码格式

(四) OOP 规约

  • 【强制】所有的相同类型的包装类对象之间值的比较,全部使用 equals 方法比较。
    说明:对于 Integer var = ? 在-128 至 127 范围内的赋值,Integer 对象是在
    IntegerCache.cache 产生,会复用已有对象,这个区间内的 Integer 值可以直接使用==进行
    判断,但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,这是一个大坑,
    推荐使用 equals 方法进行判断。

    Integer var = 128;
    var.equals(123);
    new Integer(123).equals(var);
    Integer.valueOf(123).equals(var);
    
  • 关于基本数据类型与包装数据类型的使用标准如下:
    1) 【强制】所有的 POJO 类属性必须使用包装数据类型。
    2) 【强制】RPC 方法的返回值和参数必须使用包装数据类型。
    3) 【推荐】所有的局部变量使用基本数据类型。
    说明:POJO 类属性没有初值是提醒使用者在需要使用时,必须自己显式地进行赋值,任何
    NPE 问题,或者入库检查,都由使用者来保证。
    正例:数据库的查询结果可能是 null,因为自动拆箱,用基本数据类型接收有 NPE 风险。
    反例:比如显示成交总额涨跌情况,即正负 x%,x 为基本数据类型,调用的 RPC 服务,调用
    不成功时,返回的是默认值,页面显示为 0%,这是不合理的,应该显示成中划线。所以包装
    数据类型的 null 值,能够表示额外的信息,如:远程调用失败,异常退出。

  • 【强制】定义 DO/DTO/VO 等 POJO 类时,不要设定任何属性默认值。
    反例:POJO 类的 gmtCreate 默认值为 new Date(),但是这个属性在数据提取时并没有置入具
    体值,在更新其它字段时又附带更新了此字段,导致创建时间被修改成当前时间。

  • 【推荐】循环体内,字符串的连接方式,使用 StringBuilder 的 append 方法进行扩展。
    说明:下例中,反编译出的字节码文件显示每次循环都会 new 出一个 StringBuilder 对象,
    然后进行 append 操作,最后通过 toString 方法返回 String 对象,造成内存资源浪费。
    反例:

    String str = "start";
        for (int i = 0; i < 100; i++) {
    		str = str + "hello";
    }
    
  • 【推荐】类成员与方法访问控制从严:
    1) 如果不允许外部直接通过 new 来创建对象,那么构造方法必须是 private。
    2) 工具类不允许有 public 或 default 构造方法。
    3) 类非 static 成员变量并且与子类共享,必须是 protected。
    4) 类非 static 成员变量并且仅在本类使用,必须是 private。
    5) 类 static 成员变量如果仅在本类使用,必须是 private。
    6) 若是 static 成员变量,考虑是否为 final。
    7) 类成员方法只供类内部调用,必须是 private。
    8) 类成员方法只对继承类公开,那么限制为 protected。
    说明:任何类、方法、参数、变量,严控访问范围。过于宽泛的访问范围,不利于模块解耦。
    思考:如果是一个 private 的方法,想删除就删除,可是一个 public 的 service 成员方法或
    成员变量,删除一下,不得手心冒点汗吗?变量像自己的小孩,尽量在自己的视线内,变量作
    用域太大,无限制的到处跑,那么你会担心的。

(五) 集合处理

  • 【强制】使用工具类 Arrays.asList()把数组转换成集合时,不能使用其修改集合相关的方
    法,它的 add/remove/clear 方法会抛出 UnsupportedOperationException 异常。
    说明:asList 的返回对象是一个 Arrays 内部类,并没有实现集合的修改方法。Arrays.asList
    体现的是适配器模式,只是转换接口,后台的数据仍是数组。
    String[] str = new String[] { “you”, “wu” };
    List list = Arrays.asList(str);
    第一种情况:list.add(“yangguanbao”); 运行时异常。
    第二种情况:str[0] = “gujin”; 那么 list.get(0)也会随之修改。

  • 【强制】不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator
    方式,如果并发操作,需要对 Iterator 对象加锁。

    
    正例:
    List<String> list = new ArrayList<>();
    	list.add("1");
    	list.add("2");
    	Iterator<String> iterator = list.iterator();
    	while (iterator.hasNext()) {
    		String item = iterator.next();
    	if (删除元素的条件) {
    		iterator.remove();
    	}
    }
    
    反例:
    for (String item : list) {
    	if ("1".equals(item)) {
    		list.remove(item);
    	}
    }
    说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的
    
  • 【推荐】集合泛型定义时,在 JDK7 及以上,使用 diamond 语法或全省略。
    说明:菱形泛型,即 diamond,直接使用<>来指代前边已经指定的类型。
    正例:

      // <> diamond 方式
        HashMap<String, String> userCache = new HashMap<>(16);
        // 全省略方式
        ArrayList\<User> users = new ArrayList(10);
    
  • 【推荐】高度注意 Map 类集合 K/V 能不能存储 null 值的情况,如下表格:
    请添加图片描述

    反例: 由于 HashMap 的干扰,很多人认为 ConcurrentHashMap 是可以置入 null 值,而事实上,
    存储 null 值时会抛出 NPE 异常。
  • 【参考】利用 Set 元素唯一的特性,可以快速对一个集合进行去重操作,避免使用 List 的
    contains 方法进行遍历、对比、去重操作。

(六) 并发处理

  • 【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPooLExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
    说明:Executors 返回的线程池对象的弊端如下:
    1)FixedThreadPool 和 SingleThreadPool:
    允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
    2)CachedThreadPool 和 ScheduledThreadPool:
    允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

  • 【强制】SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为
    static,必须加锁,或者使用 DateUtils 工具类。
    正例:注意线程安全,使用 DateUtils。亦推荐如下处理:\

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


    说明:如果是 JDK8 的应用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,
    DateTimeFormatter 代替 SimpleDateFormat,官方给出的解释:simple beautiful strong
    immutable thread-safe。

  • 【推荐】使用 CountDownLatch 进行异步转同步操作,每个线程退出前必须调用 countDown
    方法,线程执行代码注意 catch 异常,确保 countDown 方法被执行到,避免主线程无法执行
    至 await 方法,直到超时才返回结果。
    说明:注意,子线程抛出异常堆栈,不能在主线程 try-catch 到。

  • 【推荐】避免 Random 实例被多线程使用,虽然共享该实例是线程安全的,但会因竞争同一seed 导致的性能下降。
    说明:Random 实例包括 java.util.Random 的实例或者 Math.random()的方式。
    正例:在 JDK7 之后,可以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要编码保
    证每个线程持有一个实例。

  • 【参考】ThreadLocal 无法解决共享对象的更新问题,ThreadLocal 对象建议使用 static
    修饰。这个变量是针对一个线程内所有操作共享的,所以设置为静态变量,所有此类实例共享
    此静态变量 ,也就是说在类第一次被使用时装载,只分配一块存储空间,所有此类的对象(只
    要是这个线程内定义的)都可以操控这个变量。

(七) 控制语句

  • 【强制】在高并发场景中,避免使用”等于”判断作为中断或退出的条件。
    说明:如果并发控制没有处理好,容易产生等值判断被“击穿”的情况,使用大于或小于的区间
    判断条件来代替。
    反例:判断剩余奖品数量等于 0 时,终止发放奖品,但因为并发处理错误导致奖品数量瞬间变
    成了负数,这样的话,活动无法终止。

  • 【推荐】循环体中的语句要考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、
    获取数据库连接,进行不必要的 try-catch 操作(这个 try-catch 是否可以移至循环体外)。

  • 【推荐】避免采用取反逻辑运算符。
    说明:取反逻辑不利于快速理解,并且取反逻辑写法必然存在对应的正向逻辑写法。
    正例:使用 if (x < 628) 来表达 x 小于 628。
    反例:使用 if (!(x >= 628)) 来表达 x 小于 628。

(八) 注释规约

  • 【强制】所有的抽象方法(包括接口中的方法)必须要用 Javadoc 注释、除了返回值、参数、
    异常说明外,还必须指出该方法做什么事情,实现什么功能。
    说明:对子类的实现要求,或者调用注意事项,请一并说明。

  • 【参考】谨慎注释掉代码。在上方详细说明,而不是简单地注释掉。如果无用,则删除。
    说明:代码被注释掉有两种可能性:1)后续会恢复此段代码逻辑。2)永久不用。前者如果没
    有备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。

  • 【参考】好的命名、代码结构是自解释的,注释力求精简准确、表达到位。避免出现注释的
    一个极端:过多过滥的注释,代码的逻辑一旦修改,修改注释是相当大的负担。
    反例:

    // put elephant into fridgeput(elephant, fridge);
    


    方法名 put,加上两个有意义的变量名 elephant 和 fridge,已经说明了这是在干什么,语
    义清晰的代码不需要额外的注释。

(九) 其它

  • 【强制】在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
    说明:不要在方法体内定义:Pattern pattern = Pattern.compile(“规则”);

二、异常日志

(一) 异常处理

  • 【强制】有 try 块放到了事务代码中,catch 异常后,如果需要回滚事务,一定要注意手动回
    滚事务。

  • 【强制】finally 块必须对资源对象、流对象进行关闭,有异常也要做 try-catch。
    说明:如果 JDK7 及以上,可以使用 try-with-resources 方式。

  • 【推荐】防止 NPE,是程序员的基本修养,注意 NPE 产生的场景:
    1)返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。
    反例:public int f() { return Integer 对象}, 如果为 null,自动解箱抛 NPE。
    2) 数据库的查询结果可能为 null。
    3) 集合里的元素即使 isNotEmpty,取出的数据元素也可能为 null。
    4) 远程调用返回对象时,一律要求进行空指针判断,防止 NPE。
    5) 对于 Session 中获取的数据,建议 NPE 检查,避免空指针。
    6) 级联调用 obj.getA().getB().getC();一连串调用,易产生 NPE。
    正例:使用 JDK8 的 Optional 类来防止 NPE 问题。

(二) 日志规约

  • 【强制】对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方
    式。
    说明:logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
    如果日志级别是 warn,上述日志不会打印,但是会执行字符串拼接操作,如果 symbol 是对象,
    会执行 toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。
    正例:(条件)建设采用如下方式
    if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
    }
    正例:(占位符)
    logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

  • 【强制】避免重复打印日志,浪费磁盘空间,务必在 log4j.xml 中设置 additivity=false。
    正例:<logger name=“com.taobao.dubbo.config” additivity=“false”>

三、单元测试

四、安全规约

五、MySQL 数据库

(一) 建表规约

  • 【推荐】表的命名最好是加上“业务名称_表的作用”。
    正例:alipay_task / force_project / trade_config

  • 【推荐】库名与应用名称尽量一致。

(二) 索引规约

  • 【推荐】如果有 order by 的场景,请注意利用索引的有序性。order by 最后的字段是组合
    索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
    正例:where a=? and b=? order by c; 索引:a_b_c
    反例:索引中有范围查找,那么索引有序性无法利用,如:WHERE a>10 ORDER BY b; 索引
    a_b 无法排序。

  • 【推荐】建组合索引的时候,区分度最高的在最左边。
    正例:如果 where a=? and b=? ,如果 a 列的几乎接近于唯一值,那么只需要单建 idx_a
    索引即可。
    说明:存在非等号和等号混合时,在建索引时,请把等号条件的列前置。如:where c>? and
    d=? 那么即使 c 的区分度更高,也必须把 d 放在索引的最前列,即索引 idx_d_c。

(三) SQL 语句

  • 【强制】不要使用 count(列名)或 count(常量)来替代 count(*),count(*)是 SQL92 定义的标准统计行数的语法,跟数据库无关,跟 NULL 和非 NULL 无关。
    说明:count(*)会统计值为 NULL 的行,而 count(列名)不会统计此列为 NULL 值的行。

  • 【强制】count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct
    col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。

  • 【强制】当某一列的值全是 NULL 时,count(col)的返回结果为 0,但 sum(col)的返回结果为
    NULL,因此使用 sum()时需注意 NPE 问题。
    正例:可以使用如下方式来避免 sum 的 NPE 问题:SELECT IF(ISNULL(SUM(g)),0,SUM(g))
    FROM table;

  • 【强制】使用 ISNULL()来判断是否为 NULL 值。
    说明:NULL 与任何值的直接比较都为 NULL。
    1) NULL<>NULL 的返回结果是 NULL,而不是 false。
    2) NULL=NULL 的返回结果是 NULL,而不是 true。
    3) NULL<>1 的返回结果是 NULL,而不是 true。

  • 【强制】 在代码中写分页查询逻辑时,若 count 为 0 应直接返回,避免执行后面的分页语句。

  • 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
    说明:以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id
    则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为
    级联更新。外键与级联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻
    塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。

  • 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。

  • 【强制】数据订正(特别是删除、修改记录操作)时,要先 select,避免出现误删除,确认
    无误才能执行更新语句。

  • 【推荐】in 操作能避免则避免,若实在避免不了,需要仔细评估 in 后边的集合元素数量,控
    制在 1000 个之内。

  • 【参考】如果有国际化需要,所有的字符存储与表示,均以 utf-8 编码,注意字符统计函数
    的区别。
    说明:
    SELECT LENGTH(“轻松工作”); 返回为 12
    SELECT CHARACTER_LENGTH(“轻松工作”); 返回为 4
    如果需要存储表情,那么选择 utf8mb4 来进行存储,注意它与 utf-8 编码的区别。

  • 【参考】TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少,但 TRUNCATE
    无事务且不触发 trigger,有可能造成事故,故不建议在开发代码中使用此语句。
    说明:TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同。

(四) ORM 映射

  • 【强制】在表查询中,一律不要使用 * 作为查询的字段列表,需要哪些字段必须明确写明。
    说明:1)增加查询分析器解析成本。2)增减字段容易与 resultMap 配置不一致。3)无用字
    段增加网络消耗,尤其是 text 类型的字段。

  • 【强制】POJO 类的布尔属性不能加 is,而数据库字段必须加 is_,要求在 resultMap 中进行
    字段与属性之间的映射。
    说明:参见定义 POJO 类以及数据库字段定义规定,在<resultMap>中增加映射,是必须的。
    在 MyBatis Generator 生成的代码中,需要进行对应的修改。

  • 【强制】不要用 resultClass 当返回参数,即使所有类属性名与数据库字段一一对应,也需
    要定义;反过来,每一个表也必然有一个 POJO 类与之对应。
    说明:配置映射关系,使字段与 DO 类解耦,方便维护。

  • 【强制】sql.xml 配置参数使用:#{},#param# 不要使用${} 此种方式容易出现 SQL 注入。

  • 【强制】iBATIS 自带的 queryForList(String statementName,int start,int size)不推
    荐使用。
    说明:其实现方式是在数据库取到 statementName 对应的 SQL 语句的所有记录,再通过 subList
    取 start,size 的子集合。
    正例:Map<String, Object> map = new HashMap<>();
    map.put(“start”, start);
    map.put(“size”, size);

  • 【强制】不允许直接拿 HashMap 与 Hashtable 作为查询结果集的输出。
    说明:resultClass=”Hashtable”,会置入字段名和属性值,但是值的类型不可控。

  • 【强制】更新数据表记录时,必须同时更新记录对应的 gmt_modified 字段值为当前时间。

  • 【推荐】不要写一个大而全的数据更新接口。传入为 POJO 类,不管是不是自己的目标更新字段,都进行 update table set c1=value1,c2=value2,c3=value3; 这是不对的。执行 SQL时,不要更新无改动的字段,一是易出错;二是效率低;三是增加 binlog 存储。

  • 【参考】@Transactional 事务不要滥用。事务会影响数据库的 QPS,另外使用事务的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。

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

六、工程结构

(一) 应用分层

  • 【推荐】图中默认上层依赖于下层,箭头关系表示可直接依赖,如:开放接口层可以依赖于
    Web 层,也可以直接依赖于 Service 层,依此类推:

    请添加图片描述


    **开放接口层:**可直接封装 Service 方法暴露成 RPC 接口;通过 Web 封装成 http 接口;进行
    网关安全控制、流量控制等。
    **终端显示层:**各个端的模板渲染并执行显示的层。当前主要是 velocity 渲染,JS 渲染,
    JSP 渲染,移动端展示等。
    **Web 层:**主要是对访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。
    **Service 层:**相对具体的业务逻辑服务层。
    **Manager 层:**通用业务处理层,它有如下特征:
    1) 对第三方平台封装的层,预处理返回结果及转化异常信息;
    2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理;
    3) 与 DAO 层交互,对多个 DAO 的组合复用。
    **DAO 层:**数据访问层,与底层 MySQL、Oracle、Hbase 等进行数据交互。
    **外部接口或第三方平台:**包括其它部门 RPC 开放接口,基础平台,其它公司的 HTTP 接口。

  • 【参考】 (分层异常处理规约)在 DAO 层,产生的异常类型有很多,无法用细粒度的异常进行 catch,使用 catch(Exception e)方式,并 throw new DAOException(e),不需要打印日志,因为日志在 Manager/Service 层一定需要捕获并打印到日志文件中去,如果同台服务器再打日志,浪费性能和存储。在 Service 层出时,必须记录出错日志到磁盘,尽可能带上参数信息,相当于保护案发现场。如果 Manager 层与 Service 同机部署,日志方式与 DAO层处理一致,如果是单独部署,则采用与 Service 一致的处理方式。Web 层绝不应该继续往上抛异常,因为已经处于顶层,如果意识到这个异常将导致页面无法正常渲染,那么就应该直接跳转到友好错误页面,加上用户容易理解的错误提示信息。开放接口层要将异常处理成错误码和错误信息方式返回。

  • 【参考】分层领域模型规约:
    **DO(Data Object):**此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
    **DTO(Data Transfer Object):**数据传输对象,Service 或 Manager 向外传输的对象。
    **BO(Business Object):**业务对象,由 Service 层输出的封装业务逻辑的对象。
    **AO(Application Object):**应用对象,在 Web 层与 Service 层之间抽象的复用对象模型,极为贴近展示层,复用度不高。
    **VO(View Object):**显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
    **Query:**数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止使用 Map 类来传输。

(二) 二方库依赖

  • 【强制】定义 GAV 遵从以下规则:
    1) GroupID 格式:com.{公司/BU }.业务线 [.子业务线],最多 4 级。
    说明:{公司/BU} 例如:alibaba/taobao/tmall/aliexpress 等 BU 一级;子业务线可选。
    正例:com.taobao.jstorm 或 com.alibaba.dubbo.register
    2) ArtifactID 格式:产品线名-模块名。语义不重复不遗漏,先到中央仓库去查证一下。
    正例:dubbo-client / fastjson-api / jstorm-tool
    3) Version:详细规定参考下方。

  • 【强制】二方库版本号命名方式:主版本号.次版本号.修订号
    1) 主版本号:产品方向改变,或者大规模 API 不兼容,或者架构不兼容升级。
    2) 次版本号:保持相对兼容性,增加主要功能特性,影响范围极小的 API 不兼容修改。
    3) 修订号:保持完全兼容性,修复 BUG、新增次要功能特性等。
    说明:注意起始版本号必须为:1.0.0,而不是 0.0.1 正式发布的类库必须先去中央仓库进行查证,使版本号有延续性,正式版本号不允许覆盖升级。如当前版本:1.3.3,那么下一个合理的版本号:1.3.4 或 1.4.0 或 2.0.0

  • 【强制】线上应用不要依赖 SNAPSHOT 版本(安全包除外)。
    说明:不依赖 SNAPSHOT 版本是保证应用发布的幂等性。另外,也可以加快编译时的打包构建。

  • 【强制】依赖于一个二方库群时,必须定义一个统一的版本变量,避免版本号不一致。
    说明:依赖 springframework-core,-context,-beans,它们都是同一个版本,可以定义一个变量来保存版本:${spring.version},定义依赖的时候,引用该版本。

  • 【强制】禁止在子项目的 pom 依赖中出现相同的 GroupId,相同的 ArtifactId,但是不同的Version。
    说明:在本地调试时会使用各子项目指定的版本号,但是合并成一个 war,只能有一个版本号出现在最后的 lib 目录中。可能出现线下调试是正确的,发布到线上却出故障的问题。

(三) 服务器

  • 【推荐】高并发服务器建议调小 TCP 协议的 time_wait 超时时间。
    说明:操作系统默认 240 秒后,才会关闭处于 time_wait 状态的连接,在高并发访问下,服务器端会因为处于 time_wait 的连接数太多,可能无法建立新的连接,所以需要在服务器上调小此等待值。
    正例:在 linux 服务器上请通过变更/etc/sysctl.conf 文件去修改该缺省值(秒):
    net.ipv4.tcp_fin_timeout = 30

  • 【推荐】调大服务器所支持的最大文件句柄数(File Descriptor,简写为 fd)。
    说明:主流操作系统的设计是将 TCP/UDP 连接采用与文件一样的方式去管理,即一个连接对应于一个 fd。主流的 linux 服务器默认所支持最大 fd 数量为 1024,当并发连接数很大时很容易因为 fd 不足而出现“open too many files”错误,导致新的连接无法建立。 建议将 linux服务器所支持的最大句柄数调高数倍(与服务器的内存数量相关)。

  • 【推荐】给 JVM 环境参数设置-XX:+HeapDumpOnOutOfMemoryError 参数,让 JVM 碰到 OOM 场景时输出 dump 信息。
    说明:OOM 的发生是有概率的,甚至相隔数月才出现一例,出错时的堆内信息对解决问题非常有帮助。

  • 【推荐】在线上生产环境,JVM 的 Xms 和 Xmx 设置一样大小的内存容量,避免在 GC 后调整堆大小带来的压力。

  • 【参考】服务器内部重定向使用 forward;外部重定向地址使用 URL 拼装工具类来生成,否则会带来 URL 维护不一致的问题和潜在的安全风险。

七、设计规约

  • 【参考】系统架构设计的目的:
    1. 确定系统边界。确定系统在技术层面上的做与不做。
    2. 确定系统内模块之间的关系。确定模块之间的依赖关系及模块的宏观输入与输出。
    3. 确定指导后续设计与演化的原则。使后续的子系统或模块设计在规定的框架内继续演化。
    4. 确定非功能性需求。非功能性需求是指安全性、可用性、可扩展性等。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 操作pdf工具类

1、获取pdf页数 添加maven依赖&#xff1a; <!-- java获取Pdf文件页码 --><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox</artifactId><version>1.8.11</version></dependency>代码实现&#x…

Goby 漏洞发布|电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞

漏洞名称&#xff1a;电信网关配置管理系统后台 /manager/teletext/material/upload.php 文件上传漏洞 English Name&#xff1a;Telecom system /manager/teletext/material/upload.php fileupload vulnerability CVSS core: 9.8 影响资产数&#xff1a;856 漏洞描述&…

不过时的经典层架构

在《设计服务要考虑的7个维度》中讲到设计一定要把不稳定的部分做封装。今天咱们就从这个角度重新审视一下经典的四层架构。 上面是一个经典层架构的示意图。这个架构大多数的公司和项目都在直接用&#xff0c;或者用其变体。 比如&#xff0c;某大厂上层Client客户端可能是电商…

安卓蓝牙GATT协议介绍

前言 现在低功耗蓝牙&#xff08;BLE&#xff09;连接都是建立在 GATT (Generic Attribute Profile) 协议之上。GATT 是一个在蓝牙连接之上的发送和接收很短的数据段的通用规范&#xff0c;这些很短的数据段被称为属性&#xff08;Attribute&#xff09;。 GAP 详细介绍 GAT…

GBASE金融信创优秀解决方案鉴赏 · 核心业务系统数据库解决方案

为此&#xff0c;实验室特别开设金融信创优秀解决方案专栏&#xff0c;集中展示优秀成果。现在&#xff0c;让我们一起来领略下GBASE的优秀解决方案吧~可点击阅读原文 →《金融信创优秀解决方案--核心业务系统数据库解决方案》。 核心业务系统数据库解决方案 方案简介 随着技…

Android Qcom USB Driver学习(十三)

该系列文章总目录链接与各部分简介&#xff1a; Android Qcom USB Driver学习(零) Android Qcom USB Driver学习(八) Android Qcom USB Driver学习(九) UCSI USB Type-C Connector System Software Interface Specification DPM Device Policy Manager deals with the USB P…

智安网络|驾驭数字化转型时代:加速业务转型的战略

随着科技的飞速发展和数字化时代的到来&#xff0c;企业面临着前所未有的机遇和挑战。数字化正在改变着商业的方方面面&#xff0c;而那些能够及时适应和把握这些变化的企业将脱颖而出。因此&#xff0c;加速企业转型成为了当务之急。 一、为什么需要加速企业转型 1.全球市场竞…

D. Pairs of Segments(最大不相交区间数量)

Problem - D - Codeforces 给定一个由n个线段组成的数组[[l1,r1],[l2,r2],…,[ln,rn]]&#xff0c;其中每个线段用左右端点表示。如果存在至少一个x满足l1≤x≤r1且l2≤x≤r2&#xff0c;则称线段[l1,r1]和[l2,r2]相交。 如果k为偶数&#xff0c;并且可以将该数组的元素分成k/…

VTK裁剪【3】-vtkClipPolyDatavtkPolyPlane问题

前言&#xff1a;本博文主要记录vtkClipPolyData中采用vtkPolyPlane作为裁剪工具时的出现的问题&#xff0c;供各位小伙伴进行参考&#xff0c;避免踩坑&#xff01; 目录 vtkPolyPlane介绍及作用 vtkClipPolyData原理 实现流程&#xff1a; 问题所在&#xff1a; 需求&…

css绘制网格背景

文章目录 前言效果图说明 前言 本篇文章主要简单扼要的去实现css网格背景&#xff0c;并进一步探求其应用原理 效果图 css代码 body::before, body::after {position: fixed;top: 0;left: 0;right: 0;bottom: 0;content: ;background-repeat: repeat;pointer-events: none;o…

企业特权密码管理

随着企业中特权帐户的激增&#xff0c;必须保护的密码数量也大幅增长。跟踪所有这些密码是一项艰巨的任务&#xff0c;为避免敏感密码管理不善&#xff0c;管理员需要在集中式存储库下清点属于所有部门的密码&#xff0c;并管理对它们的直接控制。 部署PMP的好处 PMP是一个安…

Baumer工业相机堡盟工业相机如何使用新版本NEOAPI SDK控制相机数据流的开启和关闭(C#)

Baumer工业相机堡盟工业相机如何使用新版本NEOAPI SDK控制相机数据流的开启和关闭&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK的技术背景Baumer工业相机使用NEOAPISDK控制相机数据流的方式1.引用合适的类文件2.使用NEOAPISDK控制相机数据流的方式2.使用…

市场模式下光伏用户群的电能共享与需求响应模型(matlab代码)

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序复现文章《市场模式下光伏用户群的电能共享与需求响应模型》&#xff0c;为了使光伏用户群内各经济主体能实现有序的电能交易&#xff0c;提出了一种基于光伏电能供需比&#xff08;SDR&#xff09;的内…

JavaScript实现伪随机正态分布

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言什么是正态分布&am…

Jenkins+Allure+Pytest的持续集成

一、配置 allure 环境变量 1、下载 allure是一个命令行工具&#xff0c;可以去 github 下载最新版&#xff1a;https://github.com/allure-framework/allure2/releases 如果你想学习Pytest自动化测试&#xff0c;我这边给你推荐一套视频&#xff0c;这个视频可以说是B站播放全…

图扑智慧地下采矿,“像素游戏”智能呈现

在这个像素世界里&#xff0c;我们需要一个智能地下采矿可视化综合管理平台&#xff0c;来帮助我们管理和监控地下采矿全流程。 图扑软件依托自主研发的 HT for Web 产品&#xff0c;结合三维定制化渲染、动态模拟、物理碰撞、5G、物联网、云计算及大数据等先进技术&#xff0c…

vue+leaflet笔记之热力图

vueleaflet笔记之热力图 文章目录 vueleaflet笔记之热力图开发环境代码简介插件简介与安装使用简介 详细源码(Vue3) 本文介绍了Web端使用 Leaflet开发库展示热力图方法 (底图来源:天地图)&#xff0c;结合leaflet.heat插件可以很容易的做出热力图&#xff0c;通过调整其配置参…

旧系统重构遇到的种种问题

首先我将原来springboot版本升级到2.7.9&#xff0c;spring的docker分层和启动受到了影响&#xff0c;这个在docker镜像大小问题已经讲过&#xff0c;不再赘述&#xff0c;因为维护的人变成为一个人&#xff0c;因此我需要将各代码的版本进行统一&#xff0c;方便维护。 5 sun.…

数据治理(数据模型,数据规范,数据安全,数据成本,元数据,数据质量等)

数据治理是什么?为什么要做数据治理?关于数据治理我们需要做什么? 数据治理无论是在数仓建设过程中还是数仓建设完成之后都是及其重要的,是数据部门基础建设的必经之路,是降本提效,形成企业数据资产的关键一环 一 数据质量管理 1.1 数据质量基本概念 ●数据质量管理(Dat…

【Java-SpringBoot+Vue+MySql】Day3.1-SpringBoot Web开发

目录 前期回顾——SpringBoot与Maven 一、web入门 1、知识点密集区 &#xff08;1&#xff09;spring web依赖 &#xff08;2&#xff09;控制器 ​ (3)路由映射 &#xff08;4&#xff09;URL映射 &#xff08;5&#xff09;Method匹配​编辑 &#xff08;6&#xff09…