使用 Spring 的 REST 支持向应用程序添加 Atom 视图

工程 | Alef Arendsen | 2009 年 3 月 16 日 | ...

在 Spring 3.0 中,Spring MVC 将增强 REST 支持。本文描述了如何使用 REST 支持在简单示例应用程序之上实现 AtomView。按照此分步过程,了解使用 Spring MVC 中新的 REST 支持在简单应用程序之上实现 AtomView 是多么容易。

步骤 1:下载应用程序骨架

在本博客文章的底部附近,您将找到一个简单的下载文件,其中包含 Web 应用程序的骨架。在其中,您将找到此应用程序所需的所有 Spring 3.0 二进制文件,以及 Atom 功能所需的一些额外文件。Spring 二进制文件基于夜间构建,一旦 Spring 3.0 正式发布,可能会被最终构建取代。

接下来,在 Eclipse 中加载项目,使用“导入 > 将现有项目导入工作区”向导(从“文件”菜单)。该应用程序是一个简单的 Eclipse 动态 Web 项目,包含了 Spring MVC 设置的所有基础架构。因此,如果您熟悉 Spring MVC,这应该不是什么大问题。

步骤 2:审查应用程序的设置

在 /WEB-INF/web.xml 中,您将找到 Spring MVC DispatcherServlet 的定义。它从 /WEB-INF/rest-servlet.xml 文件中加载应用程序上下文。该文件反过来又包含一个组件扫描器,用于扫描 com.springsource.samples.rest 包中的 @Components(也包括 @Controllers)。

接下来,在 com.springsource.samples.rest 包中,您将找到一个包含两个控制器方法的 ContentController。


@Controller
public class ContentController {
	
	private List<SampleContent> contentList = new ArrayList<SampleContent>();
	
	@RequestMapping(value="/content.*", method=RequestMethod.GET)
	public ModelAndView getContent() {
		ModelAndView mav = new ModelAndView();
		mav.setViewName("content");
		mav.addObject("sampleContentList", contentList);
		return mav;
	}
	
	@RequestMapping(value="/content.html", method=RequestMethod.POST)
	public String addContent() {
		contentList.add(SampleContent.generateContent("Alef Arendsen", new Date()));
		return "redirect:content.html";
	}
}

第一个处理器返回 SampleContent 项的列表。第二个处理器通过使用 SampleContent.generateContent() 方法添加一个新的 SampleContent 项。第一个处理器响应 GET 请求,第二个处理器响应 POST 请求。这些方法本身已使用 @RequestMapping 注解进行注释以实现此目的。

在 rest-servlet.xml 应用程序上下文文件中,除了组件扫描器之外,您还会找到一个 ViewResolver,在本例中是一个 InternalResourceViewResolver。它将负责视图名称(在 getContent() 处理器的情况下为“content”)与 JSP 页面之间的转换。

将其部署到例如 Tomcat 后,您应该能够访问 https://:8080/spring-rest/rest。这将重定向您到 /rest/content,一个由处理器捕获的 URL。

步骤 3:实现 AtomView

为了实现 AtomView,我们将使用 Rome 项目,可从 https://rome.dev.java.net/ 获取。在应用程序的原始设置中,视图名称由视图解析器转换为 InternalResourceView 实例,在本例中将渲染 JSP。我们将创建我们自己的 View 接口的专用实例,而不是渲染 Atom 提要。

在 com.springsource.samples.rest 包中创建一个名为 SampleContentAtomView 的类,并粘贴以下代码。该代码使用了 Spring MVC 的 Atom 支持类和 Rome 项目中 Atom 提要的文档对象模型。


public class SampleContentAtomView extends AbstractAtomFeedView {

	@Override
	protected void buildFeedMetadata(Map<String, Object> model, Feed feed, HttpServletRequest request) {
		feed.setId("tag:springsource.com");
		feed.setTitle("Sample Content");
		@SuppressWarnings("unchecked")
		List<SampleContent> contentList = (List<SampleContent>)model.get("sampleContentList");
		for (SampleContent content : contentList) {
			Date date = content.getPublicationDate();
			if (feed.getUpdated() == null || date.compareTo(feed.getUpdated()) > 0) {
				feed.setUpdated(date);
			}
		}
	}

