Customizing Spring Data REST
有许多选项可以定制 Spring Data REST。以下小节显示了如何执行此操作。
There are many options to tailor Spring Data REST. These subsections show how.
Customizing Item Resource URIs
默认情况下,项目资源的 URI 由用于集合资源的路径段组成,后面附加数据库标识符。这使你可以使用存储库的 findOne(…)
方法来查找实体实例。从 Spring Data REST 2.5 开始,可以通过在 RepositoryRestConfiguration
上使用配置 API(首选在 Java 8 中使用)或通过在应用程序中将 EntityLookup
实现注册为 Spring Bean 来对其进行自定义。Spring Data REST 会挑选这些实现并根据它们的实现调整 URI 生成。
By default, the URI for item resources are comprised of the path segment used for the collection resource with the database identifier appended.
That lets you use the repository’s findOne(…)
method to lookup entity instances.
As of Spring Data REST 2.5, this can be customized by using configuration API on RepositoryRestConfiguration
(preferred on Java 8) or by registering an implementation of EntityLookup
as a Spring bean in your application.
Spring Data REST picks those up and tweaks the URI generation according to their implementation.
假设具有唯一标识它的 username
属性的 User
。进一步假设我们在对应的存储库上具有 Optional<User> findByUsername(String username)
方法。
Assume a User
with a username
property that uniquely identifies it.
Further assume that we have a Optional<User> findByUsername(String username)
method on the corresponding repository.
在 Java 8 中,我们可以将映射方法注册为方法引用以调整 URI 创建,如下所示:
On Java 8, we can register the mapping methods as method references to tweak the URI creation, as follows:
@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.withEntityLookup()
.forRepository(UserRepository.class)
.withIdMapping(User::getUsername)
.withLookup(UserRepository::findByUsername);
}
}
forRepository(…)
将存储库类型作为第一个参数,将存储库域类型映射到某些目标类型的引用作为第二个参数,并将另一个引用方法通过使用作为第一个参数提到的存储库进行映射。
forRepository(…)
takes the repository type as the first argument, a method reference mapping the repositories domain type to some target type as the second argument, and another method reference to map that value back by using the repository mentioned as the first argument.
如果你没有运行 Java 8 或更高版本,则可以使用该方法,但它需要一些非常详细的匿名内部类。在较旧的 Java 版本中,你可能应该更愿意实现一个类似以下内容的 UserEntityLookup
:
If you are not running Java 8 or better, you could use the method, but it would require a few quite verbose anonymous inner classes.
On older Java versions, you should probably prefer implementing a UserEntityLookup
that resembles the following:
@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(…)
。
Notice how getResourceIdentifier(…)
returns the username to be used by the URI creation. To load entity instances by the value returned from that method, we now implement lookupEntity(…)
by using the query method available on the UserRepository
.
Customizing repository exposure
默认情况下,所有公共 Spring Data 存储库均用于以 Repository resources 中所述方式公开 HTTP 资源。包受保护的存储库接口从该列表中排除,因为您表示其功能仅对内部包可见。通过明确设置 RepositoryDetectionStrategy
(通常通过枚举 RepositoryDetectionStrategies
)上的 RepositoryRestConfiguration
来自定义这一点。可以配置以下值:
By default, all public Spring Data repositories are used to expose HTTP resources as described in Repository resources.
Package protected repository interfaces are excluded from this list, as you express its functionality is only visible to the package internally.
This can be customized by explicitly setting a RepositoryDetectionStrategy
(usually through the enum RepositoryDetectionStrategies
) on RepositoryRestConfiguration
.
The following values can be configured:
-
ALL
— exposes all Spring Data repositories regardless of their Java visibility or annotation configuration. -
DEFAULT
— exposes public Spring Data repositories or ones explicitly annotated with@RepositoryRestResource
and itsexported
attribute not set tofalse
. -
VISIBILITY
— exposes only public Spring Data repositories regardless of annotation configuration. -
ANNOTATED
— only exposes Spring Data repositories explicitly annotated with@RepositoryRestResource
and itsexported
attribute not set tofalse
.
如果你需要应用自定义规则,只需手动实现 RepositoryDetectionStrategy
。
If you need custom rules to apply, simply implement RepositoryDetectionStrategy
manually.
Customizing supported HTTP methods
Customizing default exposure
默认情况下,Spring Data REST 会基于存储库公开的 CRUD 方法,公开 Repository resources 中所述的 HTTP 资源和方法。存储库不需要扩展 CrudRepository
,但也可以选择声明上述部分中描述的方法,资源公开也会随之出现。例如,如果存储库不公开 delete(…)
方法,则不支持项目资源的 HTTP DELETE
。
By default, Spring Data REST exposes HTTP resources and methods as described in Repository resources based on which CRUD methods the repository exposes.
The repositories don’t need to extend CrudRepository
but can also selectively declare methods described in aforementioned section and the resource exposure will follow.
E.g. if a repository does not expose a delete(…)
method, an HTTP DELETE
will not be supported for item resources.
如果您需要声明一个用于内部用途的方法,但不想触发 HTTP 方法公开,可以使用 @RestResource(exported = false)
注释存储库方法。根据 Repository resources 中的描述,要注释哪些方法以取消对哪个 HTTP 方法的支持。
If you need to declare a method for internal use but don’t want it to trigger the HTTP method exposure, the repository method can be annotated with @RestResource(exported = false)
.
Which methods to annotate like that to remove support for which HTTP method is described in Repository resources.
有时管理方法级别的公开不够细致。例如,save(…)
方法用于支持集合资源上的 POST
,以及项目资源上的 PUT
和 PATCH
。要选择性地定义应该公开哪些 HTTP 方法,可以使用 RepositoryRestConfiguration.getExposureConfiguration()
。
Sometimes managing the exposure on the method level is not fine-grained enough.
E.g. the save(…)
method is used to back POST
on collection resources, as well as PUT
and PATCH
on item resources.
To selectively define which HTTP methods are supposed to be exposed, you can use RepositoryRestConfiguration.getExposureConfiguration()
.
此类公开了一个基于 Lambda 的 API,用于定义全局规则和基于类型的规则:
The class exposes a Lambda based API to define both global and type-based rules:
ExposureConfiguration config = repositoryRestConfiguration.getExposureConfiguration();
config.forDomainType(User.class).disablePutForCreation(); 1
config.withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.PATCH)); 2
1 | Disables the support for HTTP PUT to create item resources directly. |
2 | Disables the support for HTTP PATCH on all item resources. |