开发规范
基于本框架进行开发时,请遵循以下开发规范,有助于快速、规范性的编码。
Maven依赖
sofast框架对底层依赖已经做了封装,对于我们新建的微服务工程,只需要依赖so-fast-web-starter
即可。该starter中对常用的依赖已经做好了管理,例如:redis、mybatis、log、springmvc、security等;如果当前微服务需要提供feign接口供其他微服务调用,或者调用其他微服务的feign接口,则需要按需引入sdk依赖即可。
插件部分:只需引入spring-boot-maven-plugin
即可,如果有docker需求,则引入docker-maven-plugin
。
Good:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>so-fast-platform</artifactId>
<groupId>com.sofast.cloud</groupId>
<version>${so.fast.version}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>so-fast-system</artifactId>
<description>平台内置服务-系统管理</description>
<dependencies>
<dependency>
<groupId>com.sofast.cloud</groupId>
<artifactId>so-fast-web-starter</artifactId>
</dependency>
<dependency>
<groupId>com.sofast.cloud</groupId>
<artifactId>so-fast-system-sdk</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
工程结构
so-fast规定了严格的工程目录结构(可参考「目录结构」章节),对于业务开发团队,原则上创建独立的业务服务工程进行开发,不推荐直接在so-fast-pl-cloud工程中直接开发。so-fast-pl-cloud仅用于内置服务的维护。
例如:
xxx-biz-parent
|--xxx-common
|--xxx-backend
| |----xxx-order
| |----xxx-product
|--xxx-sdk
目录结构
在biz下构建业务模块时,尽量设计、拆分合理,不允许直接在biz直接创建controller之类的package,推荐先构建业务模块package,如biz.bills,然后在其下创建基础的controller、domain、entity等package,便于按照业务模块进行拆分,便于进行领域抽象。
Good
system
├── dict
│ ├── controller
│ │ ├── DictDataController.java
│ │ └── DictTypeController.java
│ ├── domain
│ │ └── vo
│ │ ├── DictDataQueryVo.java
│ │ └── DictTypeQueryVo.java
│ ├── entity
│ │ ├── DictData.java
│ │ └── DictType.java
│ ├── mapper
│ │ ├── DictDataMapper.java
│ │ └── DictTypeMapper.java
│ └── service
│ ├── IDictDataService.java
│ ├── IDictTypeService.java
│ └── impl
│ ├── DictDataServiceImpl.java
│ └── DictTypeServiceImpl.java
配置文件
so-fast内置了三套配置文件(dev,test,prod),并通过maven打包工具管理环境的区分。在业务开发进行时,原则上开发人员只允许修改dev配置,对于test和prod应该有专人维护。
对于配置文件中的内容,除数据库、redis、安全配置、文件存储之外配置内容请慎重修改。
配置文件统一交由nacos配置中心进行维护。
异常处理
so-fast框架有统一的异常处理,其中框架内应内置如下通用异常:
SystemException // 自定义异常-内置System模块异常
CommonException // 自定义异常-非模块异常(例如:工具类异常等)
FileException // 自定义异常-文件操作通用异常
BizException // 自定义异常-业务模块通用异常
LockException // 自定义异常-分布式锁用异常
ThirdPartyException // 自定义异常-调用第三方接口异常
由于so-fast内置了统一的异常拦截,在业务开发中需要处理异常的情况下,请使用so-fast内置异常进行异常封装,业务代码中禁止抛出其他异常。如需其他异常定制,请架构师统一处理,禁止开发人员私自乱定义异常。
工具集
so-fast框架内置了通用的工具类,框架内引入了hutool、apache、bouncycastle、okhttp3等依赖,并对外提供统一出口。
utils
├── aop
│ └── SolAopUtils.java // AOP注解操作工具类
├── common
│ ├── SolBase64.java // Base64编码解码
│ ├── SolDateUtils.java // 日期工具类
│ ├── SolObjUtils.java // 对象操作工具类
│ ├── SolStringUtils.java // 字符串工具类
├── context
│ └── SpringUtils.java // Spring容器操作辅助类
├── crypto
│ ├── SolSMUtils.java // 国密算法加解密
│ └── SolSecureUtils.java // 通用加密工具类
├── es
│ └── SolEsUtils.java // ES工具类
├── file
│ ├── SolFileUtils.java // 文件操作工具类
│ └── SolImgUtils.java // 图像处理工具类
├── http
│ └── SolHttpUtils.java // 基于okhttp3的封装
├── i18n
│ └── I18nUtils.java // i18n信息国际化
├── mail
│ └── SolMailUtils.java // 邮件发送工具类
├── network
│ └── NetworkUtils.java // request、response网络操作工具类
├── thread
│ └── ThreadUtils.java // 线程池操作工具类
日志审计
审计日志分为登录日志和操作日志两大块。so-fast框架中对于登录日志和操作日志有专门的表用于记录日志数据,并可通过前端页面进行日志查看登录操作。对于更详细的业务代码执行日志,使用logback进行日志文件的记录。
登录日志
登录日志已经在框架中进行了统一处理,无需关注。前端可通过日志管理菜单进行查看。
操作日志
操作日志,基于spring的AOP原理进行织入拦截。so-fast定义的了LogOperator注解并通过LogAspect实现日志的输出。在需要记录操作记录的接口上添加LogOperator即可实现日志的输出。so-fast内置的输出信息较为简单,包含:操作内容、操作人、URL、操作类型、操作结果、客户端信息、操作时间、操作时长、以及相应的class信息。往往业务开发会有更多的需求,比如记录被操作的数据信息、数据的变化信息等更为详细的操作记录,但基于so-fast通用框架的特点,这些功能没有实现,业务开发团队可依据自身的业务需求定制更为详尽的操作日志。
操作日志使用方式如下:
对需要记录日志的api添加注解@LogOperator,其中两个属性:
title:标题。推荐使用
业务模块-操作标题
的形式type:操作类型。系统内置:增删改查、上传和下载6个固定分类。
@LogOperator(title = "字典管理-根据ID查询", type = Constants.SELECT_OPERATOR)
@LogOperator(title = "字典管理-更新字典数据", type = Constants.UPDATE_OPERATOR)
@LogOperator(title = "字典管理-根据字典ID删除", type = Constants.DELETE_OPERATOR)
@LogOperator(title = "字典管理-新增字典数据", type = Constants.INSERT_OPERATOR)
代码执行日志
对于代码执行日志,so-fast并无明确约束,框架中内置logback,可根据不同业务需求,配置logback进行日志分隔,并通过使用lombok的Slf4j注解创建log对象,不推荐自定义logger对象。
Bad
protected Logger logger = LoggerFactory.getLogger(getClass());
Good
// 使用Slf4j注解,并指定topic,topic对应logback.xml文件中的logger节点的name属性
@Slf4j(topic = "utils-log")
log.info(...)
文件处理
so-fast内置了通用的文件上传下载功能,支持头像、图片、普通文件等多种类型。在使用时,请务必做好文件的存储规划。文件下载尽量通过nginx代理进行处理,不推荐使用API下载文件。对于超大文件的处理,业务组自行斟酌,如有问题请联系国内开发技术委员会。
文件处理相关配置参考:
sofast:
file:
# 头像存储路径
avatarPath: /mnt/sofast/avatar/
# 图片文件上传路径
imagePath: /mnt/sofast/images/
# 文件上传路径
filePath: /mnt/sofast/files/
# nginx代理文件下载地址
proxyPath: /download
API接口规范
推荐使用框架自带的代码生成器进行接口的生成。
API文档
基于前后台分离的开发模式,API文档至关重要。进行接口程开发时,请务必详尽的编写swagger文档。
URL
URL的命名有多种规范,如遵循RESTful的严格要求,可能会给设计开发带来一定的难度和局限,因此so-fast推荐:所有的查询请求尽可能的使用get请求,所有的修改请求均使用post请求。
对于URI的命名请参考如下,此外的情况酌情表达语义。
- 基于id的单条数据查询使用【/{id}】
- 分页查询使用【/page】
- 不分页查询使用【/all】
- 创建数据使用【/create】
- 删除数据使用【/delete】
- 更新数据使用【/update】
- 启用数据使用【/enable】
- 禁用数据使用【/disable】
- 上传文件使用【/upload】
- 下载文件使用【/download】
Bad
/**
* 根据组织名称查询组织信息
**/
@GetMapping("/getbyname")
Good
/**
* 根据组织名称查询组织信息
**/
@GetMapping("/organization/{name}")
在整个系统中,接口层要有清晰的定位,不推荐在接口层处理复杂逻辑,接口层应尽量的轻量优雅:只负责接口数据格式的定义、底层业务的调度、返回值的封装。
基类
so-fast为controller提供了如下基类,其中BaseController封装的token的通用操作,在需要获取token内置信息时,请继承BaseController;BaseFileController封装了基础的文件操作,如需文件上传下载功能请继承BaseFileController。
com.sofast.core.framework.web.controller.BaseController
com.sofast.core.framework.web.controller.BaseFileController
业务层
推荐使用框架自带的代码生成器进行接口的生成。
Service使用接口抽象方式,其中接口命名为IXxxxService,实现类命名为XxxServiceImpl
接口必须集成IService,例:
public interface IDictDataService extends IService<DictData> {
实现类必须集成ServiceImpl,并实现父接口,例:
public class DictDataServiceImpl extends ServiceImpl<DictDataMapper, DictData> implements IDictDataService {
数据层
Domain
domain含有两种对象DTO和VO。
DTO主要针对数据层面和业务处理层面的数据组装,VO主要针对接口层面的的数据格式。业务开发团队进行实际开发时请酌情使用。
Entity
推荐使用框架自带的代码生成器进行接口的生成。
Entity定义数据实体,so-fast集成了Mybatis-plus,并且在test包下面内置了代码生成器,因此entity无需编写,使用代码生成器生成即可,生成之后注意检查swagger注解的有无以及妥当性,对于通用处理(如:更新时间的更新、创建时间的插入),可通过Mybatis-plus提供的MetaObjectHandler的统一实现,详细请参考:com.sofast.core.framework.handler.SolMetaObjectHandler。
Mapper
推荐使用框架自带的代码生成器进行接口的生成。
略
Mapper.xml
推荐使用框架自带的代码生成器进行接口的生成。
对于简单的条件处理,推荐使用Mybatis-plus内置的Wrapper进行处理,对于复杂的条件查询等,可以书写SQL文。
数据库设计规范
通用数据库设计规范不在记述范围,只约定so-fast框架规定的规范:
- 表设计时,如下为通用字段,理论上各表均需添加。
创建用户ID create_user bigint
创建时间 create_time datetime
更新用户ID update_user bigint
更新时间 update_time datetime
逻辑删除Flag delete_flg int
- 状态类字段统一使用char类型,逻辑删除Flag除外;
- 尽量避免出现以【is】开头的字段;
- 字符集使用utf8mb4
- 不允许使用联合主键
- 主键统一为bigint(20)id