	@Override
	protected List<Entry> buildFeedEntries(Map<String, Object> model,
			HttpServletRequest request, HttpServletResponse response) throws Exception {

		@SuppressWarnings("unchecked")
		List<SampleContent> contentList = (List<SampleContent>)model.get("sampleContentList");
		List<Entry> entries = new ArrayList<Entry>(contentList.size());

		for (SampleContent content : contentList) {
			Entry entry = new Entry();
			String date = String.format("%1$tY-%1$tm-%1$td", content.getPublicationDate());
			// see http://diveintomark.org/archives/2004/05/28/howto-atom-id#other
			 entry.setId(String.format("tag:springsource.com,%s:%d", date, content.getId()));
			entry.setTitle(String.format("On %s, %s wrote", date, content.getAuthor()));
			entry.setUpdated(content.getPublicationDate());

			Content summary = new Content();
			summary.setValue(content.getText());
			entry.setSummary(summary);
			
			entries.add(entry);
		}

		return entries;

	}
}

步骤 4:设置内容协商

骨架 Web 应用程序已经提供了 HTML 视图,现在我们也实现了生成 Atom 提要的视图。我们需要做的最后一件事是确保 Atom 提要的请求实际上将使用 SampleContentAtomView 进行渲染,并且在请求 HTML 视图时将渲染 JSP。

在一个完美的世界中,客户端会使用 Accept HTTP 标头请求其首选的特定表示。Accept HTTP 标头(由 HTTP 规范定义)可以包含一个或多个媒体类型,并且应由浏览器(或任何 HTTP 客户端)发送,以指示其首选的表示类型。例如,Atom 提要的适当媒体类型将是“application/atom+xml”,而 HTML 视图可能只发送“text/html”或“text/xhtml”作为 Accept 标头。然而,这存在一个小问题。浏览器通常具有固定的媒体类型集,它们作为 Accept HTTP 标头发送,并且无法(除了使用 JavaScript)修改浏览器发送的 Accept 标头。这就是为什么文件扩展名是向服务器指示您想要哪种表示的良好替代方案。

Spring 3.0 具有 ContentNegotiatingViewResolver,它可以同时使用扩展名和 Accept 标头。在确定了适当的媒体类型后,它会委托给一组其他视图解析器来为我们完成此操作。以下内容需要粘贴到 rest-servlet.xml 中才能使其工作。如您所见,ContentNegotiatingViewResolver 将委托给 BeanNameViewResolver(如果需要,解析为 SampleContentAtomView)或 InternalResourceViewResolver。顺便说一下,下面的代码片段应该替换您 rest-servlet.xml 文件中已配置的 InternalResourceViewResolver。

ContentNegotiatingViewResolver 首先查看文件扩展名,然后使用 Accept 标头(这在一定程度上是可自定义的)。我们必须将适当的扩展名映射到适当的媒体类型。在此示例中,我们将 .html 映射到媒体类型 text/html,并将 .atom 映射到 application/atom+xml。这将确保渲染适当的视图。

如果 .atom 请求进入,ContentNegotiatingViewResolver 将查找与 application/atom+xml 媒体类型匹配的视图。如果 .html 请求进入,视图解析器将查找渲染媒体类型为 text/html 的内容的视图。


<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"/>
		</map>
	</property>
	<property name="viewResolvers">
		<list>
			<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
			<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
				<property name="prefix" value="/WEB-INF/jsp/"/>
				<property name="suffix" value=".jsp"/>
			</bean>
		</list>
	</property>
</bean>

<bean id="content" class="com.springsource.samples.rest.SampleContentAtomView"/>

将其放入应用程序上下文后,重启服务器应该就可以解决问题。访问 https://:8080/spring-rest/rest/content.html 查看所有内容项并生成新的内容项。访问 https://:8080/spring-rest/rest/content.atom 订阅 Atom 提要。

我希望这篇小博客文章向您展示了向应用程序添加 Atom 提要可以多么简单。除了 Atom,Spring 还具有用于渲染 PDF 和 Excel 文件、JSON 表示和 XML 文档的视图支持类。查看它们并告诉我们您的想法!

下载

如所承诺的,这里是下载。请注意,这些项目基于 Spring 的夜间构建。有关 Spring 3.0 的最新版本,请务必查看 www.springsource.org

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看所有