简体   繁体   中英

How to globally customize the collection resource rel and path for Spring Data REST resources?

Basing on https://spring.io/guides/gs/accessing-data-rest/ in the sample project https://github.com/jcoig/gs-accessing-data-rest ) i have repository defined as follows:

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

Such defined repository is available via http://localhost:8080/persons and the response is:

{
  "_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
  }
}

I don't want to have persons in the URL and I don't want to have persons as the key in the returned JSON. Of Course I can define my repository as below:

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

but my question is how to change default Spring's behavior and got custom key and custom path provider ( just as example to disable s suffixes).

If the solution applying @Order(value = Ordered.HIGHEST_PRECEDENCE) on the customized RelProvider instance is not working the following workaround may help:

@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());
}
}

Further I had to exclude evo-inflector from the classpath:

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

Not really a nice solution, but it works for my setup.

Let's make sure what we're trying to achieve in the first place: Spring Data REST exposes two kinds of primary resources: collection resources and item resources. To be able to differentiate between the two we need two different relation names. So by default Spring Data REST uses the uncapitalized domain class name for the item resource rel and the Evo Inflector library to pluralize the item resource rel and use that as collection relation name (effectively what you informally described as adding the s suffix).

If you manually exclude the Evo Inflector library, Spring Data REST falls back to ${itemRel}List for the collection relation, which first of all is more clunky than using properly pluralized names.

As you also discovered already, you can manually configure the names to be used for each repository. However, it's a very bad idea to configure the collection resource rel to be the item resource rel as this will prevent the clients from differentiating between the two resource types.

Assuming you've got this far reading and still want to deploy a custom strategy to globally alter the relation names for types you can implement a RelProvider (see EvoInflectorRelProvider or DefaultRelProvider for implementation examples). If you register that implementation as Spring bean.

@Configuration
class MyConfig {

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

You might wanna experiment with the order (see @Order or the Ordered interface) of the implementation to make sure your custom provider is chosen in favor of the default ones registered.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM