8.预测和摘要

Spring Data REST提出了一个您正在导出的域模型的默认视图,但是有时候,你需要因为各种各样的理由来更改这些模型的意见。在这个部分,你将会学习到如何 明确预测以及更加简单提供摘要以及减少对资源的一些意见。

8.1.Projections

看下面的域模型

@EntitypublicclassPerson{@Id@GeneratedValueprivateLong id;privateString firstName, lastName;@OneToOneprivateAddress address;…}

这个Person有以下这些属性

  • id是主键
  • firstNamelastName是数据属性
  • address是一个链接到另一个域的对象 现在假设我们创建了一个对应的存储,如下
interfacePersonRepositoryextendsCrudRepository<Person,Long>{}

在默认情况下,Spring Data REST 将会输出这个域对象包括里面所有的属性firstNamelastName 会被作为清楚的数据对象被输出。这里有两个选择关于这个address属性。一个选择也规定对于address对象的存储如下

interfaceAddressRepositoryextendsCrudRepository<Address,Long>{}

在这种情况下,Person的资源将会作为一个URI给予Address属性来对应他的Address资源,如果我们在这个系统里面要查找“Fordo”,我们可以希望看到的HAL文档如下

{"firstName":"Frodo","lastName":"Baggins","_links":{"self":{"href":"http://localhost:8080/persons/1"},"address":{"href":"http://localhost:8080/persons/1/address"}}}

这里有另一条路线,如果这个address域对象没有他本身的存储定义,Spring Data REST将会对内部的person资源内联数据字段。

{"firstName":"Frodo","lastName":"Baggins","address":{"street":"Bag End","state":"The Shire","country":"Middle Earth"},"_links":{"self":{"href":"http://localhost:8080/persons/1"}}}

但是如果你不想要address的所有细节?,再一次,在默认情况下,Spring Data REST将会输出这个的所有属性(除id),你可以为消费者提供你的可替代的REST服务通过定义一个或者多个预测方法

@Projection(name ="noAddresses", types ={Person.class})(1)interfaceNoAddresses{(2)String getFirstName();(3)String getLastName();(4)}

这个规划有以下的细节 | 1 | @Projection 注释标志是一个投影,name属性提供了投影名称,你将会见识到如何简单的利用。types属性目标这个投影只试用Person对象.| | --- | --- | | 2 |这是一个java接口使其陈述 | 3 |这输出firstname | 4 |这输出lastname

NoAddress项目里面只有firsnamelastname的getter方法,意味着它不会提供任何地址信息。假设你有一个单独的存储库地址资源,spring Data REST的默认视图有点不同,如下

{"firstName":"Frodo","lastName":"Baggins","_links":{"self":{"href":"http://localhost:8080/persons/1{?projection}",(1)"templated":true(2)},"address":{"href":"http://localhost:8080/persons/1/address"}}}
1 对于新的资源这里有一个新的选择清单{?projection}.
2 self URI是一个URI模板

