跳至主要內容

技术中心大约 9 分钟

现代软件架构的复杂性需要协同开发完成,如何高效地协同呢?无规矩不成方圆,无规范难以协同,比如,制订交通法规表面上是要限制行车权,实际上是保障公众的人身安全,试想如果没有限速,没有红绿灯,谁还敢上路行驶?对软件来说,适当的规范和标准绝不是消灭代码内容的创造性、优雅性,而是限制过度个性化,以一种普遍认可的统一方式一起做事,提升协作效率,降低沟通成本。代码的字里行间流淌的是软件系统的血液,质量的提升是尽可能少踩坑,杜绝踩重复的坑,切实提升系统稳定性,码出质量。

出自:阿里巴巴Java开发手册

目录结构

后端

在实际的开发过程中,需要大家遵循公司的Java包路径规范,有利于项目代码的查找、维护和迁移等,降低开发人员的沟通成本,提升开发效率。

我们主要对一下几个包做出统一规范要求,包括:

  • **.entity包,Java BeanModel层)统一存放的包路径;
  • **.dao包,DAO层文件的统一包路径;
  • **.service包,存放Service层的逻辑代码;
  • **.web包,存放Controller层的逻辑代码;
  • **.config包,统一存放Spring BootConfiguration的包;
  • resources/mappings文件夹,统一存放Mybatis的映射文件。若该模块设计的功能较多,可以在mapping文件夹下增加子文件夹以区分不同的功能;
Java类包路径规范

前端

├── public                # 静态资源
│   ├── favicon.ico       # favicon图标
│   └── index.html        # html 模板
├── src                   # 源代码
│   ├── api               # 所有请求
│   ├── assets            # 图片、svg 等静态资源
│        ├── fonts        # 字体文件
│        ├── icons        # svg图标,自动生成雪碧图,使用 SvgIcon 组建展示
│        ├── images       # 图片资源文件
│        └── svg          # svg图片资源文件
│   ├── components        # 公共组件
│   ├── i18n              # 多语言
│   ├── layouts           # 布局
│   ├── libs              # 公共方法
│   ├── menu              # 菜单配置
│   ├── mixins            # 通用混合
│   ├── mock              # 数据模拟
│   ├── pages             # 所有页面
│   ├── plugins           # 插件
│   ├── router            # 路由配置
│   ├── store             # Vuex 状态管理
│   ├── styles            # 样式管理
│   ├── setting.env.js    # 开发配置文件
│   ├── setting.js        # 业务配置文件
|   ├── styleSetting      # 主题样式配置文件
│   ├── main.js           # 入口文件 加载组件 初始化等
│   └── App.vue           # 入口页面
├── tests                 # 测试管理
├── alias.config.js       # 别名,仅用于配置 WebStorm 识别别名,无实际用处
├── babel.config.js       # babel 配置
├── jest.config.js        # jest 配置
├── package.json          # package.json
└── vue.config.js         # Vue CLI 3 配置

编码规范

以下是框架特殊要求的内容,未完全说明的请参考Alibaba编码规范。

后端编码规范:https://developer.aliyun.com/ebook/394?spm=a2c6h.26392470.ebook-read.32.73e8393ayGEShKopen in new window

前端编码规范:https://woai3c.github.io/front-end-specification/open in new window

注意!!!

前后端都必须配置editorconfig。

以下为配置文件:

# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 4
charset = utf-8
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 300

[*.{groovy,java,kt,kts}]
indent_style = tab
continuation_indent_size = 8

[*.{xml,xsd}]
indent_style = tab

[Makefile]
indent_style = tab

[*.py]
indent_size = 4

[*.js]
indent_size = 4

[*.ts]
indent_size = 4

[*.html]
indent_size = 4

[*.{less,css}]
indent_size = 2

[*.json]
indent_size = 2

[*.{tsx,jsx}]
indent_size = 2

[*.yml]
indent_size = 2

[*.sql]
indent_size = 2

