1

我已经开始实现一个 Web 前端来操作由Spring Data Rest传统关系数据库提供的 RESTful 服务。这是完成的,AngularJS并且我发现的库angular-hal非常适合.HATEOASSpring Data Rest

例如,我只需要知道第一个 API 端点('/'),然后我的所有查询都是通过关系完成的,而不关心 url。我遇到的问题是能够直接访问显示我的实体之一的页面。

让我们以联系人存储库为例。如果我从主页开始,然后浏览联系人列表,然后选择我想详细查看的联系人,没有问题。

但我无法直接访问显示联系人详细信息的页面:资源从列表控制器注入到编辑控制器,如果列表控制器未告知,编辑控制器无法知道要请求的 url。

根本问题是Spring Data Rest,实体没有公共字段id(不是 JSON),并且存储库没有 APIrelation可以通过 id 搜索。

我想了一些解决方案,但我不喜欢其中任何一个。

1. 在后端工作

  • 为所有需要添加书签的实体添加一个Projectionwith 方法getId()
  • findById()在仓库界面 添加对应
  • 使用前端 url 中的 id 作为参数(或路径)并通过调用新的可用搜索关系来解析资源。
  • 缺点:这迫使我们手动重做 Spring Data Rest 自动生成的所有 DTO,因此我们失去了框架的目的之一。
  • 问题:有没有办法将 Spring 配置为自动公开这些 id 字段和 findById 方法?

2.使用自我关系

  • angular-hal $href('self')使用方法获取实体的自身 URI
  • 将其用作页面的参数并通过halClient.$get(resourceUri)在其上调用 new 来解析资源
  • 缺点: uri 需要在页面 url 放入前后处理,以防止地址栏中的另一个“http://”导致错误。我想对它做一些base64编码,但这很消耗。
  • 缺点:这会将 API url 暴露给世界,并且这些数据可能很关键并且需要保持隐藏(即使这也可以通过调试器监视网络流量来访问)。

3.忘记HATEOAS

  • 不要为关系和发现能力而烦恼
  • 删除angular-hal并仅$resource与普通的旧 url 映射一起使用
  • 缺点:这是倒退,感觉就像没有遵循指导方针......

那么,我错过了什么吗?在完整的 RESTFul HATEOAS 环境中访问数据的最佳实践是什么?

4

1 回答 1

1

我找到了exposeIdsFor可以在 JSON 中添加带有 @Id 注释的字段的方法。

@Configuration
public class RepositoryConfiguration  extends SpringBootRepositoryRestMvcConfiguration {

    /**
     * add here the main resources that would need direct access from outside
     */
    @Override
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.exposeIdsFor(Contact.class, User.class);
    }
}

然后我让所有我希望 id 暴露的实体从一个公共抽象类继承

@MappedSuperclass
public abstract class AbstractEntity {

    @Id @GeneratedValue
    Long id;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

这个抽象类由@NoRepositoryBean存储库提供服务

@NoRepositoryBean
public interface AbstractEntityRepository<T extends AbstractEntity> extends JpaRepository<T, Long> {    
    @RestResource(rel = "byId")
    T findById(@Param("id") Long id);
}

然后我可以为我关心的实体公开 id 和方法 byId() :

@Entity
public class Contact extends AbstractEntity {

    @Column 
   String name;

    @Column 
    String email;
}

public interface ContactRepository extends AbstractEntityRepository<Contact> {    
}

我认为这是一个很好的解决方法,并允许以低廉的价格从客户端直接访问实体

于 2015-07-31T08:13:32.400 回答