视图应用投影到资源,查找[http://localhost:8080/persons/1?projection=noAddresses](http://localhost:8080/persons/1?projection=noAddresses).

提供给投影查询参数的值在Projection指定 @Projection(name = "noAddress").一样,这和投影的接口名称无关.

也可能可以有多个预测 | |您可以尝试访问预测看一个示例项目Projections | --- | --- | Spring Data REST如何找到投影的定义?

  • 任何@Projection接口在同一个包中发现作为实体定义(或它的子包)是已登记的
  • 您可以手动注册通过RepositoryRestConfiguration.getProjectionConfiguration().addProjection(…). 在这两种情况下,接口与投影一定要用@Projection注释。

    8.1.1.发现现有的投影

    Spring Data REST显示Application-Level Profile Semantics (ALPS) 文件,一个微元数据格式 。为了查看ALPS的元数据,按照配置文件profile 资源查找。如果你在Person资源下导航ALPS资源文档(这将是alps/persons),你将会发现一些person资源的细节。预测也会随着细节列出关于GET REST转换,如下
{…"id":"get-person",(1)"name":"person","type":"SAFE","rt":"#person-representation","descriptors":[{"name":"projection",(2)"doc":{"value":"The projection that shall be applied when rendering the response. Acceptable values available in nested descriptors.","format":"TEXT"},"type":"SEMANTIC","descriptors":[{"name":"noAddresses",(3)"type":"SEMANTIC","descriptors":[{"name":"firstName",(4)"type":"SEMANTIC"},{"name":"lastName",(4)"type":"SEMANTIC"}]}]}]},…
1 alps这部分文档显示关于getperson资源的细节.
2 进一步降低投影的选项.
3 进一步降低你可以看到的noaddress投影清单.
4 这个投影提供实际的属性包括firstNamelastName.
投影的定义会被采用并且为客户提供,如果他们是:
--- ---

8.1.2.引进隐藏数据

到目前为止,您已经看到了如何使用预测来减少信息呈现给用户。预测还可以引入通常看不见的数据。例如Spring Data REST将忽略数据字段或getter与@JsonIgnore标记注释,看看下面的域对象:

@EntitypublicclassUser{@Id@GeneratedValueprivateLong id;privateString name;@JsonIgnoreprivateString password;(1)privateString[] roles;…
1 Jackson 的 @JsonIgnore 用于防止密码字段序列化为JSON.

这个user类可用于存储用户信息以及集成Spring Security。如果您创建了一个UserRepository,密码字段通常已经输出。不是很好! 在这个例子中,我们运用jackson 的 @JsonIgnore预防这样的事情发生在 password 。 | |如果@JsonIgnore在领域对应getter函数那么jackson也没有序列化这个领域为json | --- | --- |

然而,预测引入仍为这一领域的能力。可以创建这样的一个投影:

@Projection(name ="passwords", types ={User.class})interfacePasswordProjection{String getPassword();}

如果创建和使用这样一个投影,它将@JsonIgnore指令放在User.password. | | 这个例子似乎有点做作,但有可能与更丰富的领域模型和许多预测.,不小心泄漏这样的细节.因为 Spring Data REST不能辨别这些数据的敏感性,它由开发人员来避免这种情况。 | --- | --- | 预测还可以生成虚拟数据。想象你有以下实体的定义:

@EntitypublicclassPerson{...privateString firstName;privateString lastName;...}

您可以创建一个投影相结合这两个数据字段一起像这样

@Projection(name ="virtual", types ={Person.class})publicinterfaceVirtualProjection{@Value("#{target.firstName} #{target.lastName}")(1)String getFullName();}

Spring的@ value注释让你插入一个SpEL 表达式来获取目标对象,和拼接在一起的FirstNameLastName属性为只读FullName。

8.2.摘要

摘录是一个投影,应用于资源自动收集。例如,你可以改变personrepository,如下:

@RepositoryRestResource(excerptProjection =NoAddresses.class)interfacePersonRepositoryextendsCrudRepository<Person,Long>{}

这指示Spring Data REST来用NoAddresses投影当Person的 资源嵌入到集合或相关资源中。

摘录的预测并不适用于单一资源自动,他们必须谨慎被使用,摘录的预测是为了提供一个默认的预览数据采集 但不是在获取个人资源。 See 为什么摘录投影不是Spring data rest自动申请的数据 for 作为一个讨论

除了改变缺省呈现,摘录了额外的渲染选项如下所示

8.3.摘录经常访问数据

与REST服务出现常见的情况,当你组成域对象。例如,Person都存储在一个表及其相关address存储在另一个地方默认情况下Spring Data REST 将会提供人的address作为URI客户机必须导航。如果消费者总是拿到这块数据的额外一部分,摘录投影可以继续进行以及内联这个额外的数据模块。 储存你一个额外的GET。为此,我们定义一个摘录投影:

@Projection(name ="inlineAddress", types ={Person.class})(1)interfaceInlineAddress{String getFirstName();String getLastName();Address getAddress();(2)}
1 这个被命名为inlineaddress投影.
2 这个返回address的投影添加进getAddress.当使用这个投影,这使得信息被内联.

我们能按照如下插入PersonRepository定义

@RepositoryRestResource(excerptProjection =InlineAddress.class)interfacePersonRepositoryextendsCrudRepository<Person,Long>{}

这将导致HAL文件出现如下

{"firstName":"Frodo","lastName":"Baggins","address":{(1)"street":"Bag End","state":"The Shire","country":"Middle Earth"},"_links":{"self":{"href":"http://localhost:8080/persons/1"},"address":{(2)"href":"http://localhost:8080/persons/1/address"}}}

这应该会出现在你所看到的东西的组合中

1 address数据是直接内联,所以你不必导航得到这个.
2 连接到Address资源依然被提供,使它仍然可以导航到自己的资源.
配置@RepositoryRestResource(excerptProjection=…​)为了一个库改变默认行为。如果你已经做了一个发布,这个能破坏改变消费者对你的服务。小心使用.

results matching ""

    No results matching ""