Spring Data REST在不使用DTO的情况下通过REST资源公开实体是否有问题? [英] Is it problematic that Spring Data REST exposes entities via REST resources without using DTOs?

查看:140
本文介绍了Spring Data REST在不使用DTO的情况下通过REST资源公开实体是否有问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我有限的经验,我反复被告知您不应该将实体传递到前端或通过休息,而应该使用DTO.

In my limited experience, I've been told repeatedly that you should not pass around entities to the front end or via rest, but instead to use a DTO.

Spring Data Rest确实不这样做吗?我已经简要地研究了投影,但是这些投影似乎只是限制了返回的数据,并且仍然期望将实体作为post方法的参数保存到数据库中.我在这里错过了什么吗,还是我(和我的同事)不正确,因为您永远都不应绕过而成为实体?

Doesn't Spring Data Rest do exactly this? I've looked briefly into projections, but those seem to just limit the data that is being returned, and still expecting an entity as a parameter to a post method to save to the database. Am I missing something here, or am I (and my coworkers) incorrect in that you should never pass around and entity?

推荐答案

tl; dr

不. DTO只是使服务器端域模型与HTTP资源中公开的表示脱钩的一种方法.您还可以使用其他解耦方式,这就是Spring Data REST的作用.

tl;dr

No. DTOs are just one means to decouple the server side domain model from the representation exposed in HTTP resources. You can also use other means of decoupling, which is what Spring Data REST does.

是的,Spring Data REST检查您在服务器端拥有的域模型,以推断其公开的资源表示形式的方式.但是,它应用了两个关键概念来缓解域对象的幼稚暴露所带来的问题.

Yes, Spring Data REST inspects the domain model you have on the server side to reason about the way the representations for the resources it exposes will look like. However it applies a couple of crucial concepts that mitigate the problems a naive exposure of domain objects would bring.

天真的我将领域对象扔到杰克逊面前"的根本问题是,从普通实体模型来看,很难推理出合理的表示边界.特别是从数据库表派生的实体模型习惯于将几乎所有内容连接到所有内容.这源于这样一个事实,即在大多数持久性技术中根本不存在诸如聚合之类的重要领域概念(请阅读:尤其是在关系数据库中).

The fundamental problem with the naive "I throw my domain objects in front of Jackson" is that from the plain entity model, it's very hard to reason about reasonable representation boundaries. Especially entity models derived from database tables have the habit to connect virtually everything to everything. This stems from the fact that important domain concepts like aggregates are simply not present in most persistence technologies (read: especially in relational databases).

但是,我认为在这种情况下,不要暴露您的域模型"对问题的症状的作用远大于问题的核心.如果您正确地设计域模型,则域模型中的优势与通过状态更改有效驱动模型之间的良好表象之间存在巨大的重叠.一些简单的规则:

However, I'd argue that in this case the "Don't expose your domain model" is more acting on the symptoms of that than the core of the problem. If you design your domain model properly there's a huge overlap between what's beneficial in the domain model and what a good representation looks like to effectively drive that model through state changes. A couple of simple rules:

  • 对于与另一个实体的每种关系,请问自己:这难道不是一个id引用.通过使用对象引用,您可以将关系另一端的许多语义引入到您的实体中.弄错了通常会导致实体引用实体,而实体引用实体,这是一个更深层次的问题.在表示形式上,这使您可以切断数据,满足一致性范围等.
  • 避免双向关系,因为众所周知,它们很难在事物的更新方面得到解决.

Spring Data REST做了大量事情,实际上将那些实体关系转移到HTTP级别的适当机制中:一般的链接,更重要的是指向管理这些关系的专用资源的链接.这样做是通过检查为实体声明的存储库来完成的,并且基本上用关联资源的链接替换了关联实体的其他必要内联,该链接允许您显式管理该关系.

Spring Data REST does quite a few things to actually transfer those entity relationships into the proper mechanisms on the HTTP level: links in general and more importantly links to dedicated resources managing those relationships. It does so by inspecting the repositories declared for entities and basically replaces an otherwise necessary inlining of the related entity with a link to an association resource that allows you to manage that relationship explicitly.

该方法通常可以很好地与HTTP级别上DDD聚合描述的一致性保证一起使用. PUT请求默认情况下不会跨越多个聚合,这是一件好事,因为它暗示了与您的域概念相匹配的资源的一致性范围.

That approach usually plays nicely with the consistency guarantees described by DDD aggregates on the HTTP level. PUT requests don't span multiple aggregates by default, which is a good thing as it implies a scope of consistency of the resource matching the concepts of your domain.

您可以根据需要为域对象引入尽可能多的DTO.在大多数情况下,域对象中捕获的字段将以某种方式反映到表示中.我还没有看到包含firstnamelastnameemailAddress属性的实体Customer,以及与表示形式完全无关的实体.

You can introduce as many DTOs for your domain objects as you like. In most of the cases, the fields captured in the domain object will reflect into the representation in some way. I have yet to see the entity Customer containing a firstname, lastname and emailAddress property, and those being completely irrelevant in the representation.

