排除Spring-data-rest资源的某些字段

18

我正在尝试使用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
}

它不起作用。 然而评论中说:https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring#comment-1725671983 答案建议使用@Projections。 但是@Projections的结果是像这样的url:“… / recommandations {?projection} ” 这意味着投影仅仅是一个选项,因此完整对象仍然会被暴露。

这里描述了另一种方法 https://github.com/spring-projects/spring-data-rest/wiki/Configuring-the-REST-URL-path 它建议为我们不想公开的字段使用@RestResource(exported=false)注释。

但是这种方法不够灵活。 如果我想公开只读API和私有完全访问API,则无法按API禁用此注释。

是否有其他建议?


1
你如何区分公共API和私有API?你是否为同一类别拥有两个存储库?那么两个类呢? - a better oliver
2个回答

23

重要的一点是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。最常见的用例是你有一个Customer对象与一个Address对象相关联。默认情况下,查看客户地址的关系会显示导航的URI。但如果你想一直获取地址信息,可以通过创建呈现地址详细信息的投影来避免此额外的GET操作。然后你可以为Customer对象配置它,将其默认打开,每当获取客户记录时就内联地址详细信息。

我意识到参考文档对所有这些细节还不是最新的。你可以跟踪我们更新文档的进度如下:

还有一个缺陷,即Spring Data REST的ALPS元数据也需要过滤掉标记为@JsonIgnore的领域字段(请参见https://jira.spring.io/browse/DATAREST-463)。

P.S. @RestResource已弃用,不建议使用它来设置导出哪些字段。而是像之前展示的那样使用@JsonIgnore


4
@JsonIgnore会完全从响应中删除字段。如何在响应中返回只读字段,但允许更新它们? - Stackee007
这是一个Jackson配置问题:有关详细信息,请参见此问题 - Oliver Drotbohm
4
如果我需要一个内部表示(允许显示和修改此字段)和一个公共只读表示,但不想在任何情况下显示此字段,那么 @JsonIgnore 将无法帮助我,对吗?它会将该字段从两种表示中都删除,是吗? - Hugo Lassiège
1
我有类似的需求,需要动态地隐藏或删除Spring Data Rest响应中的字段。不知道是否可以通过Jackson模块钩取@JsonFilter来处理某些实体,以便与Spring Data Rest一起使用。 - Gaurav Rawat
7
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)@JsonProperty(access = JsonProperty.Access.WRITE_ONLY) - sofend
@sofend,请考虑将您的建议作为这个问题的新答案,因为它是我对这个问题唯一有用(且非过时)的答案。我肯定会给它点赞 :-) - Johannes Rudolph

21

按照@johannes-rudolph的建议...

考虑将此设置应用于字段(如果您正在从访问器进行映射,则为属性):

@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)    
private String password;

这个访问值实现了其所暗示的功能:将相关字段标记为只写。因此,该值可以通过Jackson/JSON序列化的形式进行设置,但无法检索。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接