后端工程产品、项目all in one 规范
工程改造
新建std模块(命名规范:[原工程名称]-std,例如pai-park-space : space-std),将原标准产品src(除启动类
Application.java
外)迁移至此模块。(std: standard简写,即代表标准产品)
新建application模块(命名规范:[原工程名称]-application,例如pai-park-space : space-application),迁移原标准产品启动类
Application.java
至此模块,保持原包路径为避免后期项目过多从而导致首层级过于凌乱,新建客制化pom模块(命名规范:[原工程名称]-project,例如[pai-park-space] : space-project),用于存放客制化工程,修改pom文件,添加以下节点
<packaging>pom</packaging>
在客制化pom模块下新建客制化模块(命名规范:[原工程名称]-[项目英文/简拼],例如[pai-park-space] + [海南港航]: space-hngh),用于存放客制化代码
风格1(标准单模块)
pai-park-space 工程根目录(注意所有模块要带工程缩写做前缀,避免Maven .m2目录下Jar同名冲突)
├─space-application 应用启动模块
│ └─src
│ └─main
│ └─java 应用启动模块主类
├─space-project
│ └─contract-hngh 客制化项目模块
│ └─src
│ └─main
│ ├─java 客制化项目模块代码类
│ └─resources 客制化项目模块配置资源
├─space-std 标准模块
│ └─src
│ └─main
│ ├─java 标准模块代码类
│ └─resources 标准模块配置资源
└─doc 文档资源目录
风格2(标准多模块)
pai-contract 工程根目录(注意所有模块要带工程缩写做前缀,避免Maven .m2目录下Jar同名冲突)
├─contract-application 应用启动模块
│ └─src
│ └─main
│ └─java 应用启动模块主类
├─contract-project
│ └─contract-hngh 客制化项目模块
│ └─src
│ └─main
│ ├─java 客制化项目模块代码类
│ └─resources 客制化项目模块配置资源
├─contract-std 标准模块
│ ├─contract-app 标准子模块
│ │ └─src
│ │ └─main
│ │ ├─java 标准子模块代码类
│ │ └─resources 标准子模块配置资源
│ ├─contract-base 标准子模块
│ │ └─src
│ │ └─main
│ │ ├─java 标准子模块代码类
│ │ └─resources 标准子模块配置资源
│ ├─contract-land 标准子模块
│ │ └─src
│ │ └─main
│ │ ├─java 标准子模块代码类
│ │ └─resources 标准子模块配置资源
│ ├─contract-lease 标准子模块
│ │ └─src
│ │ └─main
│ │ ├─java 标准子模块代码类
│ │ └─resources 标准子模块配置资源
│ ├─contract-property 标准子模块
│ │ └─src
│ │ └─main
│ │ ├─java 标准子模块代码类
│ │ └─resources 标准子模块配置资源
│ ├─contract-sale 标准子模块
│ │ └─src
│ │ └─main
│ │ ├─java 标准子模块代码类
│ │ └─resources 标准子模块配置资源
│ ├─contract-template 标准子模块
│ │ └─src
│ │ └─main
│ │ ├─java 标准子模块代码类
│ │ └─resources 标准子模块配置资源
│ └─contract-work-space 标准子模块
│ └─src
│ └─main
│ ├─java 标准子模块代码类
│ └─resources 标准子模块配置资源
└─doc 文档资源目录
application模块pom文件改造
添加
profiles
节点<profiles> <profile> <id>std</id> <activation><!--默认使用标准产品进行开发、打包--> <activeByDefault>true</activeByDefault> </activation> <properties> <product.path>space-std</product.path> </properties> <dependencies> <dependency> <groupId>cn.flyrise</groupId> <artifactId>space-std</artifactId> <version>${space.version}</version> </dependency> </dependencies> </profile> <profile> <id>hngh</id> <properties> <product.path>space-hngh</product.path> </properties> <dependencies> <dependency> <groupId>cn.flyrise</groupId> <artifactId>space-hngh</artifactId> <version>${space.version}</version> </dependency> </dependencies> </profile> </profiles>
默认std标准产品开发
当进行非标准产品开发时,可在idea maven面板中进行勾选切换
添加
build
节点
<build> <finalName>pai-park-space</finalName> <resources> <!-- 执行顺序为3,即使用客制化工程(space-xxx)的resources文件覆盖 【执行顺序2】的标准产品工程resources文件 --> <resource> <directory>../space-project/${product.path}/src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> <!-- 执行顺序为2,即使用标准产品工程(space-std)的resources文件覆盖【执行顺序1】的resources文件 --> <resource> <directory>../space-std/src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> <!-- 执行顺序为1,即先使用本工程(space-application)的resources文件 --> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
工程根目录pom文件改造
将
dependencyManagement
,dependencies
迁移到std模块pom文件中去除
build
节点
std模块pom改造,添加build节点
<build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>mapper/**/*</exclude> </excludes> </resource> </resources> </build>
客制化模块pom改造,
添加build节点
<build> <resources> <resource> <directory>src/main/resources</directory> <excludes> <exclude>mapper/**/*</exclude> </excludes> </resource> </resources> </build>
引入std标准产品模块的依赖
<dependency> <groupId>cn.flyrise</groupId> <artifactId>space-std</artifactId> <version>${space.version}</version> </dependency>
Dockerfile改造
ADD ./target/pai-park-space.jar ./
替换为
ADD ./space-application/target/pai-park-space.jar ./
all in one
实现Service类覆盖
std模块添加BeanConfiguration.java 装载类,对于需要客制化的类进行兼容处理(多项目时会存在A需要客制、B不需要的情况)。
(
@ConditionalOnMissingBean
直接在类声明中使用无效,具体参考说明)package cn.flyrise.pai.park.space.config; /** * bean自动装载配置类(取消配置bean的Service注解,用于客户化定制时更替换实现类) * * @author lhr * @date 2023/8/30 14:38 */ @Configuration public class BeanConfiguration { @Bean @ConditionalOnMissingBean(IRoomService.class) public IRoomService roomService() { return new RoomServiceImpl(); } }
取消需要客制化Service类声明中的@Service注解
改动不大,如:只修改其中的某个方法(如方法为
private
,可改为protected
),则可创建与父类同包名的继承类@Service("roomService") @Transactional(rollbackFor = RuntimeException.class) public class HnghRoomServiceImpl extends RoomServiceImpl { @Override public List<RoomVO> imports(MultipartFile file, String parkId) { // do somethings } }
如改动过大,也可直接整个类(同包、同类名)覆盖即可
VO、PO、DTO …等类覆盖
针对VO、PO、DTO …等类的增减字段、必填变更等,直接复制std模块vo类对象到客制化模块中相同包位置处进行调整即可
注意:
- 先将对应的类复制到客制化工程,提交到git后再进行改动,方便后期回溯改动
- service、mapper、dao.xml尽可能避免完整覆盖,完整覆盖会导致后期回溯变得异常困难,尽量使用上述【实现Service类覆盖】的方式进行覆盖
数据库相关
在客制化模块src/main/resources/meta/sql下新建文件,文件名在原有命名规范上,以_{客制化模块名称}.sql结尾
复制标准产品vo、po类到客制化相同位置,进行类覆盖字段增加
增加字段有特殊处理时应使用上述【Service类覆盖】的方式进行处理
@Service("roomService") @Transactional(rollbackFor = RuntimeException.class) public class HnghRoomServiceImpl extends RoomServiceImpl { @Override public RoomVO add(RoomVO room) { if (CharSequenceUtil.isBlank(room.getNewField())) { throw new RequiredException(I18nUtil.get("new_field")); } return super.add(room); } }
mybatis mapper
新建对应mapper,命名规范为:客制化模块名称+原mapper名称,例:RoomMapper.java-> HngnRoomMapper.java。(用于区分namespace,如有完全新建功能也可置于此处)
新建*.xml,命名规范为:客制化模块名称+原xml名称,例:RoomDao.xml -> HngnRoomDao.xml
<!--namespace指定为上述新建mapper--> <mapper namespace="cn.flyrise.pai.park.space.dao.HnghRoomMapper"> ... </mapper>
继承
<resultMap>
提供了extends
属性,可直接指向原resultMap
实现继承<resultMap type="cn.flyrise.pai.park.space.model.po.RoomPO" id="RoomMap" extends="cn.flyrise.pai.park.space.dao.RoomMapper.RoomMap"> <result property="isUse" column="is_use"/> <!--新增字段--> <result property="canArea" column="can_area"/><!--新增字段--> <result property="sharedArea" column="shared_area"/><!--新增字段--> <result property="useArea" column="use_area"/><!--新增字段--> <result property="isBreak" column="is_break"/><!--新增字段--> </resultMap>
覆盖
<sql>、<select>、<insert>、<update>
使用覆盖机制,将需要客制化的标签复制到新建的xml中进行调整即可注:
<select>、<insert>、<update>
中使用到的<resultMap>、<sql>
需要一并复制,否则mybatis启动报错nacos.yml(复制标准工程至客制化工程后)添加mybatis配置(开发过程在客制化工程中复制标准工程bootstrap-dev.yml,并添加以下配置)
mybatis: overrides: # key为标准产品xml,value为需覆盖的xml RoomDao.xml: HnghRoomDao.xml
注意:如xml文件在mapper目录的下级目录,需要一并配置,例如:
key出现特殊字符需要用”[]”包住,否则会丢失
mybatis: overrides: "[enterprise/ClueEnterpriseMapper.xml]": enterprise/HnghClueEnterpriseMapper.xml
i18n
当部分字段、提示信息与标准产品不同时,可复制std模块下的i18n文件至客制化模块相同位置,按需求替换相应文字即可
common包
在工程【pai-fe】内新建【pai-fe-(项目名称)】,此处以hngh为例,即【pai-fe-hngh】模块,与
VO类覆盖
操作一致,复制需要更改的common包中对应的类到【pai-fe-hngh】模块中相同包位置,根据需求调整后进行覆盖替换。引用包时,根据JVM 的类加载规则【先找到,先加载,后续忽略】的原则,在客制化模块(space-hngh)的pom文件中先引用【pai-fe-hngh】模块,再引用std标准模块,即可达到类覆盖的需求
<dependencies> <dependency> <groupId>cn.flyrise</groupId> <artifactId>pai-fe-hngh</artifactId> <version>2.0.0.0-SNAPSHOT</version> </dependency> <dependency> <groupId>cn.flyrise</groupId> <artifactId>space-std</artifactId> <version>${space.version}</version> </dependency> </dependencies>
发布
pai image publish -n pai-park-space -r http://dev.flyrise.cn:8090/pai-park-space/pai-park-space.git -b dev-2.0.0.0 -P std
增加-P
参数,用于指定打包的profile,如需发布客制版本,以hngh为例,则将 -P std
替换为 -P hngh
进行发布即可
注意事项
idea切换profile的时候,有可能会导致不同工程模块文件冲突、或者会出现代码覆盖未达预期的情况,此时可考虑执行以下maven命令进行修复:
maven clean compile
后续
此方案进入实施阶段,可能会存在未考虑部分客制化实现的情况,需要大家集思广益、共同努力,希望大家多多思考,共同完善,使我们从繁乱的分支解放出来,最大程度达到即可在项目中完善标准产品,也能完美交付项目的理想状态。