前置条件:原则规范
一)统一技术栈
1)关于JDK
统一使用Open JDK,版本最低1.8,几年后可能会升级到17;
避免使用Sun JDK,这是商业软件,而且包含部分私有(com.sun)类库,不利于虚拟机迁移。
新项目会统一要求环境使用Open JDK,而且当前主流操作系统默认预装(具体版本不太一样,有些需要升级)
二)数据库操作
开发人员应熟练掌握标准SQL用法,最低要求:SQL92标准,参考如下:
http://doc.xuehai.net/bd2fad0978e90e09492579599aa5719f543ac5fec.html
编写SQL代码时,不能使用数据库特定函数,如:MySQL的 to_date(),Oracle的 to_char()等;
进一步强调,如果没有特别明确的需求必须使用,则原则上不能使用函数与存储过程;
因此,研发人员应当:
1)源码中仅使用标准SQL语句,都是一些基础的,高级特性的不要使用;
2)不使用函数、存储过程
3)DAO数据层,不能引用任何与SDK有关联的任意对象,如:Oracle中 Clob**等。
这样可以实现,数据库的无缝迁移,特别是在当前国产化环境中,非常重要!
三)构建依赖(Maven/Gradle)
当前工程中对模块依赖有较大问题,粒度较粗,而且是按照横向切分,如:所有Service在一个模块,这样会导致:要么全拿来,要么就别用,负担较重,而且缺乏复用性。
应当按照微服务方式,纵向切分,一个完整的功能是一个模块,如:支付模块、基础模块、调度模块、OCR等;
1)基础类库与平台模块分离,业务模块与平台模块分离;
2)与业务无关,能提供通用底层的方法应归属基础类库模块,如:文件操作、数据库基本操作、一些接口规范定义的抽象类、接口、常量、枚举等,这些被底层封装,可以被任意业务引用。
3)平台基础管理,通用化模块并配合管理界面的内容应被划入平台,平台引用基础类库。
4)业务系统在平台基础上构建自己的项目工程,至此类库、平台都充分复用。
5)创建Maven私服,新项目需要依赖私服获取需要的模块。
四)代码质量
1)项目根POM文件
新项目根POM需要集成平台统一环境:
<groupId>com.iplatform</groupId>
<artifactId>iplatform</artifactId>
2)依赖版本号
在你的POM文件不允许使用版本号,父POM中已经引用的常用第三方库,直接引用无需加版本号;
如果确实没有提供,则说明这是一个新东西,由平台统一添加支持,业务引用即可;
还有一种情况,该第三方类库,是很冷门的,其他项目几乎不用,那么项目可以自行直接引入版本,但这种情况很少,需要由平台负责人审核。
任何私自添加依赖并引入不稳定版本,将被记录为质量事故(违规操作)
3)检查规范性
检查POM文件,查看是否存在第三方依赖、是否带有特定版本号即可快速发现问题
五)关于需求变动
Iplatform平台应用文档
iplatform是一套自研的JAVA基础应用开发套件,该平台提供了通用项目研发支持,能任意插拔其他支持模块,复用性强,积累了多年经验,是前身walker项目升级而来,结合当前流行的前后端分离模式,使开发更为高效。
前端引入了若依,后台完全独立开发,同时参考了若依的数据库中权限表的设计,结合自身特点使更加符合需求,目前支持的基础功能如下:
1)spring security权限的深度二次定制,抛弃注解方式,降低维护量
2)数据库(持久层)抛弃第三方(Hibernate、Mybatis等),直接基于Spring JDBC拓展而来,对常用方法封装,提供基础支持类库,并提供PO自动生成。
3)完善的角色权限设置,支持按钮级
4)支持多租户应用,即:多个客户同时使用一个平台,为云平台运维准备
5)跨数据库操作,研发人员只需要调整配置即可实现不同数据库的无缝迁移(开发中...)。
6)强大的缓存系统,业务使用简单,支持单机内存式缓存一级集中式Redis缓存,无缝切换。
7)独立自研的调度任务,未使用第三方Quartz,配置灵活,稳定,经历过多个项目实战(目前在改造中,计划1月底完成)。
8)对微服务的快速支持,提供Gateway网关模块,可灵活支持集群服务的接入(2.0版本较简单,计划下个版本实现配置化接入)。
9)服务注册抛弃了Euraka(新版本已经闭源),使用阿里的Nacos(需要在环境中自主安装)支持界面管理。
10)操作日志注解式配置
11)提供了基础的管理功能,如:机构、用户、权限、数据字典、菜单、日志、缓存管理、调度任务等。
一)模块说明
1)iplatform-model-pojo
生成的PO对象,数据库操作使用;base模块依赖
2)iplatform-core
平台核心模块,提供了核心的配置和对象,与管理界面无关,可以被扩展的其他平台模块依赖,如:iplatform-scheduler。
目前核心模块内容较少,随着平台完善会逐步积累更多功能。
3)iplatform-base
平台基础模块,提供了整个管理支撑结构,权限定义、用户体系、缓存系统、其他扩展定义等。
该模块提供前端界面使用的API。
通过SPI方式,支持多种安全框架,如:spring security,shiro等,shiro暂未实现。
4)iplatform-base-security
平台安全模块,提供了安全拦截、验证、权限控制等实现,系统支持多种安全框架集成,默认提供了spring security。
该模块依赖base模块,作为base的一个插件模块使用(可以被其他实现替换)
5)iplatform-scheduler
调度任务模块,即:定时任务
6)iplatform-gateway
网关模块,提供服务注册、网关路由、集群负载、参数配置(根据情况决定是否使用spring的配置模块)等服务。
该模块只能独立打包部署。
7)iplatform-ml-openocr
一个开源实现的OCR功能实现模块,引入后可支持表格、保险单、身份证的识别等,持续完善中。
8)deploy-jar-template
标准打包发布模板,在开发中,没有业务应用,需要独立打包运行测试。
二)系统缓存
系统提供了数据缓存支撑,对于持久化数据可实现:初始化缓存、添加缓存、更新缓存、删除缓存操作。
按照规范集成后,研发新创建的缓存数据,会在“缓存管理”模块中看到。
集成步骤如下:
1)定义一个接口
该步骤并非必须,这只是针对存在多种实现方式的情况,如果项目确定必须用redis则可以省略。
/**
* 组织机构缓存提供者使用规范。<p></p>
* 因为存在多种实现,如: Redis 或者 内存,因此需要抽象该接口。
* @author 时克英
* @date 2022-12-03
*/
publicinterfaceDeptCacheProvider {
/**
* 设置是否允许缓存机构的子机构关系,<br>
* 在机构数量非常庞大的时候,即便 Redis 也不太适合存储该关系,因为通常界面会展示较多数据,<br>
* 此时可能退化成数据库查询,或者通过其他 NoSQL 数据库实现。
* @param allow
* @date 2022-12-03
*/
voidsetAllowCacheChildren(booleanallow);
S_deptgetDept(longdeptId);
voidupdateDept(S_depts_dept);
voidremoveDept(longdeptId);
voidputDept(S_depts_dept);
/**
* 返回给定机构,下一级子机构ID集合。
* @param deptId 给定当前机构ID
* @return
* @date 2022-12-03
*/
List<String>getChildrenDeptIdOneLevel(longdeptId);
/**
* 返回给定机构,下一级子机构对象集合。
* @param deptId 给定当前机构ID
* @return
* @date 2022-12-03
*/
List<S_dept>getChildrenDeptOneLevel(longdeptId);
}
2)实现本地缓存方式
参考机构管理,这里代码略...
/**
* 基于本地内存实现的机构缓存提供者。
* @author 时克英
* @date 2022-12-05
*/
publicclassLocalDeptCacheProviderextendsAbstractCacheProvider<S_dept>implementsDeptCacheProvider {......}
3)实现Redis缓存方式
参考机构管理,这里代码略...
publicclassRedisDeptCacheProviderextendsRedisCacheProvider<String>implementsDeptCacheProvider{......}
4)添加到配置Bean
如果存在多种方式的缓存,需要分开配置文件,如:
LocalCacheConfig
注:当配置文件中,redis不可用时才会启用
@Configuration
@ConditionalOnProperty(prefix="iplatform.cache", name="redis-enabled", havingValue="false", matchIfMissing=true)
publicclassLocalCacheConfigextendsCacheConfiguration {...}
RedisCacheConfig
@Configuration
@ConditionalOnProperty(prefix="iplatform.cache", name="redis-enabled", havingValue="true", matchIfMissing=false)
@ConditionalOnClass({RedisCacheProvider.class})
@AutoConfigureAfter(RedisAutoConfiguration.class)
publicclassRedisCacheConfigextendsCacheConfiguration {...}
5)在Controller中注入使用。
三)数据库事务控制
平台对数据库事务进行封装,默认配置基本不需要项目重复配置或修改,具体规则如下:
1)在Service层控制事务,无需使用注解@Transactional标注方法
2)Service对象定义如下格式:
@Service
publicclassUserServiceImplextendsBaseServiceImpl {...}
service命名需要符合Impl后缀。
3)Service实现对象不需要定义接口,因为基本上没有第二种实现。
4)Service层中不能引用缓存对象。
四)多租户使用
一般项目都是单客户使用,如果存在多客户同时使用一套系统,则平台提供支持,只需要在业务表中增加一个“顶级单位”的字段即可,系统管理支持每个客户查看自己的后台数据,相互隔离。
如果无需多租户,则不需要顶级单位字段,那么后台管理只有一个租户,退化为单租户模式。
具体管理功能参考“系统管理”。
五)权限管理
1)权限定义
(有些又称资源定义)针对一个请求方法,即:URL,在若依中使用了“固定的权限字符串”以注解形式定义。
平台中则使用URL方式,一个用户可访问哪些URL,就能看到那些按钮(或请求)
2)权限呈现
URL完全匹配
如:添加(保存)用户,权限定义为:system:user:add,那么对应的请求路径就是:${contextPath}/system/user/add
URL部分匹配
关键字"query",如:system:user:view:query,则用户能够访问:${contextPath}/system/user/view/*,此时/system/user/view/123, /system/user/view/show都可访问,但/system/user/view/123/test就无法访问。
URL放开匹配
如:system:user:select:**,则${contextPath}/system/user/select/123, ${contextPath}/system/user/select/123/test都可访问。
该模式较为放松,在用户需求不需要按钮权限,或者某一个权限不需要细粒度的时候非常有用。否则一个请求都要添加一个按钮管理,非常繁琐。
六)数据权限
数据权限每个项目差异较大,平台会提供一些基础支持,同时提供了默认的几个实现,如:全单位、部门、个人等。同时提供一套机制让研发自己实现定制数据权限。
1)添加权限(菜单)
权限点ID必须以“data_scope,”开头,如:data_scope,dept_org,表示数据权限(本单位数据),dept_org是业务定义的真实权限名称。
2)角色权限分配
在权限分配中,选择角色需要的数据权限如图:
3)研发在业务中开发
在控制器中获取角色设置的“数据权限”,如图:
七)平台参数配置
平台提供了一种“运行参数”,可在系统运行过程中修改参数,实时生效,业务可添加自己的各类参数,并在业务中获取使用,系统在功能“参数配置”中可以管理这些参数。
使用步骤如下:
1)通过界面添加配置参数,或者通过SQL直接在表中添加:s_config
2)定义新添加的参数常量名称(key)
3)在控制器中直接根据名称(key)获取使用,示例:获取是否开启验证码
八)操作日志配置
平台实现了注解方式配置操作日志,在需要日志的方法上配置该注解即可,注解说明如下:
字段说明:
1)title:模块(或功能)名称
2)businessType:枚举类型,业务类别,详见枚举定义
3)operatorType:枚举类型,操作员类别,Manage(后台管理)、Mobile(移动端调用)、ServiceApi(为第三方提供的API接口,非管理界面)、Other(其他)
4)isSaveRequestData:是否报错请求参数
5)isSaveResponseData:是否保存响应结果
九)网关模块
目前仅实现了静态配置,后续要加上动态配置,支持必要的持久化保存等。
调用系统内部其他服务路由规则添加,服务降级支持等。
十)系统启动配置参数(application.yml)
以 iplatform 开头的配置即为平台相关初始化配置
涉及到权限控制的几个参数比较重要,其他的看注释即可。
十一)前端界面功能
略。
十二)待开发或完善
1)调度任务模块,管理界面完成,提供添加界面,并能实现手动启动等功能
2)分页查询时,无需研发调用任何方法,去掉:this.prepareSearchPage();
3)数据字典添加多级树实现。
十三)注意事项
1)注入对象,不要直接使用@AutoWired注解属性,应当在构造函数上使用。
2)系统中除了“Controller”和“ServiceImpl”可以使用注解配置Bean,其他对象一概不允许,只能通过Config类文件方式创建配置。
3)业务Controller必须继承SystemController,继承后可以直接调用一些系统方法,如:获取当前用户等。
4)