方案关键词:maven -> scope -> runtime
微服务概念、特性啥的网上很多,这里略过,有兴趣的可以Google。 微服务架构的优势与不足 什么是微服务架构? 但是其中最基本的一个特性就是 服务接口API对服务调用方Consumer可见,但是服务实现Provider对Consumer不可见 这样服务双方解耦后,方便快速迭代。
dubbo
为例:服务调用方配置如下:
pom.xml
<dependency>
<groupId>com.goobai.aics</groupId>
<artifactId>aics-data-api</artifactId>
<version>1.0.0</version>
</dependency>
applicationContext.xml
<dubbo:reference version="1.0" id="productService" interface="com.goobai.aics.data.api.service.ProductService"/>
可以看出调用方是只能引用aics-data-api中的服务接口ProductService,该服务的实现是不可见的。
如果接口是HTTP协议的话,服务调用方和提供方的耦合甚至更低,provider连api的jar包都不需要提供,只需要提供api接口说明文档即可。当然,provider的实现也对Consumer不可见。
新项目在开始阶段的时候,开发人员少、代码量也不多,标准微服务带来的好处并不明显,反而容易增加代码管理成本,比如调试、排错等(打开的IDE也多)。但是使用单体应用模式,又担心项目增长后,迁移到微服务的代价太大。 面对这种情况,我们团队在开发过程中逐步摸索了一个简单的办法,在单体应用中使用maven实现对微服务的模拟,既可以在前期实现快速开发,又大大降低了微服务化的成本。
下面实例中以aics-data-api为服务接口,aics-data-provider为服务实现者,aics-server为服务调用方
Maven项目架构如下图所示: aics-data-api是服务api,aics-data-provider是服务实现,aics-server是服务调用方
具体实现如下:
public class ProductSevice {
Optional<Product> queryById(int id)
}
Provider中的Spring配置文件,叫做data-applicationContext.xml
(名字其实都可以,但是不能跟consumer一样,方便在consumer的spring引用)
@Service
public class ProductServiceImpl implements ProductService {
@Resource
private ProductMapper productMapper;
@Override
Optional<Product> queryById(int id) {
return Optional.ofNullable(productMapper.selectByPrimaryKey(id));
}
}
服务调用方(aics-server)的pom.xml
<dependency>
<groupId>com.goobai.aics</groupId>
<artifactId>aics-data-api</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.goobai.aics</groupId>
<artifactId>aics-data-provider</artifactId>
<version>1.0.0</version>
<scope>runtime</scope>
</dependency>
重点!!!: 注意看上面两个jar的scope,其中api的是compile,provider的是runtime
applicationContext.xml
<import resource="classpath*:data-applicationContext.xml" />
@RequestMapping("api/products")
@RestController
public class ProductController {
@Resource
private ProductService productService;
@RequestMapping(value = "{id:\\d+}", method = RequestMethod.GET)
public WebResult getOne(@PathVariable(name = "id") int id) {
final Optional<Product> productOpt = productService.queryById(id);
return productOpt.map(WebResult::new)
.orElseGet(() -> new WebResult(404, "product does not exists"));
}
}
PropertySourcesPlaceholderConfigurer
或PropertyPlaceholderConfigurer
。因为一个Spring上下文中只能有一个。所以最好配置在服务调用方(如:aics-server)使用Maven模拟微服务后,降低了项目中各模块间的耦合度;而且一般不同的功能模块主要是由一人负责,这样在开发过程中虽然在同一个git仓库,但也极少有代码冲突,提供了并发开发的效率。
PS: 这个方案是团队逐步摸索出来的,肯定存在很多的问题,欢迎各位大神批评指正,不胜感激!
如果对你有一点帮助,麻烦为我点一个赞,如果没有帮助,也非常期待你的反馈