如何用不同的控制器编译使用相同应用程序文件的多个 jars
Posted
技术标签:
【中文标题】如何用不同的控制器编译使用相同应用程序文件的多个 jars【英文标题】:How to compile multiple jars that uses same application file with different controllers 【发布时间】:2020-08-02 20:45:51 【问题描述】:我正在编写一个 weather
服务,其中有 2 个提供商 weather-1
和 weather-2
。我有两个 Spring Controller
类 controller-1
和 controller-2
分别调用这两个服务。
我的意图是在两个气象服务 jar 之间切换,比如如果我想从 weather-1
获取气象数据,那么 controller-1
必须与 weather-1.jar
文件一起编译,而 controller-2
保持不变。
我已经为build-weather-1.gradle
和build-weather-2.gradle
等服务尝试了两个不同的Gradle
文件。
两者都有自己的 jar
依赖项。
build-weather-1.gradle
implementation 'com.xxx.weather:weather-1:0.0.1'
build-weather-2.gradle
implementation 'com.xxx.weather:weather-2:0.0.1'
我使用命令 - gradle -b build-weather-1.gradle build
运行了 build-weather-1.gradle
。不幸的是,这个构建文件也需要其他服务类控制器。
error: package com.xxx.weather.weather-2 does not exist
我已经排除了如下包,
sourceSets
main
java
exclude 'com/xxxx/weatherservice/controller/Weather2Controller.java'
但是这个接口(weather-2
) 在 Application.java 文件中被声明为一个 bean,它会抛出 package not found 错误。
如何解决这个错误?
【问题讨论】:
我不太清楚为什么要在同一个项目中保留两个不同的服务控制器。但是,您是否尝试过在父项目下创建两个不同的模块,并将控制器与相应的构建文件一起放置在各自的模块中? 【参考方案1】:您可以考虑以下模式:
-
定义一个通用的
WeatherService
接口。
两个天气服务都实现了这个接口。
实现单个控制器,通过其构造函数注入WeatherService
的实现。
这是一个应用依赖倒置原则的例子,来自SOLID principles:
高级模块不应依赖于低级模块。两者都应该依赖于抽象(例如,接口)。抽象不应该依赖于细节。细节(具体实现)应该依赖于抽象。
在您的应用程序中,控制器(实现)依赖于WeatherService
接口(抽象),而不是具体的天气服务实现。
完成上述操作后,有许多选项可用于部署使用所需天气服务实施的控制器。其中包括:
在您的main()
方法中或使用您选择的依赖注入方法:构造所需天气服务实现的实例,并使用该实例构造控制器。
使每个天气服务实现成为一个插件,使用类似PF4J
使用反射来查找和构造已放置在运行时类路径中的任何天气服务实现(假设您将每个天气服务实现编译为单独的 JAR,以及包含 WeatherService
接口和控制器的核心 JAR)。
【讨论】:
【参考方案2】:我认为,如果您的项目需要彼此独立构建,您应该将它们作为单独的项目保存(在这种情况下,您仍然可以通过其他项目可能依赖的第三个库项目共享一些代码)。
如果您仍想将它们保留在相同的 gradle 结构中,您应该查看guide 中提到的多模块设置,并将每个子模块的构建配置保留在其自己的 build.gradle 文件中。
【讨论】:
以上是关于如何用不同的控制器编译使用相同应用程序文件的多个 jars的主要内容,如果未能解决你的问题,请参考以下文章