在本文章中通过一个案例来演示一下CompletableFuture的使用。
以一个商品查询为例,在微服务架构中,一个商品信息查询会涉及商品基本信息查询、商品评论查询、商品库存查询,每个查询都涉及不同的微服务的调用,如果使用异步编程的方式,应该如何实现呢?
当前演示的案例项目是采用Spring Boot构建的,其中涉及如下类。
GoodsService,商品基本信息服务
RepoService,商品库存信息服务
CommentService,商品评论信息服务。
GoodsController,Web 请求。
注意:为了尽量减少和本书中无关内容的引入,下面的代码简化了远程通信模块,直接采用
本地调用方式来模拟远程通信。
商品实例对象类Goods定义如下。
- @Getter
- @Data
- public class Goods {
- private Integer id;
- //商品名称
- private String name;
- //价格
- private BigDecimal price;
- //库存
- private Integer repo;
- //购买人数
- private Integer buyerNum;
- //评价
- private List
comment; - public Goods(Integer id, string name, BigDecimal price){
- this.id = id;
- this.name = name;
- this.price = price;
- }
- }
商品评价信息服务类CommentService定义如下。
- @Service
- public class CommentService {
- /**
- * 返回指定商品的评论
- * @return
- */
- public List
getCommentsByGoodsId(Integer goodsId) { - return Arrays.asList("好","一般","很好");
- }
- }
商品基本信息查询服务类GoodsService定义如下。
- @Service
- public class GoodsService {
-
- /**
- * 查询商品信息
- * @return
- */
- public List
queryGoods(){ - return Arrays.asList(
- new Goods(1,"电脑",newBigDecimal(5000)),
- new Goods(2,"手机",newBigDecimal(3000)),
- new Goods(3,"书",new BigDecimal(99)),
- new Goods(4,"杯子",newBigDecimal(18)));
- }
- }
商品库存查询服务类RepoService定义如下。
- @Service
- public class RepoService {
- /**
- * 查询指定商品库存
- * @param goodsId
- * @return
- */
- public Integer getRepoByGoodsId(Integer goodsId){
- return new Random( ) .nextInt(1000);
- }
- }
GoodsController类提供HTTP接口服务,用来访问商品详细信息,代码如下。
- @RestController
- public class GoodsController {
- @Autowired
- GoodsService goodsService;
- @Autowired
- CommentService commentService;
-
- @Autowired
- RepoService repoService;
- @GetMapping("/goods")
- public List
goods() throws ExecutionException, InterruptedException{ - CompletableFuture
>goodsFuture = CompletableFuture.supplyAsync(()->goodsService.queryGoods());
- CompletableFuture cf=goodsFuture.thenApplyAsync(goods->{
- goods.stream( ).map(good1->CompletableFuture.supplyAsync(()->{
- good1.setRepo(repoService.getRepoByGoodsId(good1.getId()));
- return good1;
- }).thenCompose(good2->CompletableFuture.supplyAsync(()->{
- good2.setComment(commentService.getCommentsByGoodsId(good2.getId()));
- return good2;
- }))).toArray(size->new CompletableFuture[size]);
- return goods;
- });
- return (List
) cf.handleAsync((goods,th)->th!=nul1?"系统繁忙":goods).get( ); - }
- }
其功能说明如下。
总的来说,了解了CompletionStage中不同类型的方法之后,就可以随心所欲地在实际业务场景中使用了,建议各位兄弟根据自己的实际业务场景来判断是否有必要使用,然后根据需求尝试合理地应用,从而更好地理解CompletableFuture。
兄弟们,先消化一下上面的内容吧,接下来的文章会带领我们了解一下CompletableFuture的实现原理,敬请期待^_^