如何全局自定义Spring Data REST资源的集合资源rel和路径?

时间:2014-09-25 11:06:35

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

基于示例项目https://spring.io/guides/gs/accessing-data-rest/中的https://github.com/jcoig/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
  }
}

我不希望在网址中包含persons,并且我不希望persons作为返回的JSON中的密钥。当然,我可以按如下方式定义我的存储库:

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

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

2 个答案:

答案 0 :(得分:2)

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

@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>

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

答案 1 :(得分:1)

让我们确定我们首先想要实现的目标: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界面),以确保选择自定义提供商以支持已注册的默认提供商。