自定义 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 — 无论其 Java 可见性或注释配置如何,都公开所有 Spring Data 资源库。

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

  • VISIBILITY — 仅公开公共 Spring Data 资源库,而不管注释配置如何。

  • ANNOTATED — 仅公开显式用 @RepositoryRestResource 注释且其 exported 属性未设置为 false 的 Spring Data 资源库。

如果您需要应用自定义规则,只需手动实现 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 的支持。