如何配置Maven项目为接口各实现生成对应独立Jar包
推荐实现方案
你这个场景最稳妥的实现方式是用Maven多模块结构做隔离,从构建层面保证每个Jar只引入对应平台的实现和依赖,完全不会出现无关代码被打包进去的问题。
项目目录结构参考
小项目不用拆太细,核心公共代码放根工程,每个平台的实现单独做一个子模块即可,结构如下:
your-springboot-app/ ├── pom.xml # 父POM,统一管理依赖版本、插件配置 ├── src/ │ └── main/ │ ├── java/com/yourdomain/ │ │ ├── AppStartup.java # Spring Boot全局启动类 │ │ ├── controller/ # 所有对外接口的Controller层,全部放这里 │ │ └── service/ │ │ └── PlatformOpsService.java # 你定义的公共依赖接口 │ └── resources/ │ └── application.yml # 全局公共配置 ├── platform-win/ # Windows平台实现模块 │ ├── pom.xml │ └── src/main/ │ ├── java/com/yourdomain/service/impl/ │ │ └── WinOpsServiceImpl.java # Windows平台的接口实现类 │ └── resources/ ├── platform-linux/ # Linux平台实现模块,结构同win模块 ├── platform-mac/ # Mac平台实现模块,结构同win模块 └── platform-embedded/ # 嵌入式平台实现模块,结构同win模块
每个子模块里只放对应平台的实现代码、专属依赖,完全不引入其他平台的依赖包,从物理层面做隔离。
具体配置步骤
- 父POM基础配置
父POM的packaging属性设为pom,在<modules>标签里把4个平台子模块全部声明进去,统一管理Spring Boot版本、公共依赖(比如spring-web、lombok这类所有平台都要用的依赖)版本,不用在子模块里重复声明版本号。 - 子模块POM配置
每个平台子模块的POM继承父POM,只做两件事:- 引入当前平台必须的专属依赖,比如Windows平台的本地API依赖、Linux平台的系统调用依赖,其他平台的依赖一概不引
- 配置
spring-boot-maven-plugin插件,指定打包的主类为根工程下的启动类AppStartup,同时给当前模块生成的Jar加专属classifier,比如平台win的包配置<classifier>win</classifier>,打出来的包名会自动带平台标识,不会重名
- Bean注入适配
每个平台的实现类上加@Service注解即可,因为最终打包时每个Jar只会存在一个接口实现类,Spring会自动把该实现注入到Controller的依赖中。如果本地开发时同时加载了多个实现类导致启动报错,可以给每个实现类补一个@ConditionalOnMissingBean(PlatformOpsService.class)注解,保证容器中只会存在一个该接口的实例。 - 打包命令
需要构建对应平台的安装包时,执行带模块指定参数的Maven命令即可,比如打Windows平台的包:
其中mvn clean package -pl platform-win -am-pl platform-win表示只构建win平台模块,-am表示自动构建该模块依赖的上游模块(也就是根工程的核心公共代码),最终生成的Jar只会包含核心代码+win平台实现+win平台专属依赖,不会混入其他平台的内容。
轻量替代方案(仅适合极小项目):如果不想拆多模块,也可以用Maven Profile+条件注解实现:给4个实现类分别加
@ConditionalOnProperty(prefix = "platform", name = "type", havingValue = "xxx")注解,然后配置4个Maven Profile,每个Profile对应一个平台,构建时通过-P参数指定激活的Profile,同时通过资源过滤排除其他平台的实现类和依赖。但这种方式配置容错率低,很容易把其他平台的依赖打进包,后期维护成本高,不推荐使用。
内容的提问来源于stack exchange,提问作者RKA
相关产品推荐
相关产品推荐

