[英]Spring 3.2 @ResponseBody not working with a Model return value
The following mapping was working with Spring 3.1, but is not working with Spring 3.2. 以下映射适用于Spring 3.1,但不适用于Spring 3.2。 I get a 404 error with an explanation that the table.jsp file is missing.
我收到404错误,并说明table.jsp文件丢失。 Instead, the "model" should be serialized to json.
相反,“模型”应序列化为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? 有没有办法解决此问题而又不影响现有代码?
The following code works fine: 以下代码可以正常工作:
@RequestMapping(value = {"/table"}, method = RequestMethod.GET, produces="application/json")
public @ResponseBody Model table(Model model, @RequestParam(defaultValue = "1") Integer pg) {
return new User();
}
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不能识别出返回该模型的目的是将其转换为json而不是呈现在视图中。
This is a consequence of how Spring 3.2+ (I don't remember how 3.1 does it) handles @RequestMapping
methods' return values. 这是Spring 3.2+(我不记得它是如何做到的)如何处理
@RequestMapping
方法的返回值的结果。 Spring uses instances of type HandlerMethodReturnValueHandler
to resolve how the value returned should be handled. Spring使用
HandlerMethodReturnValueHandler
类型的实例来解决应如何处理返回的值。 Go through the javadoc too see the different types. 遍历javadoc也可以看到不同的类型。
When you configure your MVC environment, if you use the default @EnableWebMVC
or <mvc:annotation-driven>
, Spring registers these instances in a specific order. 当您配置MVC环境时,如果使用默认的
@EnableWebMVC
或<mvc:annotation-driven>
,Spring将以特定顺序注册这些实例。 This happens in the RequestMappingHandlerAdapter#getDefaultReturnValueHandlers()
method as shown below 发生在
RequestMappingHandlerAdapter#getDefaultReturnValueHandlers()
方法中,如下所示
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;
}
When your method returns a value, Spring iterates through these handlers, calling their supportsReturnType()
method and picking the first it finds that returns true
. 当您的方法返回值时,Spring遍历这些处理程序,调用它们的
supportsReturnType()
方法,并选择第一个发现返回true
。
In this case, the ModelMethodProcessor
which handles Model
return values has higher priority (is registered before) the RequestResponseBodyMethodProcessor
which handles @ResponseBody
. 在这种情况下,处理
Model
返回值的ModelMethodProcessor
具有更高的优先级(在之前注册),该RequestResponseBodyMethodProcessor
处理@ResponseBody
。
As such, you can't return a Model
and have it be converted to JSON through the @ResponseBody
. 因此,您无法返回
Model
并通过@ResponseBody
将其转换为JSON。 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. 该
Model
可供DispatcherServlet
堆栈的大部分访问,因此许多模块可以添加/删除最终JSON中可能不需要的属性。
Just use a DTO like you have in your second example. 就像在第二个示例中一样使用DTO。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.