Author Avatar
Jafir Mar 01, 2024

以下规范中未提到的,均已alibaba规范为主

1.java编码规范(包名、类名、方法名、变量名、枚举、静态常量、工具包名、微服务名)

  • 1.1:包名:全部小写,多个单词新建包
  • 1.2:类名:大驼峰
  • 1.3:方法名:增删改查, addXxx、delXxxx、updateXxx、getOneByXxx2Xxx2Xxx、getList、、、、、
  • 1.4:变量名:小驼峰,常规全局统一
  • 1.5:枚举:属性名(大写,多单词下划线)、类名(XxxEnum)
  • 1.6:静态变量:(大写,多单词下划线)(私有的就各自类内部定义)(公共:不同功能模块分别定义不同文件)
  • 1.7:工具包名:(包名:util)(类名:XxxUtils)
  • 1.8:微服务名:xxx-service
  • 1.9:注释:只在service接口层增加注释,以及实现内中复杂逻辑增加注释
  • 2.0:XxxxDTO XxxxVO 后缀均为大写


2.微服务项目相关模块以及包名规范

  • 2.1:模块命名为xxx-service、xxx-interface
  • 2.2:handler包下:
    • 2.2.1:ExceptionHandler(全局异常拦截器)
    • 2.2.2:MetaObjectHandler(mybatisplus自动注入)
  • 2.3:config包下:
    • 2.3.1:MybatisPlusConfig(mybatisplus数据库分页插件)
    • 2.3.2:SwaggerConfig(swagger配置类)
  • 2.4:exception包下:
    • 2.4.1:ExceptionEnum(业务异常枚举)
  • 2.5:feign包下:
    • 2.5.1:接口命名规范为:xxx(调用方)FeignClientApi
    • 2.5.2:例如:public interface AppFeignClientAPI extends AppFeignApi {}
  • 2.6:interface模块:
    • 2.6.1:接口命名规范为:xxx(被调用方)FeignApi
    • 2.6.2:例如:public interface ProjectFeignApi {}
    • 2.6.3:包名为:com.xiaoxi.xxxinterface
    • 2.6.4:接口模块名为:api
    • 2.6.5:例如:com.xiaoxi.xxxinterface.api.XXXFeignApi
    • 2.6.6:如果interface和service出现重复DTO、VO 就copy一份


3.数据库命名规范(库名、表名、字段名、字段长度、类型)

  • 3.1:库名:小写,多单词下划线隔开
  • 3.2:表名:小写,多单词下划线隔开
  • 3.3:字段名:小写,多单词下划线隔开
  • 3.4:字段类型:性别之类以及Boolean类型——tinyint(男女/10),只有大于255长度,选用text,全局varchar
  • 3.5:全局字段加上:create_time、update_time
  • 3.6:字符集:utf8mb4
  • 3.7:排序规则:utf8mb4_bin
    • 3.8 数据库表、字段必须写注释

4.返回值、接受参数、查询参数、实体类命名

  • 4.1:DTO定义:
    • 4.1.1:定义基础BaseDTO
    • 4.1.2:各自根据业务,实现XxxxDTO、XxxxAddDTO、XxxUpdateDTO,可采用继承
  • 4.2:实体类包名修改为:model,分别包含(dto、vo、entity)
  • 4.3:service层,只需要抛出自定义异常即可,不需要抛出 Result.Error
  • 4.4:service返回值,禁止直接返回Result,统一返回业务类,由controller接受业务类,然后进行Result返回
  • 4.5:controller禁止编码业务逻辑,以及额外判断

5.传统风格接口规范

接口风格为传统get post风格,url语义化
例如

接口url

对于数据资源(数据表)
xxx代表数据库表,例如track关注表

  • /xxx/add 新增
  • /xxx/update 编辑
  • /xxx/del 删除一个
  • /xxx/get 获取一个
  • /xxx/getList 所有列表
  • /xxx/pagetList 分页
  • /xxx/addList 批量新增
  • /xxx/delList 批量删除
    在初期数据表和mybatis生成器会生成固定的这些接口方法

对于业务功能(目前大多数是这个)

  • /业务模块/getXXXXList 获取xxxx类型列表
  • /业务模块/动词名词 业务上的通常是 动名词结合url
    比如 /user/updatePhone /user/updatePwd /user/register
  • /业务模块/子功能
    比如 /as/topcharts/game /as/topcharts/app

6.restful风格接口规范

接口风格为restful风格get、post、delete、put风格
例如

接口url

对于数据资源(数据表)
xxx代表数据库表,例如track关注表

  • /xxx 新增(post,数组参数)
  • /xxx/{id} 编辑(put)
  • /xxx/{id} 删除一个(delete)
  • /xxx/{id} 获取一个(get)
  • /xxx 所有列表(get,无参)
  • /xxx 分页列表(get,带分页参数)
  • /xxx/{id,id,id} 批量删除(delete)
    在初期数据表和mybatis生成器会生成固定的这些接口方法

对于业务功能(目前大多数是这个)

  • /业务模块/XXXX 获取xxxx类型列表
  • /业务模块/名词 ,通过请求方式区分请求操作
    比如 /user/{id}/Phone /user/{id}/password
  • /业务模块/子资源
    比如 /as/topcharts/game /as/topcharts/app
  • 登录、注册、注销接口
    • 登录:/业务模块/login (post)
    • 注册:/业务模块/regist (post)
    • 注销:/业务模块/logout (delete)
