Spring 3.2 @ResponseBody没有使用Model返回值 [英] Spring 3.2 @ResponseBody not working with a Model return value
问题描述
以下映射适用于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屋!