定制 Spring Data REST

Spring Data REST 有许多定制选项。以下小节展示了如何进行定制。

定制 Item Resource URI

默认情况下,Item Resources 的 URI 由 Collection Resource 使用的路径段附加数据库标识符构成。这允许您使用存储库的 findOne(…) 方法查找实体实例。从 Spring Data REST 2.5 版本开始,您可以通过 RepositoryRestConfiguration 上的配置 API(推荐在 Java 8 上使用)或注册 EntityLookup 的实现作为 Spring Bean 来定制这一点。Spring Data REST 会拾取这些实现并根据其实现调整 URI 生成。

假设有一个 User 实体,其 username 属性唯一标识它。进一步假设相应的存储库上有一个 Optional<User> findByUsername(String username) 方法。

在 Java 8 上,我们可以将映射方法注册为方法引用来调整 URI 的创建,如下所示:

@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {

  @Override
  public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
    config.withEntityLookup()
      .forRepository(UserRepository.class)
      .withIdMapping(User::getUsername)
      .withLookup(UserRepository::findByUsername);
  }
}

forRepository(…) 方法接受存储库类型作为第一个参数,一个将存储库的领域类型映射到目标类型的方法引用作为第二个参数,以及另一个使用第一个参数提到的存储库将该值映射回的方法引用。

如果您没有运行 Java 8 或更高版本,您可以使用该方法,但这需要一些相当冗长的匿名内部类。在较旧的 Java 版本上,您应该可能优先实现一个类似于以下内容的 UserEntityLookup

@Component
public class UserEntityLookup extends EntityLookupSupport<User> {

    private final UserRepository repository;

    public UserEntityLookup(UserRepository repository) {
        this.repository = repository;
    }

    @Override
    public Serializable getResourceIdentifier(User entity) {
        return entity.getUsername();
    }

    @Override
    public Object lookupEntity(Serializable id) {
        return repository.findByUsername(id.toString());
    }
}

请注意 getResourceIdentifier(…) 如何返回用于 URI 创建的用户名。为了通过该方法返回的值加载实体实例,我们现在通过使用 UserRepository 上可用的查询方法来实现 lookupEntity(…)

定制存储库暴露

默认情况下,所有公共 Spring Data 存储库都用于暴露 HTTP 资源,如存储库资源中所述。Package Protected 存储库接口被排除在此列表之外,因为您表示其功能仅在包内部可见。这可以通过在 RepositoryRestConfiguration 上显式设置 RepositoryDetectionStrategy(通常通过枚举 RepositoryDetectionStrategies)来定制。可以配置以下值:

  • ALL — 暴露所有 Spring Data 存储库,无论其 Java 可见性或注解配置如何。

  • DEFAULT — 暴露公共 Spring Data 存储库或那些显式使用 @RepositoryRestResource 注解且其 exported 属性未设置为 false 的存储库。

  • VISIBILITY — 仅暴露公共 Spring Data 存储库,无论注解配置如何。

  • ANNOTATED — 仅暴露显式使用 @RepositoryRestResource 注解且其 exported 属性未设置为 false 的 Spring Data 存储库。

如果您需要应用自定义规则,只需手动实现 RepositoryDetectionStrategy 即可。

定制支持的 HTTP 方法

定制默认暴露

默认情况下,Spring Data REST 根据存储库暴露的 CRUD 方法,暴露 HTTP 资源和方法,如存储库资源中所述。存储库不需要扩展 CrudRepository,也可以选择性地声明前述部分中描述的方法,资源暴露将随之改变。例如,如果存储库未暴露 delete(…) 方法,则 Item Resource 将不支持 HTTP DELETE

如果您需要声明一个用于内部使用的方法,但不想让它触发 HTTP 方法暴露,则可以通过 @RestResource(exported = false) 注解该存储库方法。关于哪些方法应该如何注解以移除对哪些 HTTP 方法的支持,请参阅存储库资源

有时,在方法级别管理暴露不够细粒度。例如,save(…) 方法用于支持 Collection Resource 上的 POST,以及 Item Resource 上的 PUTPATCH。要选择性地定义应该暴露哪些 HTTP 方法,您可以使用 RepositoryRestConfiguration.getExposureConfiguration()

该类暴露了一个基于 Lambda 的 API,用于定义全局和基于类型的规则:

ExposureConfiguration config = repositoryRestConfiguration.getExposureConfiguration();

config.forDomainType(User.class).disablePutForCreation(); (1)
config.withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.PATCH)); (2)
1 禁用直接创建 Item Resource 的 HTTP PUT 支持。
2 禁用所有 Item Resource 的 HTTP PATCH 支持。