DTO的引入绝对不能保证去耦.我已经看到太多的项目,这些项目是出于货运培训的原因而引入的,它们只是复制了支持它们的实体的所有字段,并且这引起了额外的努力,因为每个新字段也都必须添加到DTO中.但是,解耦!不是. ¯\ _(ツ)_/¯

The introduction of DTOs doesn't guarantee a decoupling by no means. I've seen way too many projects where they where introduced for cargo-culting reasons, simply duplicated all fields of the entity backing them and by that just caused additional effort because every new field had to be added to the DTOs as well. But hey, decoupling! Not. ¯\_(ツ)_/¯

也就是说,当然,在某些情况下,您可能希望略微调整这些属性的表示形式,尤其是在您使用强类型化值对象(例如)的情况下.一个EmailAddress(很好!),但仍要在JSON中将其呈现为普通的String.但这绝不是问题:Spring Data REST在幕后使用了Jackson,为您提供了各种各样的方法来调整表示形式-注释,将注释保留在域类型之外的混合,自定义序列化程序等.两者之间的映射层.

That said, there are of course situations where you'd want to slightly tweak the representation of those properties, especially if you use strongly typed value objects for e.g. an EmailAddress (good!) but still want to render this as a plain String in JSON. But by no means is that a problem: Spring Data REST uses Jackson under the covers which offers you a wide variety of means to tweak the representation — annotations, mixins to keep the annotations outside your domain types, custom serializers etc. So there is a mapping layer in between.

默认情况下不使用DTO本身并不是一件坏事.试想一下,如果我们要求为所有内容编写DTO,那么用户对所需样板数量的强烈抗议就可以了! DTO只是 one 的意思.如果可以用不同的方式(通常是可以)实现此目的,为什么要坚持使用DTO?

Not using DTOs by default is not a bad thing per se. Just imagine the outcry by users about the amount of boilerplate necessary if we required DTOs to be written for everything! A DTO is just one means to an end. If that end can be achieved in a different way (and it usually can), why insist on DTOs?

继续进行定制工作时,值得注意的是,Spring Data REST的存在恰好涵盖了API的各个部分,这些部分仅遵循其实现的基本REST API实现模式.而且该功能已经到位,使您有更多时间思考

Continuing on the customization efforts it's worth noticing that Spring Data REST exists to cover exactly the parts of the API, that just follow the basic REST API implementation patterns it implements. And that functionality is in place to give you more time to think about

  1. 如何塑造域模型
  2. 通过超媒体驱动的交互,可以更好地表达API的哪些部分.

这是我在SpringOne Platform 2016上的演讲的幻灯片,总结了情况.

Here's a slide from the talk I gave at SpringOne Platform 2016 that summarizes the situation.

可以在此处找到完整的幻灯片.在InfoQ上也有录音记录.

The complete slide deck can be found here. There's also a recording of the talk available on InfoQ.

存在Spring Data REST,您可以专注于带有下划线的圆圈.我们绝不认为仅通过打开Spring Data REST就可以构建出色的API.我们只想减少样板的数量,以便您有更多时间考虑有趣的部分.

Spring Data REST exists for you to be able to focus on the underlined circles. By no means we think you can build a great really API solely by switching Spring Data REST on. We just want to reduce the amount of boilerplate for you to have more time to think about the interesting bits.

就像一般的Spring Data一样,减少了要为标准持久性操作编写的样板代码的数量.没有人会说您实际上可以仅通过CRUD操作来构建真实世界的应用程序.但是,从无聊的工作中抽出精力,我们可以让您更深入地思考实际的领域挑战(并且您应该这样做:)).

Just like Spring Data in general reduces the amount of boilerplate code to be written for standard persistence operations. Nobody would argue you can actually build a real world app from only CRUD operations. But taking the effort out of the boring bits, we allow you to think more intensively about the real domain challenges (and you should actually do that :)).

您可以非常有选择性地覆盖某些资源,以完全控制它们的行为,包括根据需要手动将域类型映射到DTO.您还可以在Spring Data REST提供的功能旁边放置自定义功能,并将两者挂钩.对您的使用保持选择性.

You can be very selective in overriding certain resources to completely take control of their behavior, including manually mapping the domain types to DTOs if you want. You can also place custom functionality next to what Spring Data REST provides and just hook the two together. Be selective about what you use.

您可以找到我在 Spring RESTBucks (Spring( RESTful Web服务一书中基于RESTBucks示例的基于数据REST的实现.它使用Spring Data REST管理Order实例,但对其处理进行了调整,以引入自定义要求并完全手动实现故事的付款部分.

You can find a slightly advanced example of what I described in Spring RESTBucks, a Spring (Data REST) based implementation of the RESTBucks example in the RESTful Web Services book. It uses Spring Data REST to manage Order instances but tweaks its handling to introduce custom requirements and completely implement the payment part of the story manually.

这篇关于Spring Data REST在不使用DTO的情况下通过REST资源公开实体是否有问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