在 Spring-MVC 控制器中支持多种内容类型
Posted
技术标签:
【中文标题】在 Spring-MVC 控制器中支持多种内容类型【英文标题】:Supporting multiple content types in a Spring-MVC controller 【发布时间】:2011-05-23 03:56:27 【问题描述】:Rails 控制器可以很容易地支持多种内容类型。
respond_to do |format|
format.js render :json => @obj
format.xml
format.html
end
美丽。在一个控制器操作中,我可以很容易地响应多种内容类型,并且对于我希望呈现的内容具有很大的灵活性,无论是模板、我的对象的序列化形式等。
我可以在 Spring-MVC 中做类似的事情吗? Spring中支持多种内容类型的标准是什么?我见过涉及视图解析器的解决方案,但这看起来很难管理,特别是如果我想支持除了 xhtml 和 xml 之外的 JSON。
欢迎提出任何建议,但更简单、更优雅的解决方案将受到更多赞赏;)
编辑
如果我断言视图解析器难以管理是不正确的,请随时纠正我并提供示例。最好是可以返回 xml、xhtml 和 JSON 的。
【问题讨论】:
【参考方案1】:这里是工作示例控制器,它根据请求标头“Content-Type”呈现 JSON 和 HTML。
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class PersonService
@RequestMapping(value = "/persons/userId", method = RequestMethod.GET)
public ResponseEntity<?> getPersonByName(@RequestHeader("Content-Type") String contentMediaType,
@PathVariable("userId") String userId,@RequestParam("anyParam") boolean isAscending) throws IOException
Person person = getPersonById(userId);
if (isJSON(contentMediaType))
return new ResponseEntity<Person>(person, HttpStatus.OK);
return new ResponseEntity("Your HTML Goes Here", HttpStatus.OK);
//Note: Above you could use any HTML builder framework, like HandleBar/Moustache/JSP/Plain HTML Template etc.
private static final boolean isJSON(String contentMediaType)
if ("application/json".equalsIgnoreCase(contentMediaType))
return true;
return false;
【讨论】:
【参考方案2】:在 Spring 3 中,您想使用 org.springframework.web.servlet.view.ContentNegotiatingViewResolver
。
它需要一个媒体类型列表和ViewResolvers
。来自Spring docs:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
<bean id="content" class="com.springsource.samples.rest.SampleContentAtomView"/>
控制器:
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class BlogsController
@RequestMapping("/blogs")
public String index(ModelMap model)
model.addAttribute("blog", new Blog("foobar"));
return "blogs/index";
您还需要包含 Jackson JSON jar。
【讨论】:
是否像 Rails 一样简单和“漂亮”?不。但按照 Java 标准,可能与我们将得到的一样好。 P.S. - 我只测试了 HTML 和 JSON 内容类型。我现在正在研究原子。 @Todd:谢谢!不过这有点令人困惑。如果我返回字符串“blogs/index”,我的任何视图如何与我的模型交互?我期待它返回一个 ModelAndView 对象,我们会将字符串“blogs/index”传递给该对象,然后如果客户端请求 JSON,Spring 将忽略该字符串并通过 Jackson 序列化该对象。你能解释一下你的例子是如何工作的吗? @Samo,博客模型在模型中设置,传入(通过引用)并作为“博客”提供给视图。视图“blogs/index”映射到“WEB-INF/jsp/blogs/index.jsp”。是的,当我将 .json 添加到我的 url 时,“/blogs.json”视图被忽略并打印"blog":"name":"foobar"
@Samo,你也可以使用 ModelAndView。我刚试过。 @RequestMapping("/blogs") public ModelAndView index() Blog blog = new Blog("foobar"); ModelAndView model = new ModelAndView("blogs/index", "blog", blog);返回模型; 以上是关于在 Spring-MVC 控制器中支持多种内容类型的主要内容,如果未能解决你的问题,请参考以下文章