【发布时间】:2011-05-23 04:44:44
【问题描述】:
所以,在 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 状态。
所以,对于文字墙感到抱歉,让我知道您对此的看法。谢谢
【问题讨论】:
标签: java spring spring-mvc