Spring 3.2 @ResponseBody没有使用Model返回值 [英] Spring 3.2 @ResponseBody not working with a Model return value

查看:600
本文介绍了Spring 3.2 @ResponseBody没有使用Model返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下映射适用于Spring 3.1,但不适用于Spring 3.2。
我得到404错误,并解释了table.jsp文件丢失。相反,模型应序列化为json。

The following mapping was working with Spring 3.1, but is not working with Spring 3.2. I get a 404 error with an explanation that the table.jsp file is missing. Instead, the "model" should be serialized to json.

    @RequestMapping(value = {"/table"}, method = RequestMethod.GET, produces="application/json")
    public @ResponseBody Model table(Model model, @RequestParam(defaultValue = "1") Integer pg) {
        fillListModel(model, pg);
        return model;
    }

有没有办法解决这个问题而不会对现有代码产生任何影响?

Is there a way to fix this without any impact to the existing code?

以下代码正常工作:

    @RequestMapping(value = {"/table"}, method = RequestMethod.GET, produces="application/json")
    public @ResponseBody Model table(Model model, @RequestParam(defaultValue = "1") Integer pg) {
        return new User();
    }

所以看起来Spring无法识别模型的返回目的是为了转为json而不是在视图中呈现。

So it looks like Spring cannot recognize that the model is returned with a purpose to be turned into json instead to be rendered in a view.

推荐答案

这是Spring 3.2+(我不知道)的结果记住它是如何处理 @RequestMapping 方法的返回值。 Spring使用 HandlerMethodReturnValueHandler 以解决应如何处理返回值的方法。通过javadoc也可以看到不同的类型。

This is a consequence of how Spring 3.2+ (I don't remember how 3.1 does it) handles @RequestMapping methods' return values. Spring uses instances of type HandlerMethodReturnValueHandler to resolve how the value returned should be handled. Go through the javadoc too see the different types.

配置MVC环境时,如果使用默认的 @EnableWebMVC < mvc:annotation-driven> ,Spring按特定顺序注册这些实例。这发生在 RequestMappingHandlerAdapter#getDefaultReturnValueHandlers()方法中,如下所示

When you configure your MVC environment, if you use the default @EnableWebMVC or <mvc:annotation-driven>, Spring registers these instances in a specific order. This happens in the RequestMappingHandlerAdapter#getDefaultReturnValueHandlers() method as shown below

private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
    List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();

    // Single-purpose return value types
    handlers.add(new ModelAndViewMethodReturnValueHandler());
    handlers.add(new ModelMethodProcessor());
    handlers.add(new ViewMethodReturnValueHandler());
    handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
    handlers.add(new CallableMethodReturnValueHandler());
    handlers.add(new DeferredResultMethodReturnValueHandler());
    handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));

    // Annotation-based return value types
    handlers.add(new ModelAttributeMethodProcessor(false));
    handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));

    // Multi-purpose return value types
    handlers.add(new ViewNameMethodReturnValueHandler());
    handlers.add(new MapMethodProcessor());

    // Custom return value types
    if (getCustomReturnValueHandlers() != null) {
        handlers.addAll(getCustomReturnValueHandlers());
    }

    // Catch-all
    if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
        handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
    }
    else {
        handlers.add(new ModelAttributeMethodProcessor(true));
    }

    return handlers;
}

当你的方法返回一个值时,Spring会遍历这些处理程序,调用它们的 supportsReturnType()方法并选择它找到的第一个返回 true 的方法。

When your method returns a value, Spring iterates through these handlers, calling their supportsReturnType() method and picking the first it finds that returns true.

在这种情况下, ModelMethodProcessor 处理模型返回值具有更高的优先级(之前已注册) RequestResponseBodyMethodProcessor ,它处理 @ResponseBody

In this case, the ModelMethodProcessor which handles Model return values has higher priority (is registered before) the RequestResponseBodyMethodProcessor which handles @ResponseBody.

因此,您无法返回模型并通过<$ c将其转换为JSON $ C> @ResponseBody 。在我看来,你根本不应该这样做。 DispatcherServlet 堆栈的大多数部分都可以访问 Model ,因此许多模块可以添加/删除您可能没有的属性想要在最终的JSON中。

As such, you can't return a Model and have it be converted to JSON through the @ResponseBody. In my opinion, you shouldn't do this at all. The Model is accessible to most parts of the DispatcherServlet stack and therefore many modules can add/remove attributes which you may not want in the final JSON.

在你的第二个例子中使用像你一样的DTO。

Just use a DTO like you have in your second example.

这篇关于Spring 3.2 @ResponseBody没有使用Model返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