自定义 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 的生成。
假设有一个具有唯一标识符 username 属性的 User。进一步假设我们相应的仓库中有一个 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注解且其exported属性未设置为false的 Spring Data 仓库。
如果您需要应用自定义规则,只需手动实现 RepositoryDetectionStrategy。
自定义支持的 HTTP 方法
自定义默认暴露
默认情况下,Spring Data REST 根据仓库暴露的 CRUD 方法暴露 仓库资源 中描述的 HTTP 资源和方法。仓库不需要扩展 CrudRepository,也可以选择性地声明上述部分中描述的方法,资源的暴露将随之进行。例如,如果一个仓库不暴露 delete(…) 方法,则项资源将不支持 HTTP DELETE。
如果您需要声明一个内部使用的方法,但又不想它触发 HTTP 方法的暴露,则可以将仓库方法标注为 @RestResource(exported = false)。关于如何标注哪些方法以取消对哪些 HTTP 方法的支持,请参阅 仓库资源。
有时在方法级别管理暴露不够精细。例如,save(…) 方法用于支持集合资源的 POST,以及项资源的 PUT 和 PATCH。要选择性地定义应该暴露哪些 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 的支持。 |