如何在spring-hateos项目中使用ResourceProcessorHandlerMethodReturnValueHandler

时间:2017-12-05 16:26:43

标签: spring-mvc spring-boot spring-hateoas

使用spring-data-rest时,会对从控制器返回的Resource个类进行后处理(例如RepositoryRestControllers)。在后期处理中调用正确的ResourceProcessor

负责此操作的班级是ResourceProcessorHandlerMethodReturnValueHandler,它是spring-hateoas的一部分。

我现在有一个仅使用spring-hateoas的项目,我想知道如何在这种情况下配置ResourceProcessorHandlerMethodReturnValueHandler。看起来它的自动配置部分仍然驻留在spring-data-rest

有关如何在ResourceProcessorHandlerMethodReturnValueHandler上下文中启用spring-hateoas的任何提示?

1 个答案:

答案 0 :(得分:0)

我最近也一直在研究这个问题,而关于如何实现这一目标的文档不存在。如果创建类型为ResourceProcessorInvokingHandlerAdapter的bean,则似乎会丢失自动配置的RequestMappingHandlerAdapter及其所有功能。因此,我想避免使用此bean或丢失WebMvcAutoConfiguration,因为我真正想要的只是ResourceProcessorHandlerMethodReturnValueHandler

您不能只通过ResourceProcessorHandlerMethodReturnValueHandler添加WebMvcConfigurer.addReturnValueHandlers,因为我们要做的实际上是覆盖整个列表,就像ResourceProcessorInvokingHandlerAdapter.afterPropertiesSet中发生的一样:

@Override
public void afterPropertiesSet() {

    super.afterPropertiesSet();

    // Retrieve actual handlers to use as delegate
    HandlerMethodReturnValueHandlerComposite oldHandlers = getReturnValueHandlersComposite();

    // Set up ResourceProcessingHandlerMethodResolver to delegate to originally configured ones
    List<HandlerMethodReturnValueHandler> newHandlers = new ArrayList<HandlerMethodReturnValueHandler>();
    newHandlers.add(new ResourceProcessorHandlerMethodReturnValueHandler(oldHandlers, invoker));

    // Configure the new handler to be used
    this.setReturnValueHandlers(newHandlers);
}

因此,在没有更好的解决方案可用的情况下,我添加了BeanPostProcessor来处理在现有RequestMappingHandlerAdapter上设置处理程序列表的问题:

@Component
@RequiredArgsConstructor
@ConditionalOnBean(ResourceProcessor.class)
public class ResourceProcessorHandlerMethodReturnValueHandlerConfigurer implements BeanPostProcessor {

    private final Collection<ResourceProcessor<?>> resourceProcessors;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {

        if (bean instanceof RequestMappingHandlerAdapter) {

            RequestMappingHandlerAdapter requestMappingHandlerAdapter = (RequestMappingHandlerAdapter) bean;

            List<HandlerMethodReturnValueHandler> handlers =
                    requestMappingHandlerAdapter.getReturnValueHandlers();

            HandlerMethodReturnValueHandlerComposite delegate =
                    handlers instanceof HandlerMethodReturnValueHandlerComposite ?
                            (HandlerMethodReturnValueHandlerComposite) handlers :
                            new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);

            requestMappingHandlerAdapter.setReturnValueHandlers(Arrays.asList(
                    new ResourceProcessorHandlerMethodReturnValueHandler(delegate,
                            new ResourceProcessorInvoker(resourceProcessors))));

            return requestMappingHandlerAdapter;
        }

        else return bean;
    }
}

到目前为止,这似乎一直有效...