【问题标题】:How to globally customize the collection resource rel and path for Spring Data REST resources?Spring Data REST资源如何全局自定义集合资源rel和path?
【发布时间】:2014-09-25 11:06:35
【问题描述】:

基于示例项目https://github.com/jcoig/gs-accessing-data-rest 中的https://spring.io/guides/gs/accessing-data-rest/)我的存储库定义如下:

@RepositoryRestResource
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
    List<Person> findByLastName(@Param("name") String name);
}

此类定义的存储库可通过http://localhost:8080/persons 获得,响应为:

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/persons{?page,size,sort}",
      "templated" : true
    },
    "search" : {
      "href" : "http://localhost:8080/persons/search"
    }
  },
  "_embedded" : {
    "persons" : [ {
      "firstName" : "John",
      "lastName" : "Smith",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/persons/1"
        }
      }
    } ]
  },
  "page" : {
    "size" : 20,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

我不想在 URL 中包含 persons,也不想在返回的 JSON 中包含 persons 作为键。当然,我可以将我的存储库定义如下:

@RepositoryRestResource(collectionResourceRel = "key", path = "path")
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
    List<Person> findByLastName(@Param("name") String name);
}

但我的问题是如何更改默认 Spring 的行为并获得自定义键和自定义路径提供程序(仅作为示例禁用 s 后缀)。

【问题讨论】:

    标签: spring rest spring-data-rest hateoas spring-hateoas


    【解决方案1】:

    如果在自定义 RelProvider 实例上应用 @Order(value = Ordered.HIGHEST_PRECEDENCE) 的解决方案不起作用,则以下解决方法可能会有所帮助:

    @Configuration
    @Import(RepositoryRestMvcConfiguration.class)
    public class RestMvcConfigurer extends RepositoryRestMvcConfiguration
    {
    ...
    @Override
    public ResourceMappings resourceMappings()
    {
    
      final Repositories repositories = repositories();
      final RepositoryRestConfiguration config = config();
      return new RepositoryResourceMappings( config, repositories, new YourCustomRelProvider());
    }
    }
    

    我还必须从类路径中排除 evo-inflector

    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.atteo</groupId>
                    <artifactId>evo-inflector</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    

    不是一个很好的解决方案,但它适用于我的设置。

    【讨论】:

    • 感谢多米尼克的回复!有用!现在我将ccc 作为响应 JSON 中的一个键,http://localhost:8080/person{?page,size,sort} 在“href”中。剩下的问题是如何在不使用 @RepositoryRestResource 注释中的“路径”参数的情况下更改此路径。
    • 我不确定您所说的更改路径是什么意思。如果引用基本 URI,则可以覆盖 RestMvcConfigurer 中的 protected void configureRepositoryRestConfiguration( final RepositoryRestConfiguration config ) 方法。其中调用config.setBaseUri("mybaseuri")
    • 返回的 JSON 在两个不同的地方包含单词“persons”:作为 _embedded 下的键和几个 href。我想更改这些 href 中的路径,而不在 @RepositoryRestResource 注释中指定 path = "path"
    【解决方案2】:

    让我们首先确定我们想要实现的目标:Spring Data REST 公开了两种主要资源:集合资源和项目资源。为了能够区分两者,我们需要两个不同的关系名称。因此,默认情况下,Spring Data REST 使用项目资源 rel 的非大写域类名称和 Evo Inflector 库来复数项目资源 rel 并将其用作集合关系名称(实际上您非正式地描述为添加 s 后缀)。

    如果您手动排除 Evo Inflector 库,Spring Data REST 将回退到 ${itemRel}List 的集合关系,首先这比使用正确的复数名称更笨拙。

    正如您已经发现的那样,您可以手动配置要用于每个存储库的名称。 但是,将集合资源 rel 配置为项目资源 rel 是一个非常糟糕的主意,因为这会阻止客户端区分两种资源类型。

    假设您已经阅读了这么多,并且仍然希望部署自定义策略来全局更改类型的关系名称,您可以实现 RelProvider(有关实现示例,请参见 EvoInflectorRelProviderDefaultRelProvider)。如果您将该实现注册为 Spring bean。

    @Configuration
    class MyConfig {
    
      @Bean
      YourCustomRelProvider customRelProvider() {
        return new YourCustomRelProvider(…);
      }
    }
    

    您可能想试验一下实现的顺序(参见@OrderOrdered 接口),以确保选择您的自定义提供程序以支持注册的默认提供程序。

    【讨论】:

    • 感谢您的回复!不幸的是,我仍然无法得到我想要的……在来自 spring.io/guides/gs/accessing-data-rest> 的项目中(没有 collectionResourceRelpath)我添加了一个实现 RelProvider 的类,带有注释 ComponentOrder(value = Ordered.HIGHEST_PRECEDENCE) 和三个被覆盖方法:getItemResourceRelFor(返回"iii")、getCollectionResourceRelFor(返回"ccc")和supports(返回true)。在 Application.java 中,我添加了 bean,就像在您的回答中一样……我仍然在 JSON 的密钥和 URL 中得到 persons。我做错了什么?
    • 这就是我们让事情顺利进行的方式,而且似乎奏效了。这样做是为了让所有页面都有项目,因此页面界面被规范化。你能确认你的组件被注册为 bean 吗? (确保您的支持方法被调用)配置中的组件注释和 bean 方法是多余的......但应该仍然有效。我们不需要做 Order 注释。我们的也是弹簧靴
    • 克里斯,请看这个项目:github.com/jcoig/gs-accessing-data-rest。它基于 spring.io/guides/gs/accessing-data-rest,并根据 Oliver 的提示(或我所理解的)进行了更改。
    • 确实,它不能按原样工作,我已经做了一个回答,向您展示我是如何让它工作的。有些东西我不明白..像 RepositoryRelProvider 有这个注释 @Order(Ordered.LOWEST_PRECEDENCE + 10) .. LOWEST_PRECEDENCE 是 Integer.MAX_VALUE ..所以它取决于溢出吗?这看起来真的很奇怪!
    • 最奇怪的事情..我为您的项目下载了源代码和文档...它刚刚开始工作我现在看到 rel 提供者正在介入并且出现的关系是 ccc!?不知道为什么它开始工作......我没有改变任何代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 2018-07-30
    • 1970-01-01
    • 2015-08-30
    相关资源
    最近更新 更多