排除 Spring-data-rest 资源的部分字段
Posted
技术标签:
【中文标题】排除 Spring-data-rest 资源的部分字段【英文标题】:Exclude some fields of Spring-data-rest resource 【发布时间】:2015-04-04 00:48:45 【问题描述】:我正在尝试将 Spring-data-rest 与 spring-data-mongodb 一起使用来公开只读资源。
我遇到的问题是我想对我的文档有不同的看法。 假设我在文档中有一些私人信息,我不想公开它们。
所以我尝试了几种方法。 我读了这篇 https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring 的帖子,描述了如何使用 JsonView 来选择我们想要公开的字段。
我试过这样:
@RepositoryRestResource(collectionResourceRel = "recommandation", path = "recommandations")
interface RecommandationRepository extends MongoRepository<Recommendation, ObjectId>
@Override
@JsonView(View.Public.class)
Iterable<Recommendation> findAll(Iterable<ObjectId> objectIds);
... // other find methods
它不起作用。然而,在 cmets 中说:https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring#comment-1725671983 答案建议使用@Projections 但是@Projections 会产生这样的网址:“…/recommandations?projection” 这意味着投影只是一个选项,因此仍然会暴露整个对象。
这里描述了另一种方法https://github.com/spring-projects/spring-data-rest/wiki/Configuring-the-REST-URL-path 它建议对我们不想公开的字段使用 @RestResource(exported = false) 注释。
但它不灵活。如果我想公开一个公共的只读 API 和一个私有的完全访问 API。不能按 api 禁用此注解。
还有其他建议吗?
【问题讨论】:
如何区分公共 API 和私有 API?同一个类有两个存储库吗?那么两节课怎么样? 【参考方案1】:重要的一点是 Spring Data REST 使用基于域对象的 Jackson 序列化参数,而不是存储库定义。隐藏特定字段以免出现在 JSON 中的一种简单方法如下:
@Entity
public class User
@Id @GeneratedValue
private Long id;
private String name;
@JsonIgnore
private String password;
...
在此示例中,无论如何使用此实体,我的用户对象都不会导出密码字段。 Jackson 支持将这个放在场上,或者放在相应的 getter 方法上。
当您将 @JsonIgnore 放入域模型中时,它会使其成为默认定义。投影是更改渲染哪些字段的选项。看下面的例子:
@Projection(name = "noImages", types = Item.class)
public interface NoImages
public Link gethtmlUrl();
这个项目只能在渲染 Item 域对象时使用。它不是默认视图,而是通过 ?projection=noImages 使用的选项。但不要忘记:当应用 Jackson 序列化时,项目将覆盖领域模型的设置。这意味着您可以为上面的 User 对象编写一个投影,并让它包含 String getPassword()。这将覆盖域模型的默认设置,进而导出密码。责任在你。
最后一件事。 Spring Data REST 支持 Excerpt Projections。最常见的用例是您有一个与 Address 对象相关的 Customer 对象。默认情况下,查看客户地址的关系将显示要导航的 URI。但是,如果您一直想要地址信息,您可以通过创建一个呈现地址详细信息的投影来避免这种额外的 GET 操作。然后您可以为 Customer 对象配置它,默认打开此投影,并在您获取客户记录时基本上内联地址详细信息。
我意识到参考文档在所有这些细节上都不是最新的。您可以跟踪我们的进度以适当地更新文档,如下所示:
https://jira.spring.io/browse/DATAREST-449 https://jira.spring.io/browse/DATAREST-450 https://jira.spring.io/browse/DATAREST-451 https://jira.spring.io/browse/DATAREST-452 https://jira.spring.io/browse/DATAREST-453 https://jira.spring.io/browse/DATAREST-454还有一个错误,即来自 Spring Data REST 的 ALPS 元数据还需要过滤掉带有 @JsonIgnore 标记的域字段(参见 https://jira.spring.io/browse/DATAREST-463)
附: @RestResource 已弃用,并且不是设置导出哪些字段的推荐方法。相反,请使用 @JsonIgnore,如前所示。
【讨论】:
@JsonIgnore
从响应中完全删除字段。如何返回只读字段作为响应,但只是让它们更新?
这是一个 Jackson 配置问题:有关详细信息,请参阅 this question。
如果我需要一个内部表示(允许显示和修改这个字段)和一个根本不想显示这个字段的公共只读表示,@JsonIgnore 不会帮助我对?它将删除两种表示的字段,不?
我有类似的要求来动态隐藏弹簧数据休息响应中的删除字段。想知道我们是否可以通过 Jackson 模块为某些实体挂钩 @jsonfilter 以使用 spring 数据休息
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)【参考方案2】:
根据@johannes-rudolph 的建议...
考虑将此设置应用于字段(或属性,如果您从访问器进行映射):
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
这就是访问值所暗示的:将关联的字段标记为只写。因此该值可以设置,但不能通过 Jackson/JSON 序列化形式检索。
【讨论】:
以上是关于排除 Spring-data-rest 资源的部分字段的主要内容,如果未能解决你的问题,请参考以下文章
是否有适用于 JPA、spring-data、spring-data-rest 的通用 REST 查询语言
如何配置 Spring-Data-Rest 以仅返回登录用户拥有的数据