Java 如何在Spring中为REST服务在HandlerInterceptor中填充ModelAndView

Java 如何在Spring中为REST服务在HandlerInterceptor中填充ModelAndView,java,spring,spring-mvc,concurrency,Java,Spring,Spring Mvc,Concurrency,我正在使用Spring框架构建一个RESTfull服务 在控制器中处理请求后,我需要根据响应类型向响应添加自定义Cookie @Controller public class SomeController { ... @RequestMapping(method = RequestMethod.GET, value = MY_PROFILE, produces = PRODUCES) public @ResponseBody Some myProfile(@Reque

我正在使用Spring框架构建一个RESTfull服务

在控制器中处理请求后,我需要根据响应类型向响应添加自定义Cookie

@Controller
public class SomeController {

    ...

    @RequestMapping(method = RequestMethod.GET, value = MY_PROFILE, produces = PRODUCES)
    public @ResponseBody Some myProfile(@RequestBody() A a) {
        ...
    }

    ...
}
但当它到达我的拦截器时

public class SomeIntercepter implements HandlerInterceptor {

    ...

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    ...

}
ModelAndView为空,我只能处理请求和响应

所以我有两个问题:

  • 有没有一种方法可以让Spring使用数据填充ModelAndView,而不使用HttpServletResponseHttpEntityModelAndView显式地运行,从而保持控制器的完整性?(我不打算使用ModelAndView添加Cookie,我只需要知道拦截器中的响应对象,并将Cookie添加到HttpServletResponse。)
  • 我想用ThreadLocal解决这个问题,但据我所知,在异步处理的情况下,这会停止。是否有一个经验证的ThreadLocal解决方案,在我决定切换到异步处理时不会中断
  • 示例用例:

    假设我正在进行A/B测试,我的UI根据响应中的Cookie呈现不同的效果。
    我希望有一个地方,基于返回对象,我可以指定这个Cookie。

    @ResponseBody
    的特殊之处在于它告诉Spring响应已经被处理(或者应该用返回值处理)。在这种情况下,不需要
    ModelAndView
    ,因为没有要渲染的视图。因此MVC堆栈不会创建一个
    模型和视图
    ,也不会向
    HandlerInterceptor
    提供任何模型和视图。基本上,在调用
    postHandle
    时,响应已经刷新,您将无法编写任何cookie。而且,在任何情况下,
    ModelAndView
    都不是添加cookie的合适位置。
    HttpServletResponse
    是。

    当您使用
    @ResponseBody
    时,Spring不使用模型,您甚至没有在控制器方法中声明它,无论如何它都没有意义


    但您可以始终使用请求属性将数据从控制器传递到拦截器,拦截器将能够在其
    postHandle
    方法中使用它来决定如何处理响应和Cookie。

    那么,我如何在控制器之外添加Cookie呢?我不打算将ModelAndView用于Cookie,我只需要知道拦截器中的响应对象,并将Cookie添加到HttpServletResponse@mavarazy你以前能做吗?在
    预处理中
    ?您可以在
    过滤器中执行此操作吗?请注意,您可以包装
    HttpServletResponse
    ,使其无法立即刷新响应(您可以在
    过滤器中执行此操作
    )。不,我只能在处理后根据结果执行此操作。这就是为什么我想到了ThreadLocal,这样我就可以在同一个线程中共享响应,假设拦截器只能在同一个线程中运行。@mavarazy这将是一个问题,因为
    HandlerInterceptor
    比处理返回值的
    RequestResponseBodyMethodProcessor
    运行得晚(并将其写入响应)。一种可能的解决方案是重写该类并将其注册为
    HandlerMethodReturnValueHandler
    ,以便它添加额外的Cookie。@mavarazy或者,您可以使用自定义注释创建
    HandlerMethodReturnValueHandler
    的独立子类型,该注释通过包装
    RequestResponseByme执行类似操作这些处理器