因此,我们在Spring应用程序中已经到了这一点,我们需要决定如何处理视图和内容协商。以前,我们只支持端点中的一种特定内容类型。
我将抛出我认为的三种方法。
我的问题:哪一项通常被认为是最佳做法/维护量最少?我们的目标是在我们的应用程序中遵循一个坚实的惯例,如果需要,可以在需要时提供灵活性。
第一种方法:
使用ContentNegotiatingViewResolver。这将涉及在servlet文件中定义的映射...在控制器中,每个控制器操作都需要使用一些魔术字符串在地图中显式设置对象。控制器操作将返回一个字符串,该字符串引用模板名称...类似于以下内容:
@RequestMapping(value = "/someMapping/source", method = RequestMethod.GET)
public String foo(Model model)
{
// more stuff here
model.addAttribute(SOME_MODEL_KEY, new ArrayList<String>() { "hello world"});
return "someDummyJsonString";
}
缺点:
查看解析器看起来有点笨拙......它们有优先级,你需要经常覆盖它们等等。另外,我不喜欢用于引用模板/视图bean名称的“魔术字符串”的想法。
第二种方法:
我认为这是Spring 3.0中的新功能,但在RequestMapping
中你可以匹配标题...所以你可以在Accept标题上匹配,如下所示:
@RequestMapping(value="/someMapping", method = RequestMethod.GET, headers="Accept=application/json")
public @ResponseBody SomeBar foo()
{
// call common controller code here
return buildBar();
}
@RequestMapping(value="/someMapping", method = RequestMethod.GET, headers="Accept=text/xml")
public String foo(Model model)
{
model.addAttribute("someModelName", this.buildBar());
return "someTemplateNameProcessedByViewResolver";
}
SomeBar buildBar()
{
return new SomeBar();
}
缺点:
可能不够灵活吗?我不确定,但我认为我非常喜欢headers
方法...我已经看到其他框架(RESTLet,Rails)使用类似的东西。
第三种方法:
第三种方法涉及创建一个自定义View
,它将根据Accept
标头协商内容,并通过适当的方法抛出模型。此内容协商视图必须知道模板,并加载模板等。
@RequestMapping(value="/someMapping", method = RequestMethod.GET, headers="Accept=text/xml")
public View foo()
{
SomeBar bar = new SomeBar();
ContentNegotiatingView view = new ContentNegotiatingView(bar, "templateName");
return return view;
}
缺点:
在这种情况下,视图似乎做得太多了...视图将查看标题,并设置响应主体本身。它可能还需要设置http状态。
所以,对不起文字的墙,让我知道你对此的看法。感谢