使用 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 二进制文件基于 nightly build,一旦 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://127.0.0.1:8080/spring-rest/rest。这将重定向到 /rest/content,这是处理程序获取的 URL。

步骤 3:实现 AtomView

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

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


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 Feed 的视图。我们需要做的最后一件事是确保对 Atom Feed 的请求实际上将使用 SampleContentAtomView 进行呈现,并且在请求 HTML 视图时将呈现 JSP。

在理想情况下,客户端将使用 Accept HTTP 标头请求其首选的特定表示形式。Accept HTTP 标头(如 HTTP 规范中所定义)可以采用一种或多种媒体类型,并且应由浏览器(或任何 HTTP 客户端)发送,以指示其首选的表示形式类型。例如,Atom Feed 的适当媒体类型为“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://127.0.0.1:8080/spring-rest/rest/content.html 查看所有内容项并生成新内容项。转到 https://127.0.0.1:8080/spring-rest/rest/content.atom 订阅 Atom Feed。

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

下载

如承诺的那样,以下是下载文件。请注意,这些项目基于 Spring 的 nightly build。对于 Spring 3.0 的较新版本,请务必查看 www.springsource.org

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

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

了解更多

获得支持

Tanzu Spring 在一个简单的订阅中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

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

查看全部