【问题标题】:Given a Spring Data Rest URI, How Do you find the associated target repository?给定一个 Spring Data Rest URI,你如何找到关联的目标存储库?
【发布时间】:2019-09-19 19:50:16
【问题描述】:

我正在使用 Spring Data REST 构建一个应用程序,并使用 MappedInterceptor 实现拦截器模式,正如 post 中所建议的那样。拦截器按预期工作,它拦截@RestControllers

现在,使用preHandle(…) 方法签名中可用的参数(包括:HttpServletRequest request, HttpServletResponse response, Object handler => can be casted to org.springframework.web.method.HandlerMethod),我如何访问正在调用的 RestRepository 类或存储库方法(来自 HandlerMethod 类的 getMethod() 效果很好使用具体类,但它不适用于 Repository 接口,它结束返回一个 RestAbstractController 类,该类通过反射调用目标存储库)???

为什么我需要这个?

因为,我在做一个横切的逻辑,需要访问Repository接口来查找特定的业务注解,如果注解存在,就完成了一些逻辑(比如设置MDC特殊值) ...

谢谢...

【问题讨论】:

  • 您能否提供代码示例,说明您尝试过但没有成功的方法?
  • 我相信代码在这里没有帮助......正如我所说,使用来自org.springframework.web.method.HandlerMethodgetMethod() 我可以获得对具体类的引用,然后我可以从那里查找我的通过反射进行注释...这种方法仅适用于我自己实现的具体类...但是,Spring JPA Rest Repositories 由 Spring 提供的具体类调用,因此目标存储库被此类包装,我不知道如何访问它们...

标签: java spring spring-data-jpa spring-data spring-data-rest


【解决方案1】:

一般查找和使用 Spring Data 存储库的最灵活方法是通过 RepositoriesRepositoryInvoker 抽象。 前者提供了按类型查找关于存储库和存储库本身的元数据的能力。后者允许在这些存储库上通用调用 CRUD 和查询方法。这种额外的抽象是必要的,因为 Spring Data 存储库不必实现特殊接口,只要它们公开在语法上与 Spring Data 的CrudRepository 中提供的方法等效的方法。

一般方式

如果您知道您尝试访问存储库的实际域类,则可以将Repositories 的实例注入到您的类中。这反过来又允许您查找实体和存储库信息以及存储库本身。

由于后者不必强制实现专用接口,Repositories.getRepositoryFor(…) 只返回Optional<Object>,如果您想在存储库上实际做一些事情,这并没有太大帮助。 RepositoryInvokerFactory 允许您创建 RepositoryInvoker 实例,这些实例允许您显式调用存储库上的某些方法,而不管它们的实际声明方式。

@Component
@RequiredArgsConstructor
class SomeComponent {

  private final Repositories repositories;

  public <T> void someMethod(Class<T> type) {

    … = repositories.getEntityInformation(type);

    RepositoryInvokerFactory factory = new DefaultRepositoryInvokerFactory(repositories);
    RepositoryInvoker invoker = factory.getInvokerFor(type);
    Optional<T> entity = invoker.invokeFindById(4711);
  }
}

注意,如果您使用 Spring Data REST,Repositories 实例可用作 Spring Bean。如果您不简单地为它声明一个bean。它只需要ListableBeanFactory

Spring 数据 REST

使用图片中的 Spring Data REST 可能需要查找支持 URI 的特定路径段的存储库。这些额外的知识编码在RepositoryResourceMappings 中,可用于了解所访问的域类型:

RepositoryResourceMappings mappings = … // get injected

Optional<Class<?>> domainType = mappings.stream()
  .filter(metadata -> metadata.getPath().matches(pathSegment))
  .findFirst()
  .map(ResourceMetadata::getDomainType);

发现的类型现在可用于从Repositories 获取存储库实例。 Spring Data REST 还提供了一个预配置的 RepositoryInvokerFactory 实例,该实例应用了可能注册的自定义 EntityLookup 实例。 IE。使用它优于创建一个自己的,如上所示。

【讨论】:

  • 如果我没有关于实际域类的信息怎么办?我只有通过HttpServletRequest?? 的 URL REST 端点
  • 那么您必须找出如何将 URI 映射回您的域类型?除了你之外没有人知道哪些 URI 处理哪些实体。
  • 不是真的,我想要的是:给定一个 URI,向 spring 询问它将被调用的存储库(接口)(Spring 以某种方式知道这样的映射,因为它调用给定URI的正确存储库)...然后分析此类接口以查找我的自定义注释...
  • 如果您明确提到您似乎正在使用 Spring Data REST,那将会很有帮助。它在使用的标签之一中,但问题描述并没有揭示这一点。我已经相应地更新了答案。
  • 这个答案对我有用。我想通过添加来扩展它,您还可以通过使用存储库实例获取定义数据存储库的接口并要求为该域类定义的接口:repositories.getRepositoryInformationFor(type).getRepositoryInterface()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 2017-04-30
  • 2016-07-06
  • 2017-10-18
  • 2019-12-25
  • 1970-01-01
  • 2017-12-02
相关资源
最近更新 更多