自定义 Spring Data REST

Spring Data REST 提供了许多选项来定制。以下部分将展示如何进行定制。

定制项目资源 URI

默认情况下,项目资源的 URI 由用于集合资源的路径段加上数据库标识符组成。这使您可以使用存储库的 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 资源。包保护的存储库接口被排除在这个列表之外,因为您表达其功能仅对包内部可见。这可以通过在 RepositoryRestConfiguration 上显式设置 RepositoryDetectionStrategy(通常通过枚举 RepositoryDetectionStrategies)来定制。可以配置以下值

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

  • DEFAULT — 公开公共 Spring Data 存储库或显式用 @RepositoryRestResource 注释的存储库,并且其 exported 属性未设置为 false

  • VISIBILITY — 公开所有公共 Spring Data 存储库,无论注释配置如何。

  • ANNOTATED — 仅公开显式用 @RepositoryRestResource 注释的 Spring Data 存储库,并且其 exported 属性未设置为 false

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

自定义支持的 HTTP 方法

自定义默认暴露

默认情况下,Spring Data REST 会像在 存储库资源 中描述的那样公开 HTTP 资源和方法,这取决于存储库公开的 CRUD 方法。存储库不需要扩展 CrudRepository,但也可以选择性地声明上述部分中描述的方法,并且资源暴露将随之而来。例如,如果存储库没有公开 delete(…) 方法,则不会为项目资源支持 HTTP DELETE

如果您需要声明一个供内部使用的方法,但不想触发 HTTP 方法暴露,则可以使用 @RestResource(exported = false) 注解存储库方法。哪些方法需要这样注解以移除对哪些 HTTP 方法的支持,请参见 存储库资源 中的说明。

有时在方法级别管理暴露不够细粒度。例如,save(…) 方法用于支持集合资源上的 POST,以及项目资源上的 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 禁用对 HTTP PUT 的支持,以直接创建项目资源。
2 禁用对所有项目资源上的 HTTP PATCH 的支持。