3

以前的设计

我有一个如下构建的 Spring 控制器:

@RequestMapping(value = "/rest/funf/{datatype}", method = RequestMethod.GET)
public ModelAndView getFunfData(@PathVariable("datatype") String dataType,
        WebRequest request) throws HttpException {

我还有一个HandlerInterceptorAdapter执行预处理和后处理(根据策略修改返回的模型)。后处理处理程序的签名如下

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

它实际上运作良好。REST API 返回了一个结构不完善的 JSON 有效负载,但至少拦截器(一个策略执行点)能够从模型中匿名(剥离用户个人数据)并替换它。

关键是,使用旧设计,我能够在将响应发送到输出之前检索响应,对其进行修改并将其重新注入到ModelAndView实例中。为简洁起见,无需发布代码。

新设计

现在我发现了一种新设计,可以帮助我克服响应结构中的缺陷。

当我有return new ModelAndView(jacksonView_instance, "data", dataToConvertToJson)它的结构像

{
    "data": {
        "myAttr1":"myVal1"
     }
}

当接收程序想要将有效负载转换为 JSON 时,这很糟糕。所以我发现

@RequestMapping(value = "/rest/funf/{datatype}", method = RequestMethod.GET, produces = { "application/json" })
    public @ResponseBody
    Object[] getFunfData(@PathVariable("datatype") String dataType,
            WebRequest request) throws HttpException {

这个简化的代码有点,最重要的是使响应结构良好,比如

{
    "myAttr1":"myVal1"
}

REST 设计合同完全可以,但是

问题

现在 HandlerInterceptor 将无法再检索模型以及我从 API 返回的对象(它是一个与FUNF相关的 API,用于处理记录在移动设备上的个人数据,甚至是敏感数据)。

所以如果我需要匿名记录,我不能像以前那样在拦截器中做到这一点

解决方法

我意识到我可以杀死拦截器并在 API 中执行策略执行权,但这不是一个很好的设计,即使在当前执行授权preHandle和义务执行的 PEPpostHandle是自动实例化的 Spring 对象。在处理多个 API 以及中期更改/扩展 PEP 实现的可能性时,在 API 中复制和粘贴代码是一个坏主意。

无论如何,让我们在充分解释上下文之后提出一个直截了当的问题

问题是

给定一个通用 Spring MVC API,它返回一个由内容协商器处理的对象

@RequestMapping(value = "/path/{variable}", method = RequestMethod.GET)
public @ResponseBody Object api() {

如何在外部类中拦截返回的对象以对其进行修改?(例如,替换为要返回给客户端的新对象实例)

4

1 回答 1

2

Looks like this is not possible in Spring MVC. I have just seen the code in a debug session.

When you use ModelAndView, Spring MVC stores the MaV in a variable that lives till postHandle and then is written in response body.

Instead, when you use @ResponseBody and return value that value is handled directly in the invocation cycle, using a MessageConverter to be written to the response.

Since the response is a one-way network stream, it's too late for intercepting it.

The solution should be based on a different approach than the handlers, like AOP interceptors applied directly to controller methods.

于 2013-02-05T11:28:08.620 回答