[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

后端

分层结构

​ 由于clzy-web框架主要侧重于web后端开发,并且在实际的项目运用中,clzy-web不参与前端页面的开发,因此在MVC分层架构中,clzy-web主要承担Model、Controller的角色。同时clzy-web也需承担数据持久层(DAO)的角色

代码结构分层open in new window图:

代码分层结构
代码分层结构

CRUD关键类说明

  • MyBatisDao

    MyBatisDao的包路径为com.clzy.web.crud.persistence.annotation.MyBatisDao,该类为注解类,主要用于定义Dao层接口文件。使用该注解的类会被Mybatis识别。

  • BaseEntity

    BaseEntity的包路径为com.clzy.web.crud.persistence.BaseEntity,该类为抽象类,是所有JavaBean的父类。JavaBean继承该类后,可以快速的进行CRUD操作

  • DataEntity

    DataEntity的包路径为com.clzy.web.crud.persistence.DataEntity,该作为所有业务实体的父类。

  • PageEntity

    PageEntity的包路径为com.clzy.web.crud.persistence.PageEntity,该类作为所有支持分页查询的业务实体的父类,该类中的Page对象用以支持分页查询。

  • CrudDao

    CrudDao的包路径为com.clzy.web.crud.persistence.CrudDao,该类为接口类,定义了常用的CRUD操作,业务DAO继承改类,可以方便快捷的进行基本的业务操作。包括增删查改及其批量操作功能。

  • CrudService

    CrudService的包路径为com.clzy.web.crud.service.CrudService,该类可作为所有业务Service的父类,该类中内置了针对业务对象的CRUD功能,且默认支持数据库事务。

  • PageService

    PageService的包路径为com.clzy.web.crud.service.PageService,该类可作为所有需要分页查询的业务Service的父类,该类内置了针对业务对象的CRUD及分页查询功能。

前端

  • tab转空格
    clzy-web前端统一采用vscode + ESlint来实现代码格式化校验。为保证格式校验一次,需要在 setting -> Tab Size中设置,一个tab等于4个空格。

  • css转rem
    clzy-web前端自动计算和更改了根字体大小,因此推荐合理使用rem来进行响应式布局。vscode自带了css到rem的转换。需要在 setting -> Cssrem中设置基准font-size为14px,默认为16

  • 性能优化

    • 在vue2中,所有在data中声明的变量都将会被深度监听,当你的变量很大且具有非常深的层级属性时,不要讲其声明在data中,例如地图对象等。
    • 当你的变量每次改变都是整体改变,例如数组 a = [1,2,3] ,每次对 a 的改变都是给 a 赋一个全新的值 a = [4,5,6] 才会让dom更新,而不是 a 中有某个元素或者其属性变化了就要对dom进行更新的时候,可以将 a 数组通过 Object.freeze()进行冻结已节约性能:a = Object.freeze([1,2,3]) 防止 a 数组中的某个对象元素本身发生变化以后还会触发响应式更新而浪费性能。
    • 其他的对象也类似,没有必要需要数据双向绑定的,可以视情况不在data中声明或者进行冻结

API接口规范

请求约定

接口整体采用Resultful风格,使用GET,POST,DELETE作为请求方式,定义如下:

  • GET请求(Read): 从服务器取出资源(一项或多项);
  • POST请求(Create Or Update): 在服务器新建、更新一个资源;
  • DELETE 请求(Delete): 从服务器删除资源

URL约定

  1. 一般的以/api作为URI起始开头,例: /api/xxx;
  2. 请求资源使用复数形式,并且是名词不能是动词,紧跟/api/后面,例: /api/brokers;
  3. 如果存在子模块,需要以模块的path开头。例:/api/rtus和/api/rtus/cmds
  4. 路径分割避免使用驼峰命名,以单个单词为一层级进行路由分割或者使用单词合并简写的小写;

框架预置请求

主要针对在controller层继承CrudControllerPageController

  1. 分页请求: POST /api/xxx/page
  2. 列表查询: POST /api/xxx/list
  3. 详情查询: GET /api/xxx/
  4. 新建和更新: POST /api/xxx
  5. 逻辑删除: DELETE /api/xxx/
  6. 物理删除: DELETE /api/xxx/force/
  7. 批量逻辑删除/恢复(更新): DELETE /api/xxx/batch?delete=true|false&ids=
  8. 批量物理删除: DELETE /api/xxx/batch/force?ids=

响应及响应码

  1. 所有响应返回都时 JsonResponse<T>
  2. 响应码:请参考后续框架响应码约定

接口文档注解要求

如果采用了clzy-web-starter-doc,那么对controller的说明及请求参数,请按照下面要求:

  1. controller类指定@Api注解,并指定@Api的value属性、与tags属性
  2. controller类接口对应方法指定@ApiOperation注解,并指定@ApiOperation注解的value属性
  3. 在传输的实体类上标注@ApiModel,以及类属性上添加@ApiModelProperty并指定其value属性(value、note、example)

数据库脚本

框架已经集成flyway数据库版本管理工具,所以数据库的变更更新需要按照一定的要求编写脚本。

脚本存放路径

src\main\resources\db\migration

脚本命名要求

格式:V{脚本版本号}__{系统版本}__{脚本名称}.sql

  • {脚本版本号}

采用x.x.x格式,其中x为数字,请按照已有版本号+1,逐步添加自己的脚本。

  • {系统版本}

组长发布的本次系统版本号,在本次开发周期的都将是统一的版本号。

  • {脚本名称}

采用_分割,可以多个单词简单表述脚本的用途

脚本内容要求

脚本内容如果存在多条语句,请写明注释;同时,保证语法的正确。例如:多条语句之间采用;隔开等。

注意事项

  1. 一旦线上环境构建并自动执行后的脚本,原则上是不能再去修改。如果需要修改数据库请创建新的脚本进行变更;
  2. 注意使用drop,delete等关键字的语句,避免数据被误删。尤其是连接已有数据的数据库,但是没有进行版本管理的,可能会造成表被删除重建。
  3. 创建脚本,提交时先更新脚本目录,避免版本号冲突。如果更新发现相同版本号,则更改后提交。可随时与项目组保持沟通,线下沟通好脚本版本号。

版本号

采用:Semantic Versioning(简称 SemVer)

总格式:1.1.0 = 主版本号.小版本.修订号

主版本号:不考虑向下兼容,开发新特性

小版本:考虑向下兼容,开发新特性

修订号:考虑向下兼容,修复bug

其他(待整理)

前端

  • 需要图片占位的一律使用:http://temp.im/open in new window

  • 函数命名
    canXXXXX:判断是否可执行某个动作
    hasXXXXX:判断是否含有某个值
    isXXXXX:判断是否为某个值
    getXXXXX:获取某个值
    setXXXXX:设置某个值
    onXXXX: 触发事件函数

  • 设计UI规范

  • 常用命名及单词:

- 头:header
- 尾:bottom
- 容器: container
- 内容:content / container
- 尾部/页脚:footer
- 页面外围控制整体布局宽度:wrapper
- 导航:nav
- 主导航:mainbav
- 子导航:subnav
- 顶导航:topnav
- 菜单:menu
- 子菜单:submenu
- 侧栏:sidebar
- 上边栏:topSideBar
- 下边栏:bottomSideBar
- 左边栏:leftSidebar
- 右导航:rightSidebar
- 栏目:column
- 左右中:left right center
- 登陆:login
- 登录条:loginBar
- 标志:logo
- 广告:banner
- 主体:main
- 热点:hot
- 新闻:news
- 下载:download
- 搜索:search
- 版权:copyright
- 滚动:scroll
- 按钮:btn
- 内容:content
- 标签页:tab
- 图标: icon
- 注释:note
- 指南:guide
- 购物车:cart
- 当前的: current
- 当前位置:position
- 小技巧:tips
- 加入:join
- 指南:guild
- 服务:service
- 注册:register
- 状态:status
- 投票:vote
- 文章列表:list
- 提示信息:msg
- 栏目标题:title
- 友情链接:friendLink
- 合作伙伴:partner
- 摘要/概要/总结: summary