• CompletableFuture 实战


            在本文章中通过一个案例来演示一下CompletableFuture的使用。
            以一个商品查询为例,在微服务架构中,一个商品信息查询会涉及商品基本信息查询、商品评论查询、商品库存查询,每个查询都涉及不同的微服务的调用,如果使用异步编程的方式,应该如何实现呢?
            当前演示的案例项目是采用Spring Boot构建的,其中涉及如下类。

    •         Goods,商品实体对象。
    •         独立微服务:                    

                         GoodsService,商品基本信息服务

                         RepoService,商品库存信息服务

                         CommentService,商品评论信息服务。

             

            GoodsController,Web 请求。

    注意:为了尽量减少和本书中无关内容的引入,下面的代码简化了远程通信模块,直接采用
    本地调用方式来模拟远程通信。


    商品实体对象


    商品实例对象类Goods定义如下。

    1. @Getter
    2. @Data
    3. public class Goods {
    4. private Integer id;
    5. //商品名称
    6. private String name;
    7. //价格
    8. private BigDecimal price;
    9. //库存
    10. private Integer repo;
    11. //购买人数
    12. private Integer buyerNum;
    13. //评价
    14. private List comment;
    15. public Goods(Integer id, string name, BigDecimal price){
    16. this.id = id;
    17. this.name = name;
    18. this.price = price;
    19. }
    20. }

    模拟微服务请求实现类


    商品评价信息服务类CommentService定义如下。

    1. @Service
    2. public class CommentService {
    3. /**
    4. * 返回指定商品的评论
    5. * @return
    6. */
    7. public List getCommentsByGoodsId(Integer goodsId) {
    8. return Arrays.asList("好","一般","很好");
    9. }
    10. }

    商品基本信息查询服务类GoodsService定义如下。
     

    1. @Service
    2. public class GoodsService {
    3. /**
    4. * 查询商品信息
    5. * @return
    6. */
    7. public List queryGoods(){
    8. return Arrays.asList(
    9. new Goods(1,"电脑",newBigDecimal(5000)),
    10. new Goods(2,"手机",newBigDecimal(3000)),
    11. new Goods(3,"书",new BigDecimal(99)),
    12. new Goods(4,"杯子",newBigDecimal(18)));
    13. }
    14. }


        商品库存查询服务类RepoService定义如下。

    1. @Service
    2. public class RepoService {
    3. /**
    4. * 查询指定商品库存
    5. * @param goodsId
    6. * @return
    7. */
    8. public Integer getRepoByGoodsId(Integer goodsId){
    9. return new Random( ) .nextInt(1000);
    10. }
    11. }

    Web请求


            GoodsController类提供HTTP接口服务,用来访问商品详细信息,代码如下。

    1. @RestController
    2. public class GoodsController {
    3. @Autowired
    4. GoodsService goodsService;
    5. @Autowired
    6. CommentService commentService;
    7. @Autowired
    8. RepoService repoService;
    9. @GetMapping("/goods")
    10. public List goods() throws ExecutionException, InterruptedException{
    11. CompletableFuture>goodsFuture = CompletableFuture.supplyAsync(()->goodsService.queryGoods());
    12. CompletableFuture cf=goodsFuture.thenApplyAsync(goods->{
    13. goods.stream( ).map(good1->CompletableFuture.supplyAsync(()->{
    14. good1.setRepo(repoService.getRepoByGoodsId(good1.getId()));
    15. return good1;
    16. }).thenCompose(good2->CompletableFuture.supplyAsync(()->{
    17. good2.setComment(commentService.getCommentsByGoodsId(good2.getId()));
    18. return good2;
    19. }))).toArray(size->new CompletableFuture[size]);
    20. return goods;
    21. });
    22. return (List) cf.handleAsync((goods,th)->th!=nul1?"系统繁忙":goods).get( );
    23. }
    24. }

    其功能说明如下。

    • 使用supplyAsync()方法来构建一个CompletableFuture任务,这个任务负责查询所有商品的基本信息。
    • 接着通过thenApplyAsyne()方法来连接另外一个任务,也就是当第一个查询商品基本信息的 CompletinStage任务执行结束后,通过异步线程执行第二个任务。
    • 在第二个任务中,使用了thenCompose()方法来组合两个CompletionStage任务,完成商品评论和商品库存信息的补充。
    • 最终采用handleAsync()方法返回执行结果,这里用handleAsyncO方法的目的是避免将前置任务的异常直接抛给前端。

            总的来说,了解了CompletionStage中不同类型的方法之后,就可以随心所欲地在实际业务场景中使用了,建议各位兄弟根据自己的实际业务场景来判断是否有必要使用,然后根据需求尝试合理地应用,从而更好地理解CompletableFuture。


            兄弟们,先消化一下上面的内容吧,接下来的文章会带领我们了解一下CompletableFuture的实现原理,敬请期待^_^

  • 相关阅读:
    【校招VIP】[前端][一本][6分]项目需要考虑到PC端和移动端
    JAVA--企业级分层开发模式
    数据分析与可视化概述
    SpringMvc 源码分析 (如何自定义视图 + 如何自定义异常) (十四)
    indiegogo海外众筹是品牌冷启动最好方式之一?
    nltk报错punkt 缺失 Error Loading Error11004
    商业智能中的决策, 数据和数据处理方法
    基于idea的YonBuilder Premium开发者工具(原NCC开发插件)使用说明
    微调Qwen2大语言模型加入领域知识
    oracle 打补丁
  • 原文地址:https://blog.csdn.net/wm31898/article/details/134066538