注意:有参数都是?xxx=xxx的方式,而不是在path上直接添加 (如果是string类型,字符串里面包含/就可能出问题 避免坑),Path路径只允许携带id或者类型

7.注释规范

  • 类注释
    /**

    • TODO
    • @version 1.0
    • @author
    • @date ${DATE} ${TIME}
      */
  • 方法接口注释
    **

    • TODO
    • @author
    • @date $date$ $time$
    • $params$
    • @return $return$
      */

8.异常和日志

  • 调用外部服务等可能异常的代码块,用 try/catch 代码块捕获并在catch中记录异常跟踪日志及业务逻辑处理
  • 禁止吞掉异常信息
        禁止catch里不做任何记录和处理,吞掉异常及其堆栈信息

    禁止: logger.error(“XXX操作异常”) 或 logger.error(“XXX操作异常”+e) 或 e.printStackTrace()

    正确: logger.error(“XXX操作异常”, e)

  • 对于非预期的条件,尽量增加else记录跟踪日志
  • 日志记录logger需使用Slf4J代理声明,禁止绑死具体日志系统的API,避免后期更换日志组件导致代码的大量改动
        private static final Logger log = LoggerFactory.getLogger(OrganizationServiceImpl.class);

     如采用了lombok,可用 @Slf4j 注解替代以上声明。

  • 对 trace/debug/info 级别的日志输出,必须使用占位符形式,避免直接String拼接异常信息(即使日志级别不匹配也会执行拼接操作空耗资源)。
        正确写法如:

       log.debug(“当前用户id: {} ,操作对象: {}=>{} “, userId, objectType, objectId);

      或条件输出形式如:

        if(log.isDebugEnabled()){

           log.debug(“当前用户id: “+id+” ,操作对象: “+ objectType +”=> “+ objectId);

         }

9.逻辑代码规范

  • 接口类中的方法不需添加 public 修饰符
  • 需要序列化的Bean类统一实现Serializable接口并用IDE生成serialVersionUID

public class MyEntity implements Serializable {

       private static final long serialVersionUID = 123456L;

       …

    }

  • if/else/for/while语句后必须使用大括号,即使只有一行代码。
  • 避免NPE(NullPointException)的一些建议:

    • equals比较将非空对象前置:如 “true”.equals(request.getParameter(“isXx”)),即使后者为空也不会导致NPE。
    • 数据库字段可空的映射属性使用包装类型定义:如基本数据类型的int映射到数据库的null值将产生NPE,而用包装类型 Integer 则不会。
    • 可能为空的变量进行必要判空,并在非预期条件下打印必要的跟踪日志,不但避免NPE,还非常便于跟踪调试。
    • 级联调用 obj.getA().getB().getC() 易产生 NPE,先进行判空或使用 JDK8 的 Optional 类包装。
    • 封装统一的判空类用于常用类型的判空,代码需要判空时统一调用即可。如 XX.isEmpty(), XX.isNotEmpty()
  • 禁止在循环中执行耗时的操作,如在循环中执行SQL语句/调用外部服务等


        // 错误的示例:

    for(Long id : idList){

      // 循环执行SQL查询或调用外部系统接口,产生性能问题

      Entity entity = xxService.getEntityById(id);

       …

    }

    // 此案例的更优方案是 通过idList一次性查询获取到Entity集合,然后转换为Map供后续获取。

  • 需要保证写一致性的逻辑,在外层方法上添加事务 @Transactional(rollbackFor = Exception.class)
  • 需要多次使用的可复用对象将对象单独定义,禁止多次调用取不同属性。如:


        String name = userService.getUser(id).getName();

    Long deptId = userService.getUser(id).getDepeId();

    替换为:

    User user = userService.getUser(id); String name = user.getName(), ….

10.安全规范

  • 用户敏感数据禁止列表展示/导出,需要做脱敏处理,如:身份证、手机号、银行卡信息等(具体参考需求)
  • 禁止写死后台管理页面的登录账号密码,为系统增加安全风险(测试阶段除外)
  • 禁止代码/配置文件中出现与生产环境相关的明文密码
  • 禁止侵犯他人版权,如:版权代码、版权图片、版权字体等
  • 禁止数据库中存明文密码,必须加密存储
  • 网络传输数据,除非使用https加密协议,否则必须进行对称加密或者非对称加密处理

11.OOP规范

  • 不能使用过时的类或方法
  • 所有的覆写方法,必须加@Override 注解
  • 所有的 POJO 类属性必须使用包装数据类型
  • RPC 方法的返回值和参数必须使用包装数据类型
  • 构造方法里面禁止加入任何业务逻辑,如果有初始化逻辑,请放在 init 方法中
  • 使用集合转数组的方法,必须使用集合的 toArray(T[] array),传入的是类型完全一样的数组,大小就是 list.size()
  • 不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用 Iterator方式,如果并发操作,需要对 Iterator 对象加锁

12.并发相关

  • 线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险
  • SimpleDateFormat 是线程不安全的类,一般不要定义为 static 变量,如果定义为static,必须加锁
  • 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程

本项目相关

  • 时间撮:入参出参都是秒级
  • 设备类型:AsDevice(字符串传递)
  • OS版本:ASOs(字符串传递)
  • 榜单类型:AsPid(字符串传递)
  • 有效/无效变动:0(有效)/1(无效)