一个基于spring cloud实现的脚手架。所实现功能如下:
- 接口文档自动生成(利用idea yapi插件上传到yapi server)
- 可以生成mock数据,充分发挥前后端分离的作用
- 部署灵活,服务可合并(合并后服务间通过内部进程通信;分开后通过rpc通信)部署,合并后也可拆分开部署
- 业务无关代码自动生成
- 接口支持加密与签名
- 业务无关功能(如日志打印、公共配置、常用工具类等)抽象为starter
- 支持web接口日志、feign日志、method注解日志、mybatis日志、mq消费者日志打印,日志级别可配置
- 支持多数据源、分表分库、分布式事务
- 支持多语言(国际化)
- 敏感配置信息支持加密,表隐私字段加解密
- 本地限流注解
- 分布式锁注解,缓存注解
- mq(rabbitmq)消费失败,通过自定义注解实现重试(放入延迟队列重新消费)
- 日志敏感数据脱敏
- 单体服务开发接阶段测试不依赖其他服务(mock test、关闭nacos、sentinel等)
- 技术栈稳定、实用、易用
示例工程见smart-cloud-examples
smart-cloud
├── smart-api-core -- 接口权限、加解密、签名等注解 && 用户上下文
│ ├──smart-api-annotation -- 接口权限、加解密、签名等注解
│ └──smart-user-context -- 用户上下文
├── smart-code-generate -- 代码生成
├── smart-common-pojo -- 公共对象(VO、DTO、BO、DO等)
├── smart-common-web -- web模块公共处理
├── smart-constants -- 常量模块
├── smart-exception -- 异常模块
├── smart-mask -- 敏感数据混淆
├── smart-test -- test封装
│ ├──smart-cloud-starter-test -- test封装
│ ├──smart-cloud-starter-test-mock-rabbitmq -- test rabbitmq模块封装
│ ├──smart-cloud-starter-test-mock-redis -- test redis模块封装
│ └──smart-cloud-test-core -- test 单元测试、集成测试封装
├── smart-utility -- 工具类
└── smart-could-starter -- 框架封装
├── smart-cloud-starter-configure -- 框架配置属性封装
├── smart-cloud-starter-core -- 框架核心(自定义注解、异常封装、请求响应公共参数、业务相关工具类)
├── smart-cloud-starter-elasticsearch-dynamic-datasource -- elasticsearch动态数据源
├── smart-cloud-starter-feign -- feign封装(可拆可合、切面处理)
├── smart-cloud-starter-global-id -- 分布式id生成器
├── smart-cloud-starter-job -- 定时任务封装
├── smart-cloud-starter-locale -- 国际化封装
├── smart-cloud-starter-log4j2 -- 日志封装(log4j2日志打印,支持日志敏感数据脱敏)
├── smart-cloud-starter-logback -- 日志封装(logback日志打印,支持日志敏感数据脱敏)
├── smart-cloud-starter-method-log -- 方法切面日志封装
├── smart-cloud-starter-mock -- mock封装(mock工具类、常用mock策略、请求接口mock拦截器)
├── smart-cloud-starter-mp-shardingjdbc -- mybatis plus、dynamic-datasource、shardingjdbc封装(支持多数据源、分库分表、分布式事务;mapper工具类)
├── smart-cloud-starter-mybatis-plus -- mybatis plus、dynamic-datasource封装(支持多数据源、分布式事务;mapper工具类、表隐私字段加解密等)
├── smart-cloud-starter-rabbitmq -- rabbitmq封装(消费失败,自动放入延迟队列重新消费)
├── smart-cloud-starter-rate-limit -- 接口限流
├── smart-cloud-starter-redis -- redis封装、自定义分布式锁注解
└── smart-cloud-starter-web -- web封装(日志切面、异常处理、参数校验)
名称 | 说明 |
---|---|
spring boot | 手脚架 |
spring cloud gateway | 服务网关 |
nacos | 服务注册、配置中心 |
spring boot admin | 服务监控 |
openfeign | 声明式服务调用 |
sleuth、log4j2 | 链路追踪、日志 |
mybatis 、mybatis plus | ORM |
dynamic-datasource | 多数据源 |
seata | 分布式事务 |
sharding jdbc | 分库分表 |
redis、embedded-redis | 缓存、集成测试 |
sentinel | 限流、熔断降级 |
rabbitmq | 消息队列 |
fastdfs | 文件存储 |
xxl-job | 定时任务 |
easyexcel | excel导入导出 |
Hibernator-Validator | 参数校验 |
mockito、podam | 单元测试、数据mock |
h2 | 数据库集成测试 |
embedded-redis | redis集成测试 |
rabbitmq-mock | rabbitmq集成测试 |
embedded-elasticsearch | elasticsearch集成测试 |
freemarker | 用于代码生成 |
yapi、idea yapi upload plugin | 接口文档 |
jasypt-spring-boot | 配置文件中敏感数据加解密 |
Lombok | 简化代码 |
- 合并服务只需修改pom.xml,将待合并的服务import进去即可。
- rpc接口通过自定义注解SmartFeignClient实现。单个服务独自部署时,FeignClient会生效;当服务提供者和服务消费者合并部署时,FeignClient注解会失效,此时rpc接口将通过实现类对象直接调用。具体逻辑见SmartFeignClientCondition。
单个服务以jar的形式,通过maven引入合并服务中。在单体服务中,feign接口通过http请求;服务合并后,feign接口通过内部进程的方式通信。
不同服务合并打一起后,会存在bean名称冲突的问题。通过自定义bean名称生成规则解决。
自定义条件注解封装FeignClient。使其在单体服务时,rpc走feign;在合体服务时,rpc走内部进程通信。
自定义注解YamlScan,用来加载配置的yaml文件(支持正则匹配)。通过SPI机制,在spring.factories文件中添加EnvironmentPostProcessor的实现类,通过其方法参数SpringApplication获取启动类的信息,从而获取YamlScan注解配置的yaml文件信息。然后将yaml文件加到ConfigurableEnvironment中。
自定义条件注解SmartSpringCloudApplicationCondition,只会让启动类标记的启动注解生效。
合体服务打包时,单体服务依赖的包也打进单体服务jar。通过maven profiles解决
1.从日志侧切入,自定义标签,打印日志时进行脱敏处理;
2.自定义jackson的序列化器;打印日志时,采用自定义的序列化器;
3.通过反射获取log传入参数的MaskRule注解信息,最终根据注解规则进行字符串的截取与替换。
接口通过切面拦截的方式,通过反射可以获取返回对象的所有信息,然后根据对象的属性类型,可以随机生成数据;对于特定要求的数据,可以制定mock规则,生成指定格式的数据。
利用单元测试,提高测试覆盖率。
- 在集成测试下,关闭nacos,减少依赖。
- 依赖的服务rpc接口,通过mockito走挡板。
- redis层使用embedded-redis做集成测试。
- rabbitmq层使用rabbitmq-mock做集成测试
- 数据库层使用h2做集成测试(另外两种方案:方案一通过事务回滚还原测试用例对DB的修改;方案二在测试用例执行前删除相关的表)。
通过idea yapi upload plugin插件,上传到yapi server
所属模块 | code | message |
---|---|---|
smart-constants | 200 | 成功 |
smart-constants | 101 | 校验失败 |
smart-constants | 102 | 数据不存在 |
smart-constants | 103 | 数据已存在 |
smart-constants | 400 | 签名错误 |
smart-constants | 401 | 无权限访问 |
smart-constants | 404 | 请求url错误 |
smart-constants | 408 | 请求超时 |
smart-constants | 409 | 重复提交 |
smart-constants | 412 | 参数不全 |
smart-constants | 415 | 请求方式不支持 |
smart-constants | 416 | 请求类型不支持 |
smart-constants | 417 | 获取锁失败 |
smart-constants | 418 | 上传文件大小超过限制 |
smart-constants | 419 | 当前会话已失效,请重新登陆 |
smart-constants | 420 | 请求入参json解析异常 |
smart-constants | 421 | 接口访问太频繁,请稍后再试 |
smart-constants | 500 | 服务器异常 |
smart-constants | 501 | 获取Request失败 |
smart-constants | 502 | 获取Response失败 |
smart-constants | 503 | rpc请求失败 |
smart-constants | 504 | rpc返回结果异常 |
smart-cloud-starter-web | 2001 | 待校验参数object不能为null |
smart-cloud-starter-elasticsearch-dynamic-datasource | 3001 | elasticsearch ds key不存在 |
smart-cloud-starter-elasticsearch-dynamic-datasource | 3002 | elasticsearch 数据源未找到 |
smart-cloud-starter-elasticsearch-dynamic-datasource | 3003 | elasticsearch 动态数据源属性未配置 |