Spring 数据剩余添加 Link 到根目录 - RepositoryLinksResource 无法转换为 Resource

Spring Data Rest Adding Link to Root - RepositoryLinksResource cannot be cast to Resource

我正在尝试将自定义 link 添加到我的 API 的根文档中,遵循以下答案: Custom response for root request int the Spring REST HATEOAS with both RepositoryRestResource-s and regular controllers

这是我的自定义资源处理器:

import org.springframework.data.rest.webmvc.RepositoryLinksResource;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.ResourceProcessor;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
import org.springframework.stereotype.Component;

@Component
public class CustomRootLinksResourceProcessor implements ResourceProcessor<RepositoryLinksResource> {

    @Override
    public RepositoryLinksResource process(RepositoryLinksResource resource) {
         Link link = ControllerLinkBuilder
                .linkTo(ControllerLinkBuilder
                        .methodOn(CustomerController.class)
                        .register(null))
                .withRel("registerCustomer");

        resource.add(link);

        return resource;
    }
}

但是,当我查询 API 时,我收到以下异常

LOGBACK:19:01:03.425 [http-nio-8080-exec-2] ERROR o.s.d.r.w.RepositoryRestExceptionHandler - org.springframework.data.rest.webmvc.RepositoryLinksResource cannot be cast to org.springframework.hateoas.Resource
java.lang.ClassCastException: org.springframework.data.rest.webmvc.RepositoryLinksResource cannot be cast to org.springframework.hateoas.Resource
    at org.springframework.hateoas.mvc.ResourceProcessorInvoker$DefaultProcessorWrapper.invokeProcessor(ResourceProcessorInvoker.java:224)
    at org.springframework.hateoas.mvc.ResourceProcessorInvoker.invokeProcessorsFor(ResourceProcessorInvoker.java:141)
    at org.springframework.hateoas.mvc.ResourceProcessorInvoker.invokeProcessorsFor(ResourceProcessorInvoker.java:124)
    at org.springframework.hateoas.mvc.ResourceProcessorHandlerMethodReturnValueHandler.handleReturnValue(ResourceProcessorHandlerMethodReturnValueHandler.java:113)
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:132)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)

我不确定我在这里做错了什么,因为检查 ResourceProcessorInvoker 的源代码似乎只有 ResourceSupport 的转换(RepositoryLinksResource 扩展,所以它应该没事的)。这是 spring 数据休息中的错误还是我的 CustomRootLinksResourceProcessor 有问题?

    @Override
    @SuppressWarnings("unchecked")
    public Object invokeProcessor(Object object) {
        return ((ResourceProcessor<ResourceSupport>) processor).process((ResourceSupport) object);
    }

所以我在调试器中逐步检查了 SDR 代码,结果发现异常是由另一个 ResourceProcessor 的调用引起的,看起来像这样:

@Component
public class CustomerResourceProcessorWrapper {
    @Bean
    public ResourceProcessor<Resource<Customer>> customerResourceProcessor() {

我对 Spring Data Rest 及其反射魔法还很陌生,但是用直接的 ResourceProcessor 替换错误的 CustomerResourceProcessorWrapper 声明为我解决了这个问题:

@Component
public class CustomerResourceProcessor implements ResourceProcessor<Resource<Customer>> {

    @Override
    public Resource<Customer> process(Resource<Customer> resource) {
    ...

我仍然很想知道这个包装器是什么以及为什么它不起作用... 使用 CustomerResourceProcessorWrapper 的相同代码工作正常,除非我添加 CustomRootLinksResourceProcessor

作为Sam mentioned (and all credit to him) "I think ResourceProcessor implementation must not be a lambda just like in the docs

我无法在文档中找到确切的参考资料,但这里有一个示例,以防其他人遇到这个问题。

这个有效:

@Bean
public ResourceProcessor<Resource<Invoice>> processor() {
    return new ResourceProcessor<Resource<Invoice>>() {
        @Override
        public Resource<Invoice> process(Resource<Invoice> resource) {
            resource.add(entityLinks.linkToSingleResource(Invoice.class, 1));
            return resource;
        }
    };
}

但这不是:

@Bean
public ResourceProcessor<Resource<Invoice>> processor() {
    return (Resource<Invoice> resource) -> {
        resource.add(entityLinks.linkToSingleResource(Invoice.class, 1));
        return resource;
    };
}