【发布时间】:2017-06-08 15:46:27
【问题描述】:
我有一些旧版控制器将一些数据放入Model 对象(Thymeleaf 模板需要)。
现在我必须在 REST 服务中返回与 JSON 相同的数据。
出于这些目的,我将数据准备块包装到单独的方法中,以便在两个地方使用:用于 thymeleaf 模板的旧方法和新方法:
@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index(Model model) {
prepareIndexModel(model);
return "index";
}
@RequestMapping(value = "/index/model", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Map<String, Object> indexModel(Model model) {
prepareIndexModel(model);
return model.asMap();
}
private void prepareIndexModel(Model model) {
model.addAttribute("prop1", ...);
...
}
但是,当我尝试通过 GET /index/model 访问时,我收到以下错误:
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "/WEB-INF/templates/index/model.html")
所以它只是认为我的方法不是 REST 方法。我猜,这是因为方法实际上返回了实现两个接口的ExtendedModelMap 类的实例:Model 和Map。
因此,将/index/model 方法更改为:
@RequestMapping(value = "/index/model", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Map<String, Object> indexModel(Model model) {
prepareIndexModel(model);
return new LinkedHashMap<>(model.asMap());
}
一切都按预期开始:GET /index/model 返回我想要的 JSON。所以基本上我只是把模型包装成LinkedHashMap。
我的问题是:这是一个特定的行为还是只是一个错误?我希望通过使用@ResponseBody 注释来注释方法, Spring 应该忽略返回对象是Model 的实例这一事实。不应该吗?
更新:@Sotirios Delimanolis 提供了指向非常相似的question 的链接,该链接大约是 3.2 版。但我的问题不是关于为什么,而是 Spring 的 bug 还是它在文档中的某个位置指定?
UPDATE-2:还请注意,在链接的问题中,方法具有Model 返回类型,并且描述了它的行为。就我而言,我有 Map<...> 返回类型,我认为是什么让这种行为变得奇怪且不一致!
【问题讨论】:
-
链接的副本是在 Spring 仍在 3.x 上的时候。答案仍然适用。
getDefaultReturnValueHandlers以相同的顺序注册或多或少相同的HandlerMethodReturnValueHandlers,即。Model的一个在@ResponseBody的一个之前。此外,asMap返回一个同样实现了Model的Map。 -
1) 我使用的是 Spring 4。 2) 你仔细阅读我的问题了吗?我已经明确强调了
model.asMap()返回的对象,其类也实现了Model -
正如我在副本中的回答所解释的那样,处理
Model的ModelMethodProcessor在处理@ResponseBody的RequestResponseBodyMethodProcessor之前起作用。 -
嗯,考虑一下。
-
在我看来,这是
supportsReturnType的文档中的一个错误,而不是您目睹的行为。
标签: java spring spring-mvc model-view-controller