HandlerInterceptorAdapter,JSON编码和后处理响应

时间:2013-02-05 10:52:31

标签: java spring rest spring-mvc

以前的设计

我有一个如下构建的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执行授权的PEP和{{1}中的义务执行当前是一个自动实例化的Spring对象。在处理多个API时,在API中复制和粘贴代码是一个坏主意,并且在中期可能会更改/扩展PEP实现。

无论如何,在完整地解释上下文后,让我们提出一个直接的问题

问题是

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

postHandle

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

1 个答案:

答案 0 :(得分:2)

在Spring MVC中看起来这是。我刚看到调试会话中的代码。

当你使用ModelAndView时,Spring MVC将MaV存储在一个直到postHandle的变量中,然后写在响应体中。

相反,当您使用@ResponseBody并返回值时,该值将在调用周期中直接处理,并使用MessageConverter写入响应。

由于响应是单向网络流,因此拦截它为时已晚。

解决方案应基于与处理程序不同的方法,例如AOP 拦截器直接应用于控制器方法。