徐昊 · TDD 项目实战 70 讲
徐昊
Thoughtworks 中国区 CTO
18159 人已学习
新⼈⾸单¥98
登录后,你可以任选4讲全文学习
课程目录
已完结/共 88 讲
实战项目二|RESTful开发框架:依赖注入容器 (24讲)
实战项目三|RESTful Web Services (44讲)
徐昊 · TDD 项目实战 70 讲
15
15
1.0x
00:00/00:00
登录|注册

36|实战中的TDD:RESTful Web Services

你好,我是徐昊。通过前面的项目练习,我们完成了 DI Container 的功能。从这节课开始,我们就进入 RESTful Web Services 的开发。

整体功能介绍

在 DI Container 的部分,我们参考了 Jakarta Dependency Injection 作为功能依据。在 RESTful Web Services 部分,我们将会参考 Jakarta RESTful Web Services。
Jakarta RESTful Web Services 的功能比 Jakarta Dependency Injection 要庞杂一些,如视频中所演示的,我将从三个部分来讲解说明:
00:00 / 00:00
    1.0x
    • 2.0x
    • 1.5x
    • 1.25x
    • 1.0x
    • 0.75x
    • 0.5x
    网页全屏
    全屏
    00:00
    经过多年发展,Jakarta RESTful Web Services 也变得日渐复杂,其中有些“高级”特性很少应用,在我们的项目中需要做一些取舍:
    00:00 / 00:00
      1.0x
      • 2.0x
      • 1.5x
      • 1.25x
      • 1.0x
      • 0.75x
      • 0.5x
      网页全屏
      全屏
      00:00
      那么下面这段代码展示了我们需要实现的主要功能,并提供了相应的扩展能力:
      public class UserOrdersResource {
      private User user;
      @Context
      private Orders orders;
      @Context
      private Products products;
      public UserOrdersResource(User user) {
      this.user = user;
      }
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public CollectionModel<Order> all() {
      return CollectionModel.of(orders.findBy(user.getId()))
      .add(Link.of("/users/{id}/orders").expand(user.getId().value()),
      Link.of("/users/{id}", "owner").expand(user.getId().value()));
      }
      @GET
      @Path("/{id}")
      @Produces(MediaType.APPLICATION_JSON)
      public EntityModel<Order> findBy(@PathParam("id") long id) {
      return orders.findBy(user.getId(), new Order.Id(id))
      .map(o -> EntityModel.of(o)
      .add(Link.of("/users/{id}/orders/{id}").expand(user.getId().value(), id),
      Link.of("/users/{id}", "owner").expand(user.getId().value())))
      .orElse(null);
      }
      @POST
      @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
      public Response placeOrder(@FormParam("item") List<Long> items, @FormParam("quantity") List<Double> quantities) {
      List<Product> products = this.products.find(items.stream().map(Product.Id::new).toList());
      Map<Product, Double> orderItems = new HashMap<>();
      for (int i = 0; i < products.size(); i++)
      orderItems.put(products.get(i), quantities.get(i));
      Order order = orders.create(user, orderItems);
      return Response.created(Link.of("/users/{uid}/orders/{oid}").expand(user.getId().value(), order.getId().value()).toUri()).build();
      }
      }
      public class UserResource {
      private User user;
      public UserResource(User user) {
      this.user = user;
      }
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public EntityModel<User> get() {
      return EntityModel.of(user).add(Link.of("/users/{value}").expand(user.getId().value()));
      }
      @Path("/orders")
      public UserOrdersResource orders(@Context ResourceContext context) {
      return context.initResource(new UserOrdersResource(user));
      }
      }
      @Path("/users")
      public class UsersResource {
      @Context
      private Users users;
      @Path("{id}")
      public UserResource findById(@PathParam("id") User.Id id) {
      return users.findById(id).map(UserResource::new).orElse(null);
      }
      @POST
      @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
      public Response register(@FormParam("name") String name, @FormParam("email") String email) {
      User user = users.create(name, email);
      return Response.created(Link.of("/users/{id}").expand(user.getId().value()).toUri()).build();
      }
      }
      我们很容易可以发现,RESTful Web Services 需要多模块协同完成。而不是像 DI Container 那样,可以从单一模块入手,完成几个功能之后再进行重构。所以对于 RESTful Web Services,伦敦学派或许是一种更好的方式。
      确认放弃笔记?
      放弃后所记笔记将不保留。
      新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
      批量公开的笔记不会为你同步至部落
      公开
      同步至部落
      取消
      完成
      0/2000
      荧光笔
      直线
      曲线
      笔记
      复制
      AI
      • 深入了解
      • 翻译
        • 英语
        • 中文简体
        • 中文繁体
        • 法语
        • 德语
        • 日语
        • 韩语
        • 俄语
        • 西班牙语
        • 阿拉伯语
      • 解释
      • 总结

      徐昊在本文中介绍了在实战中使用TDD开发RESTful Web Services的过程。他首先介绍了整体功能,并指出RESTful Web Services相较于DI Container更为复杂,需要多模块协同完成,因此伦敦学派可能是更好的方式。接着,他展示了需要实现的主要功能,并提供了相应的扩展能力。文章中的代码示例清晰地展示了RESTful Web Services的开发过程,包括UserOrdersResource、UserResource和UsersResource等类的实现。最后,徐昊提出了一个思考题,邀请读者分享他们对于架构愿景的想法和项目代码。通过本文,读者可以快速了解TDD在RESTful Web Services开发中的应用,以及对于伦敦学派的思考。

      仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
      《徐昊 · TDD 项目实战 70 讲》
      新⼈⾸单¥98
      立即购买
      登录 后留言

      全部留言(1)

      • 最新
      • 精选
      • Flynn
        老师,科普一下什么是RESTful呗

        编辑回复: 指路《如何落地业务建模》里的10、11节,讲RESTful的

        2022-06-06
      收起评论
      显示
      设置
      留言
      1
      收藏
      沉浸
      阅读
      分享
      手机端
      快捷键
      回顶部